main.pas

来自「FIR引擎最新源码+注册」· PAS 代码 · 共 1,441 行 · 第 1/3 页

PAS
1,441
字号
  Socket: TCustomWinSocket);
var
  sRecvMsg: string;
begin
  sRecvMsg := Socket.ReceiveText;
  ClientSockeMsgList.Add(sRecvMsg);
end;

procedure TFrmMain.SendTimerTimer(Sender: TObject);
var
  nIndex: Integer;
  UserSession: pTUserSession;
begin
  if ServerSocket.Active then begin
    n456A30 := ServerSocket.Socket.ActiveConnections;
  end;
  if boSendHoldTimeOut then begin
    LbHold.Caption := IntToStr(n456A30) + '#';
    if (GetTickCount - dwSendHoldTick) > 3 * 1000 then boSendHoldTimeOut := False;
  end else begin
    LbHold.Caption := IntToStr(n456A30);
  end;
  if boGateReady and (not boKeepAliveTimcOut) then begin
    for nIndex := 0 to GATEMAXSESSION - 1 do begin
      UserSession := @g_SessionArray[nIndex];
      if UserSession.Socket <> nil then begin
        if (GetTickCount - UserSession.dwUserTimeOutTick) > 60 * 60 * 1000 then begin
          UserSession.Socket.Close;
          UserSession.Socket := nil;
          UserSession.SocketHandle := -1;
          UserSession.MsgList.Clear;
          UserSession.sRemoteIPaddr := '';
        end;
      end;
    end;
  end;
  if not boGateReady and (boServiceStart) then begin
    if (GetTickCount - dwReConnectServerTick) > 1000 {30 * 1000} then begin
      dwReConnectServerTick := GetTickCount();
      ClientSocket.Active := False;
      ClientSocket.Port := ServerPort;
      ClientSocket.Host := ServerAddr;
      ClientSocket.Active := True;
    end;
  end;
end;

procedure TFrmMain.TimerTimer(Sender: TObject);
var
  I: Integer;
begin
  if ServerSocket.Active then begin
    if g_boClearTempList then begin
      if GetTickCount - m_dwAttackTick > 1000 * g_dwClearTempList then begin
        m_nAttackCount := 0;
        if TempBlockIPList <> nil then begin
          TempBlockIPList.Lock;
          try
            for I := 0 to TempBlockIPList.Count - 1 do begin
              Dispose(pTSockaddr(TempBlockIPList.Items[I]));
            end;
            TempBlockIPList.Clear;
          finally
            TempBlockIPList.UnLock;
          end;
        end;
      end;
    end;

    if g_boReliefDefend then begin
      if (GetTickCount - m_dwAttackTick > 1000 * g_dwClearTempList) and (m_nAttackCount = 0) then begin
        if nAttackLevel <> nUseAttackLevel then nAttackLevel := nUseAttackLevel;
        if BlockMethod <> UseBlockMethod then BlockMethod := UseBlockMethod;
      end;
    end;

    if m_nAttackCount > 0 then begin
      StatusBar.Panels[3].Text := '攻击计次:' + IntToStr(m_nAttackCount);
    end;

    StatusBar.Panels[0].Text := IntToStr(ServerSocket.Port);
    if boSendHoldTimeOut then
      StatusBar.Panels[2].Text := IntToStr(nSessionCount) + '/#' + IntToStr(ServerSocket.Socket.ActiveConnections)
    else
      StatusBar.Panels[2].Text := IntToStr(nSessionCount) + '/' + IntToStr(ServerSocket.Socket.ActiveConnections);
  end else begin
    StatusBar.Panels[0].Text := '????';
    StatusBar.Panels[2].Text := '????';
  end;
  Label2.Caption := IntToStr(dwDecodeMsgTime);
  if not boGateReady then begin
    StatusBar.Panels[1].Text := '---]    [---';
    //StatusBar.Panels[1].Text := '未连接';
  end else begin
    if boKeepAliveTimcOut then begin
      StatusBar.Panels[1].Text := '---]$$$$[---';
      //StatusBar.Panels[1].Text := '超时';
    end else begin
      StatusBar.Panels[1].Text := '-----][-----';
      //StatusBar.Panels[1].Text := '已连接';
      LbLack.Caption := IntToStr(n456A2C) + '/' + IntToStr(nSendMsgCount);
    end;
  end;
end;

procedure TFrmMain.DecodeTimerTimer(Sender: TObject);
var
  sProcessMsg: string;
  sSocketMsg: string;
  sSocketHandle: string;
  nSocketIndex: Integer;
  nMsgCount: Integer;
  nSendRetCode: Integer;
  nSocketHandle: Integer;
  dwDecodeTick: LongWord;
  dwDecodeTime: LongWord;
  sRemoteIPaddr: string;
  UserSession: pTUserSession;
begin
  ShowMainLogMsg();
  if boDecodeLock or (not boGateReady) then Exit;
  try
    dwDecodeTick := GetTickCount();
    boDecodeLock := True;
    sProcessMsg := '';
    while (True) do begin
      if ClientSockeMsgList.Count <= 0 then break;
      sProcessMsg := sProcMsg + ClientSockeMsgList.Strings[0];
      sProcMsg := '';
      ClientSockeMsgList.Delete(0);
      while (True) do begin
        if TagCount(sProcessMsg, '$') < 1 then break;
        sProcessMsg := ArrestStringEx(sProcessMsg, '%', '$', sSocketMsg);
        if sSocketMsg = '' then break;
        if sSocketMsg[1] = '+' then begin
          case sSocketMsg[2] of
            '-': begin
                CloseSocket(Str_ToInt(Copy(sSocketMsg, 3, Length(sSocketMsg) - 2), 0));
                Continue;
              end;
            'B': begin
                Inc(m_nAttackCount);
                m_dwAttackTick := GetTickCount;
                sRemoteIPaddr := CloseSocketAndGetIPAddr(Str_ToInt(Copy(sSocketMsg, 3, Length(sSocketMsg) - 2), 0));
                AddTempBlockIP(sRemoteIPaddr);
                Continue;
              end;
            'T': begin
                Inc(m_nAttackCount);
                m_dwAttackTick := GetTickCount;
                sRemoteIPaddr := CloseSocketAndGetIPAddr(Str_ToInt(Copy(sSocketMsg, 3, Length(sSocketMsg) - 2), 0));
                AddBlockIP(sRemoteIPaddr);
                Continue;
              end;
          else begin
              dwKeepAliveTick := GetTickCount();
              boKeepAliveTimcOut := False;
              Continue;
            end;
          end;
        end;
        sSocketMsg := GetValidStr3(sSocketMsg, sSocketHandle, ['/']);
        nSocketHandle := Str_ToInt(sSocketHandle, -1);
        if nSocketHandle < 0 then Continue;
        for nSocketIndex := 0 to GATEMAXSESSION - 1 do begin
          if g_SessionArray[nSocketIndex].SocketHandle = nSocketHandle then begin
            g_SessionArray[nSocketIndex].MsgList.Add(sSocketMsg);
            break;
          end;
        end;
      end;
    end;
    //if sProcessMsg <> '' then ClientSockeMsgList.Add(sProcessMsg);
    if sProcessMsg <> '' then sProcMsg := sProcessMsg;

    nSendMsgCount := 0;
    n456A2C := 0;
    StringList318.Clear;
    for nSocketIndex := 0 to GATEMAXSESSION - 1 do begin
      if g_SessionArray[nSocketIndex].SocketHandle <= -1 then Continue;

      //踢除超时无数据传输连接
      if (nAttackLevel > 0) and ((GetTickCount - g_SessionArray[nSocketIndex].dwConnctCheckTick) > dwKeepConnectTimeOut * nAttackLevel) then begin
        sRemoteIPaddr := g_SessionArray[nSocketIndex].sRemoteIPaddr;
        g_SessionArray[nSocketIndex].Socket.Close;
        //MainOutMessage('端口空连接攻击: ' + sRemoteIPaddr, 1);}
        Continue;
      end;
      { if (nAttackLevel > 0) and ((GetTickCount - g_SessionArray[nSocketIndex].dwReceiveMsgTick) > 1000 * 30 * nAttackLevel) and (g_SessionArray[nSocketIndex].nReviceMsgLength > 1000) then begin
         sRemoteIPaddr := g_SessionArray[nSocketIndex].sRemoteIPaddr;
         Inc(m_nAttackCount);
         m_dwAttackTick := GetTickCount;
         if m_nAttackCount >= 3 then begin
           if BlockMethod = mDisconnect then BlockMethod := mBlock;
           if nAttackLevel > 1 then nAttackLevel := 1;
         end;
         case BlockMethod of
           mDisconnect: begin
               //Socket.Close;
             end;
           mBlock: begin
               AddTempBlockIP(sRemoteIPaddr);
               CloseConnect(sRemoteIPaddr);
             end;
           mBlockList: begin
               AddBlockIP(sRemoteIPaddr);
               CloseConnect(sRemoteIPaddr);
             end;
         end;
         if m_nAttackCount < 10 then begin
           MainOutMessage('端口攻击: ' + sRemoteIPaddr, 1);
         end;
         g_SessionArray[nSocketIndex].Socket.Close;
         Continue;
       end;}

      while (True) do begin
        if g_SessionArray[nSocketIndex].MsgList.Count <= 0 then break;
        UserSession := @g_SessionArray[nSocketIndex];
        nSendRetCode := SendUserMsg(UserSession, UserSession.MsgList.Strings[0]);
        if (nSendRetCode >= 0) then begin
          if nSendRetCode = 1 then begin
            UserSession.dwConnctCheckTick := GetTickCount();
            UserSession.MsgList.Delete(0);
            Continue;
          end;
          if UserSession.MsgList.Count > 100 then begin
            nMsgCount := 0;
            while nMsgCount <> 51 do begin
              UserSession.MsgList.Delete(0);
              Inc(nMsgCount);
            end;
          end;
          Inc(n456A2C, UserSession.MsgList.Count);
          MainOutMessage(UserSession.sIP +
            ' : ' +
            IntToStr(UserSession.MsgList.Count), 5);
          Inc(nSendMsgCount);
        end else begin
          UserSession.SocketHandle := -1;
          UserSession.Socket := nil;
          UserSession.MsgList.Clear;
        end;
      end;
    end;
    if (GetTickCount - dwSendKeepAliveTick) > 2 * 1000 then begin
      dwSendKeepAliveTick := GetTickCount();
      if boGateReady then
        ClientSocket.Socket.SendText('%--$');
    end;
    if (GetTickCount - dwKeepAliveTick) > 10 * 1000 then begin
      boKeepAliveTimcOut := True;
      ClientSocket.Close;
    end;
  finally
    boDecodeLock := False;
  end;
  dwDecodeTime := GetTickCount - dwDecodeTick;
  if dwDecodeMsgTime < dwDecodeTime then dwDecodeMsgTime := dwDecodeTime;
  if dwDecodeMsgTime > 50 then Dec(dwDecodeMsgTime, 50);
end;

procedure TFrmMain.CloseSocket(nSocketHandle: Integer);
var
  nIndex: Integer;
  UserSession: pTUserSession;
begin
  for nIndex := 0 to GATEMAXSESSION - 1 do begin
    UserSession := @g_SessionArray[nIndex];
    if (UserSession.Socket <> nil) and (UserSession.SocketHandle = nSocketHandle) then begin
      UserSession.Socket.Close;
      break;
    end;
  end;
end;

function TFrmMain.CloseSocketAndGetIPAddr(nSocketHandle: Integer): string;
var
  nIndex: Integer;
  UserSession: pTUserSession;
begin
  Result := '';
  for nIndex := 0 to GATEMAXSESSION - 1 do begin
    UserSession := @g_SessionArray[nIndex];
    if (UserSession.Socket <> nil) and (UserSession.SocketHandle = nSocketHandle) then begin
      Result := UserSession.sRemoteIPaddr;
      UserSession.Socket.Close;
      break;
    end;
  end;
end;

function TFrmMain.SendUserMsg(UserSession: pTUserSession; sSendMsg: string): Integer;
begin
  Result := -1;
  if UserSession.Socket <> nil then begin
    if not UserSession.bo0C then begin
      if not UserSession.boSendAvailable and (GetTickCount > UserSession.dwSendLockTimeOut) then begin
        UserSession.boSendAvailable := True;
        UserSession.nCheckSendLength := 0;
        boSendHoldTimeOut := True;
        dwSendHoldTick := GetTickCount();
      end;
      if UserSession.boSendAvailable then begin
        if UserSession.nCheckSendLength >= 250 then begin
          if not UserSession.boSendCheck then begin
            UserSession.boSendCheck := True;
            sSendMsg := '*' + sSendMsg;
          end;
          if UserSession.nCheckSendLength >= 512 then begin
            UserSession.boSendAvailable := False;
            UserSession.dwSendLockTimeOut := GetTickCount + 3 * 1000;
          end;
        end;
        UserSession.Socket.SendText(sSendMsg);
        Inc(UserSession.nSendMsgLen, Length(sSendMsg));
        Inc(UserSession.nCheckSendLength, Length(sSendMsg));
        Result := 1;
      end else begin
        Result := 0;
      end;
    end else begin
      Result := 0;
    end;
  end;
end;

procedure TFrmMain.LoadConfig;
var
  Conf: TIniFile;
  sConfigFileName: string;
begin
  sConfigFileName := '.\Config.ini';
  Conf := TIniFile.Create(sConfigFileName);
  TitleName := Conf.ReadString(GateClass, 'Title', TitleName);
  ServerPort := Conf.ReadInteger(GateClass, 'ServerPort', ServerPort);
  ServerAddr := Conf.ReadString(GateClass, 'ServerAddr', ServerAddr);
  GatePort := Conf.ReadInteger(GateClass, 'GatePort', GatePort);
  GateAddr := Conf.ReadString(GateClass, 'GateAddr', GateAddr);
  nShowLogLevel := Conf.ReadInteger(GateClass, 'ShowLogLevel', nShowLogLevel);
  BlockMethod := TBlockIPMethod(Conf.ReadInteger(GateClass, 'BlockMethod', Integer(BlockMethod)));
  UseBlockMethod := BlockMethod;

  if Conf.ReadInteger(GateClass, 'KeepConnectTimeOut', -1) <= 0 then
    Conf.WriteInteger(GateClass, 'KeepConnectTimeOut', dwKeepConnectTimeOut);

  if Conf.ReadInteger(GateClass, 'AttackLevel', -1) <= 0 then
    Conf.WriteInteger(GateClass, 'AttackLevel', nAttackLevel);

  nAttackLevel := Conf.ReadInteger(GateClass, 'AttackLevel', nAttackLevel);
  nUseAttackLevel := nAttackLevel;

  nMaxConnOfIPaddr := Conf.ReadInteger(GateClass, 'MaxConnOfIPaddr', nMaxConnOfIPaddr);
  dwKeepConnectTimeOut := Conf.ReadInteger(GateClass, 'KeepConnectTimeOut', dwKeepConnectTimeOut);
  g_boDynamicIPDisMode := Conf.ReadBool(GateClass, 'DynamicIPDisMode', g_boDynamicIPDisMode);
  g_boMinimize := Conf.ReadBool(GateClass, 'Minimize', g_boMinimize);

  g_boChgDefendLevel := Conf.ReadBool(GateClass, 'ChgDefendLevel', g_boChgDefendLevel);
  g_boClearTempList := Conf.ReadBool(GateClass, 'ClearTempList', g_boClearTempList);
  g_boReliefDefend := Conf.ReadBool(GateClass, 'ReliefDefend', g_boReliefDefend);
  g_nChgDefendLevel := Conf.ReadInteger(GateClass, 'ChgDefendLevelCount', g_nChgDefendLevel);
  g_dwClearTempList := Conf.ReadInteger(GateClass, 'ClearTempListTime', g_dwClearTempList);
  g_dwReliefDefend := Conf.ReadInteger(GateClass, 'ReliefDefendTime', g_dwReliefDefend);

  Conf.Free;
  LoadBlockIPFile();
end;

procedure TFrmMain.StartService;
begin
  try
    MainOutMessage(g_sProductName, 0);
    MainOutMessage(g_sUpDateTime, 0);
    MainOutMessage(g_sProgram, 0);
    MainOutMessage(g_sWebSite, 0);
    MainOutMessage('正在启动服务...', 3);
    SendGameCenterMsg(SG_STARTNOW, g_sNowStartGate);
    //StatusBar.Panels[3].Text:=sVersion;
    boServiceStart := True;
    boGateReady := False;
    boServerReady := False;
    nSessionCount := 0;
    MENU_CONTROL_START.Enabled := False;
    MENU_CONTROL_STOP.Enabled := True;

    dwReConnectServerTick := GetTickCount - 25 * 1000;
    boKeepAliveTimcOut := False;
    nSendMsgCount := 0;
    n456A2C := 0;
    dwSendKeepAliveTick := GetTickCount();
    boSendHoldTimeOut := False;
    dwSendHoldTick := GetTickCount();

    CurrIPaddrList := TGList.Create;
    BlockIPList := TGList.Create;
    TempBlockIPList := TGList.Create;
    AttackIPaddrList := TGList.Create;
    ClientSockeMsgList := TStringList.Create;

    ResUserSessionArray();
    LoadConfig();
    Caption := GateName + ' - ' + TitleName;
    ClientSocket.Active := False;
    ClientSocket.Host := ServerAddr;
    ClientSocket.Port := ServerPort;
    ClientSocket.Active := True;

    ServerSocket.Active := False;
    ServerSocket.Address := GateAddr;
    ServerSocket.Port := GatePort;
    ServerSocket.Active := True;

    SendTimer.Enabled := True;
    MainOutMessage('启动服务完成...', 3);
    SendGameCenterMsg(SG_STARTOK, g_sNowStartOK);
    if g_boMinimize then Application.Minimize;
  except
    on E: Exception do begin
      MENU_CONTROL_START.Enabled := True;
      MENU_CONTROL_STOP.Enabled := False;
      MainOutMessage(E.Message, 0);
    end;
  end;
end;

procedure TFrmMain.StopService;
var
  I, II: Integer;
  nSockIdx: Integer;
  IPaddr: pTSockaddr;
  IPList: TList;
begin
  MainOutMessage('正在停止服务...', 3);
  boServiceStart := False;
  boGateReady := False;
  MENU_CONTROL_START.Enabled := True;
  MENU_CONTROL_STOP.Enabled := False;
  SendTimer.Enabled := False;
  for nSockIdx := 0 to GATEMAXSESSION - 1 do begin
    if g_SessionArray[nSockIdx].Socket <> nil then
      g_SessionArray[nSockIdx].Socket.Close;
  end;
  SaveBlockIPList();
  ServerSocket.Close;
  ClientSocket.Close;
  ClientSockeMsgList.Free;

  CurrIPaddrList.Lock;
  try
    for I := 0 to CurrIPaddrList.Count - 1 do begin
      IPList := TList(CurrIPaddrList.Items[I]);
      if IPList <> nil then begin
        for II := 0 to IPList.Count - 1 do begin
          if pTSockaddr(IPList.Items[II]) <> nil then
            Dispose(pTSockaddr(IPList.Items[II]));
        end;
        IPList.Free;
      end;
    end;
  finally
    CurrIPaddrList.UnLock;
    CurrIPaddrList.Free;
  end;

  BlockIPList.Lock;
  try
    for I := 0 to BlockIPList.Count - 1 do begin
      IPaddr := pTSockaddr(BlockIPList.Items[I]);
      Dispose(IPaddr);
    end;
  finally
    BlockIPList.UnLock;
    BlockIPList.Free;
  end;

  TempBlockIPList.Lock;
  try
    for I := 0 to TempBlockIPList.Count - 1 do begin
      IPaddr := pTSockaddr(TempBlockIPList.Items[I]);
      Dispose(IPaddr);
    end;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?