📄 runsock.~pas
字号:
unit RunSock;
interface
uses
Windows, Classes, SysUtils, StrUtils, SyncObjs, JSocket, ObjBase, Grobal2,SDK, FrnEngn,UsrEngn;
type
TRunSocket = class //Size: 0xCD0
m_RunSocketSection :TRTLCriticalSection;
m_RunAddrList :TStringList; //0x4
n8 :Integer;//0x8
m_IPaddrArr :array[0..19] of TIPaddr;
n4F8 :Integer; //0x4F8
dwSendTestMsgTick :LongWord; //0x4FC
private
procedure LoadRunAddr;
procedure ExecGateBuffers(nGateIndex:Integer;Gate:pTGateInfo;Buffer:PChar;nMsgLen:Integer);
procedure DoClientCertification(GateIdx:Integer;GateUser:pTGateUserInfo;nSocket:Integer;sMsg:String);
procedure ExecGateMsg(GateIdx:Integer;Gate:pTGateInfo;MsgHeader:pTMsgHeader;MsgBuff:PChar;nMsgLen:Integer);
procedure SendCheck(Socket: TCustomWinSocket;nIdent:Integer);
function OpenNewUser(nSocket:Integer;nGSocketIdx:Integer;sIPaddr:String; UserList:TList): Integer;
procedure SendNewUserMsg(Socket:TCustomWinSocket;nSocket:Integer;nSocketIndex,nUserIdex:Integer);
procedure SendGateTestMsg(nIndex:Integer);
function SendGateBuffers(GateIdx:Integer;Gate:pTGateInfo;MsgList:TList):Boolean;
function GetGateAddr(sIPaddr:String):String;
procedure SendScanMsg(DefMsg:pTDefaultMessage;sMsg:String;nGateIdx,nSocket,nGsIdx:integer);
public
constructor Create();
destructor Destroy; override;
procedure AddGate(Socket:TCustomWinSocket);
procedure SocketRead(Socket:TCustomWinSocket);
procedure CloseGate(Socket:TCustomWinSocket);
procedure CloseErrGate(Socket:TCustomWinSocket;var ErrorCode:Integer);
procedure CloseAllGate();
procedure Run();
procedure DemoRun();
procedure Execute;
procedure CloseUser(GateIdx,nSocket:Integer);
function AddGateBuffer(GateIdx:Integer;Buffer:PChar):Boolean;
procedure SendOutConnectMsg(nGateIdx,nSocket,nGsIdx:integer);
procedure SetGateUserList(nGateIdx,nSocket:Integer;PlayObject:TPlayObject);
procedure KickUser(sAccount:String;nSessionID:Integer);
end;
var
g_GateArr :array [0..19] of TGateInfo;
g_nGateRecvMsgLenMin:Integer;
g_nGateRecvMsgLenMax:Integer;
implementation
uses M2Share, IdSrvClient, HUtil32, EDcode, EncryptUnit;
var
nRunSocketRun :Integer = -1;
{ TRunSocket }
procedure TRunSocket.AddGate(Socket: TCustomWinSocket);
var
i:Integer;
sIPaddr:String;
Gate:pTGateInfo;
ResourceString
sGateOpen = '游戏网关[%d](%s:%d)已打开...';
sKickGate = '服务器未就绪: %s';
begin
sIPaddr:=Socket.RemoteAddress;
if boStartReady then begin
for i:=Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[i];
if Gate.boUsed then Continue;
Gate.boUsed := True;
Gate.Socket := Socket;
Gate.sAddr := GetGateAddr(sIPaddr);
Gate.nPort := Socket.RemotePort;
Gate.n520 := 1;
Gate.UserList := TList.Create;
Gate.nUserCount := 0;
Gate.Buffer := nil;
Gate.nBuffLen := 0;
Gate.BufferList := TList.Create;
Gate.boSendKeepAlive := False;
Gate.nSendChecked := 0;
Gate.boSendCheckPro := false;
Gate.dwSendCheckProTick := GetTickCount;
Gate.nSendBlockCount := 0;
Gate.dwTime544 := GetTickCount;
MainOutMessage(format(sGateOpen,[I,Socket.RemoteAddress,Socket.RemotePort]));
break;
end;
end else begin
MainOutMessage(format(sKickGate,[sIPaddr]));
Socket.Close;
end;
end;
procedure TRunSocket.CloseAllGate;//004E0068
var
GateIdx:integer;
Gate:pTGateInfo;
begin
for GateIdx:= Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[GateIdx];
if Gate.Socket <> nil then begin
Gate.Socket.Close;
end;
end;
end;
procedure TRunSocket.CloseErrGate(Socket: TCustomWinSocket;
var ErrorCode: Integer);//004DFF58
begin
if Socket.Connected then Socket.Close;
ErrorCode:=0;
end;
procedure TRunSocket.CloseGate(Socket: TCustomWinSocket);//004E00B4
var
I,GateIdx:Integer;
GateUser:pTGateUserInfo;
UserList:TList;
Gate:pTGateInfo;
ResourceString
sGateClose = '游戏网关[%d](%s:%d)已关闭...';
begin
EnterCriticalSection(m_RunSocketSection);
try
for GateIdx:= Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[GateIdx];
if Gate.Socket = Socket then begin
UserList:=Gate.UserList;
for I:=0 to UserList.Count - 1 do begin
GateUser:=UserList.Items[I];
if GateUser <> nil then begin
if GateUser.PlayObject <> nil then begin
TPlayObject(GateUser.PlayObject).m_boEmergencyClose:=True;
if not TPlayObject(GateUser.PlayObject).m_boReconnection then begin
FrmIDSoc.SendHumanLogOutmsg(GateUser.sAccount,GateUser.nSessionID);
// MainOutMessage('if not TPlayObject(GateUser.PlayObject).m_boReconnection then SendHumanLogOutmsg');
end;
end;
Dispose(GateUser);
UserList.Items[I]:=nil;
end;
end;
Gate.UserList.Free;
Gate.UserList:=nil;
//004E01BF
if Gate.Buffer <> nil then
FreeMem(Gate.Buffer);
Gate.Buffer:=nil;
Gate.nBuffLen:=0;
for I:=0 to Gate.BufferList.Count -1 do begin
FreeMem(Gate.BufferList.Items[I]);
end;
Gate.BufferList.Free;
Gate.BufferList:=nil;
Gate.boUsed:=False;
Gate.Socket:=nil;
MainOutMessage(format(sGateClose,[GateIdx,Socket.RemoteAddress,Socket.RemotePort]));
break;
end;
end;//004E02F1
finally
LeaveCriticalSection(m_RunSocketSection);
end;
end;
//004E16E4
procedure TRunSocket.ExecGateBuffers(nGateIndex:Integer;Gate:pTGateInfo;Buffer:PChar;nMsgLen:Integer);
var
nLen:Integer;
Buff:PChar;
MsgBuff:PChar;
MsgHeader:pTMsgHeader; //0x20
nCheckMsgLen:Integer;
TempBuff:PChar;
ResourceString
sExceptionMsg1 = '[Exception] TRunSocket::ExecGateBuffers -> pBuffer';
sExceptionMsg2 = '[Exception] TRunSocket::ExecGateBuffers -> @pwork,ExecGateMsg ';
sExceptionMsg3 = '[Exception] TRunSocket::ExecGateBuffers -> FreeMem';
begin
nLen:=0;
Buff:=nil;
try
if Buffer <> nil then begin
ReallocMem(Gate.Buffer,Gate.nBuffLen + nMsgLen);
Move(Buffer^,Gate.Buffer[Gate.nBuffLen],nMsgLen);
end;
except
MainOutMessage(sExceptionMsg1);
end;
try
nLen:=Gate.nBuffLen + nMsgLen;
Buff:=Gate.Buffer;
if nLen >= SizeOf(TMsgHeader) then begin
while (True) do begin
{
pMsg:=pTMsgHeader(Buff);
if pMsg.dwCode = RUNGATECODE then begin
if nLen < (pMsg.nLength + SizeOf(TMsgHeader)) then break;
MsgBuff:=@Buff[SizeOf(TMsgHeader)];
}
MsgHeader:=pTMsgHeader(Buff);
nCheckMsgLen:=abs(MsgHeader.nLength) + SizeOf(TMsgHeader);
if (MsgHeader.dwCode = RUNGATECODE) and (nCheckMsgLen < $8000) then begin
if nLen < nCheckMsgLen then break;
MsgBuff:=Buff + SizeOf(TMsgHeader);//Jacky 1009 换上
//MsgBuff:=@Buff[SizeOf(TMsgHeader)];
ExecGateMsg(nGateIndex,Gate,MsgHeader,MsgBuff,MsgHeader.nLength);
Buff:=Buff + SizeOf(TMsgHeader) + MsgHeader.nLength;//Jacky 1009 换上
//Buff:=@Buff[SizeOf(TMsgHeader) + pMsg.nLength];
nLen:= nLen - (MsgHeader.nLength + SizeOf(TMsgHeader));
end else begin
Inc(Buff);
Dec(nLen);
end;
if nLen < SizeOf(TMsgHeader) then break;
end;
end;
except
MainOutMessage(sExceptionMsg2);
end;
try
if nLen > 0 then begin
GetMem(TempBuff,nLen);
Move(Buff^,TempBuff^,nLen);
FreeMem(Gate.Buffer);
Gate.Buffer:=TempBuff;
Gate.nBuffLen:=nLen;
end else begin
FreeMem(Gate.Buffer);
Gate.Buffer:=nil;
Gate.nBuffLen:=0;
end;
except
MainOutMessage(sExceptionMsg3);
end;
end;
procedure TRunSocket.SocketRead(Socket: TCustomWinSocket);//004DFF84
var
nMsgLen, GateIdx:Integer;
Gate:pTGateInfo;
RecvBuffer:array[0..DATA_BUFSIZE * 2 - 1] of Char;
nLoopCheck:Integer;
ResourceString
sExceptionMsg1 = '[Exception] TRunSocket::SocketRead';
begin
for GateIdx:= Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[GateIdx];
if Gate.Socket = Socket then begin
try
//nLoopCheck:=0;
while (True) do begin //Jacky 1009 换上
nMsgLen:=Socket.ReceiveBuf(RecvBuffer,SizeOf(RecvBuffer));
if nMsgLen <= 0 then break;
ExecGateBuffers(GateIdx,Gate,@RecvBuffer,nMsgLen);
// Inc(nLoopCheck);
// if nLoopCheck > g_Config.nRunSocketDieLoopLimit then begin
// MainOutMessage('[Exception] TRunSocket.SocketRead DieLoop');
// break;
// end;
end;
break;
except
MainOutMessage(sExceptionMsg1);
end;
end;
end;
end;
procedure TRunSocket.Run;//004E1CD0
var
dwRunTick:LongWord;
i,nG:Integer;
Gate:pTGateInfo;
ResourceString
sExceptionMsg = '[Exception] TRunSocket::Run ';
begin
dwRunTick:=GetTickCount();
if boStartReady then begin
try
if g_Config.nGateLoad > 0 then begin
if (GetTickCount - dwSendTestMsgTick) >= 100 then begin
dwSendTestMsgTick:=GetTickCount();
for i:=Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[i];
if Gate.BufferList <> nil then begin
for nG:= 0 to g_Config.nGateLoad -1 do begin
SendGateTestMsg(i);
end;//004E1D7D
end;
end;
end;//if (GetTickCount() - dwTime4FC) >= 100 then begin
end;//004E1D86 if nGateLoad > 0 then begin
for i:=Low(g_GateArr) to High(g_GateArr) do begin
Gate:=@g_GateArr[i];
if Gate.BufferList <> nil then begin
{
EnterCriticalSection(RunSocketSection);
try
TempList:=SendMsgList;
SendMsgList:=Gate.BufferList;
Gate.BufferList:=TempList;
finally
LeaveCriticalSection(RunSocketSection);
end;
Gate.nSendMsgCount:=SendMsgList.Count;
ThreadSendGateBuffers(i,Gate,SendMsgList);
Gate.nSendRemainCount:=SendMsgList.Count;
SendMsgList.Clear;
}
EnterCriticalSection(m_RunSocketSection);
try
Gate.nSendMsgCount:=Gate.BufferList.Count;
if SendGateBuffers(I,Gate,Gate.BufferList) then begin
Gate.nSendRemainCount:=Gate.BufferList.Count;
end else begin//004E1DE3
Gate.nSendRemainCount:=Gate.BufferList.Count;
end;
finally
LeaveCriticalSection(m_RunSocketSection);
end;
end;//004E1DF2
end;//004E1DFB
for I:=Low(g_GateArr) to High(g_GateArr) do begin
if g_GateArr[I].Socket <> nil then begin
Gate:=@g_GateArr[I];
if (GetTickCount - Gate.dwSendTick) >= 1000 then begin
Gate.dwSendTick:=GetTickCount();
Gate.nSendMsgBytes:=Gate.nSendBytesCount;
Gate.nSendedMsgCount:=Gate.nSendCount;
Gate.nSendBytesCount:=0;
Gate.nSendCount:=0;
end;//004E1E75
if Gate.boSendKeepAlive then begin
Gate.boSendKeepAlive:=False;
SendCheck(Gate.Socket,GM_CHECKSERVER);
end;//004E1EBF //网关连接上后 60秒以后发送一个 消息 给网关,告诉网关,专业版本
if (not Gate.boSendCheckPro)and (GetTickCount - Gate.dwSendCheckProTick >(random(60)+10)*1000) then begin
Gate.boSendCheckPro:=true;
SendCheck(Gate.Socket,GM_TEST);
end;
end;//004E1EBF
end;
except
on e: Exception do begin
MainOutMessage(sExceptionMsg);
MainOutMessage(E.Message); raise;
end;
end;
end;//004E1EEA if boStartReady then begin
g_nSockCountMin:=GetTickCount - dwRunTick;
if g_nSockCountMin > g_nSockCountMax then g_nSockCountMax := g_nSockCountMin;
asm
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
end;
end;
procedure TRunSocket.DoClientCertification(GateIdx:Integer;GateUser:pTGateUserInfo;nSocket:Integer;sMsg:String);//004E1028
function ScanCertification(sAccount:String;sChrName:String;nSessionID,nClientVersion:Integer):Boolean;
var
DefMsg:TDefaultMessage;
// DES:TDES; // DES有问题
ResourceString
sInfoMsg = '%s/%s/%s/%d/%d/%d/%d-%d';
begin
Result:=False;
//**00/88/200000/200000/0
if (sAccount = '00') and (sChrName = '88') and (nSessionID = 200000) and (nClientVersion = 200000) then begin
// DES:=TDES.Create;
sMsg:=format(sInfoMsg,[g_Config.sServerName,
g_config.sRegKey,
g_config.sRegServerAddr,
g_config.nRegServerPort,
UserEngine.OnlinePlayObject,
g_dwStartTick,
GetTickCount,
VEROWNER]);
// sMsg:=DES.EncryptHexString(sMsg,IntToStr(nSessionID xor (nClientVersion div 3)));
// DES.Free;
SendScanMsg(nil,EncodeString(sMsg),GateIdx,nSocket,GateUser.nGSocketIdx);
Result:=True;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -