📄 smgwsimthread.pas
字号:
unit SMGWSimThread;
interface
//{$DEFINE DEBUGMODE}
uses
Classes, SysUtils, IdTcpServer, IdGlobal, IdTcpClient, CNGPStructs, CNGPConsts,
WinSock, Windows, MD5Implementation, General, Messages
{$IFDEF DEBUGMODE}
, AppGenerals
{$ENDIF}
;
const
//实现高级的反馈
UM_THRD_EXECUTE = WM_USER + 9800;
UM_SUBMIT_RECEIVED = WM_USER + 9801;
UM_DELIVER_SENT = WM_USER + 9802;
UM_REPORT_SENT = WM_USER + 9803;
UM_LOGIN_RECEIVED = WM_USER + 9804;
UM_EXIT_RECEIVED = WM_USER + 9805;
UM_AT_RECEIVED = WM_USER + 9806;
type
TSMGWSimThread = class(TThread)
private
idServer: TIdTcpServer;
conn: TIdTcpServerConnection;
FLogin, FSharedKey: string;
FMainHandle: THandle;
procedure IdServerOnExecute(AThread: TIdPeerThread);
procedure HandleLogin(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleExit(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleActiveTest(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleActiveTestResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleSubmit(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleDeliverResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleExitResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure HandleOther(const pHdr: PHeader; sock: TIdTcpServerConnection);
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
property Login: string read FLogin write FLogin;
property SharedKey: string read FSharedKey write FSharedKey;
property MainHandle: THandle read FMainHandle write FMainHandle;
procedure LockSock;
procedure UnlockSock;
procedure DeliverMsg(msgContent: string);
end;
var
sockLock: TRTLCriticalSection;
implementation
{ TSMGWSimThread }
constructor TSMGWSimThread.Create;
begin
inherited Create(True);
idServer := TIdTcpServer.Create(nil);
idServer.OnExecute := IdServerOnExecute;
idServer.DefaultPort := 9890;
idServer.ReuseSocket := rsFalse;
end;
procedure TSMGWSimThread.DeliverMsg(msgContent: string);
procedure GenerateArr(var arr: array of Char; len: integer);
var
iLen: integer;
l, h: integer;
begin
l := Low(arr);
h := High(arr);
if len < h then
h := len;
for iLen := l to h do
arr[iLen] := Char(Random(26) + Ord('A') - 1);
end;
var
deliver: CNGPDeliver;
p: PChar;
len: integer;
begin
if not Assigned(conn) then
Exit;
ZeroMemory(@deliver, sizeof(CNGPDeliver));
deliver.Header.Command_Id := htonl(COMMAND_DELIVER);
deliver.Header.Sequence_Id := Random(1000000);
len := sizeof(CNGPDeliver) - 255 + Length(msgContent);
deliver.Header.Total_Length := htonl(len);
GenerateArr(deliver.MsgId, 10);
GenerateArr(deliver.SrcTermId, 10);
CopyMemory(@deliver.DestTermId[0], PChar(SharedKey), Length(SharedKey));
deliver.MsgLength := 20;
StrPCopy(@deliver.msgContent[0], msgContent);
GetMem(p, len);
CopyMemory(p, @deliver, len - 5);
LockSock;
try
conn.WriteBuffer(p^, len, True);
finally
UnlockSock;
FreeMem(p, len);
end;
end;
destructor TSMGWSimThread.Destroy;
begin
idServer.OnExecute := nil;
idServer.Free;
inherited;
end;
procedure TSMGWSimThread.Execute;
begin
try
idServer.Active := True;
except
Exit;
end;
while not Terminated do begin
sleep(100);
end;
idServer.Active := False;
end;
procedure TSMGWSimThread.HandleActiveTest(const pHdr: PHeader; sock: TIdTcpServerConnection);
var
resp: PActiveTestResp;
begin
New(resp);
try
resp^.Command_Id := htonl(COMMAND_ACTIVE_TEST_RESP);
resp^.Command_Status := 0;
resp^.Sequence_Id := pHdr^.Sequence_Id;
resp^.Total_Length := sizeof(CNGPActiveTestResp);
LockSock;
try
sock.WriteBuffer(resp^, sizeof(CNGPActiveTestResp), True);
finally
UnlockSock;
end;
finally
Dispose(resp);
end;
end;
procedure TSMGWSimThread.HandleActiveTestResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
begin
//do nothing
end;
procedure TSMGWSimThread.HandleDeliverResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
var
buf: PDeliverResp;
begin
New(buf);
try
sock.ReadBuffer(buf^.MsgId[0], sizeof(CNGPDeliverResp) - sizeof(CNGPHeader));
finally
Dispose(buf);
end;
end;
procedure TSMGWSimThread.HandleExit(const pHdr: PHeader; sock: TIdTcpServerConnection);
begin
Self.conn := nil;
end;
procedure TSMGWSimThread.HandleExitResp(const pHdr: PHeader; sock: TIdTcpServerConnection);
begin
Self.conn := nil;
end;
procedure TSMGWSimThread.HandleLogin(const pHdr: PHeader; sock: TIdTcpServerConnection);
var
p: PLogin;
resp: PLoginResp;
sts: string;
input: PAnsiChar;
len: integer;
output: PAnsiChar;
olen: integer;
ctx: MD5Context;
digest: MD5Digest;
begin
New(p);
New(resp);
ZeroMemory(p, sizeof(CNGPLogin));
ZeroMemory(resp, sizeof(CNGPLoginResp));
resp^.Header.Total_Length := htonl(sizeof(CNGPLoginResp));
resp^.Header.Command_Id := htonl(COMMAND_LOGIN_RESP);
resp^.Header.Sequence_Id := pHdr^.Sequence_Id;
try
CopyMemory(p, pHdr, sizeof(CNGPHeader));
sock.ReadBuffer(p^.ClientId[0], sizeof(CNGPLogin) - sizeof(CNGPHeader));
sts := RightStr(IntToStr(10000000000 + DWord(ntohl(p^.TimeStamp))), 10);
len := Length(FLogin) + Length(FSharedKey) + 17;
GetMem(input, len + 1);
FillChar(input[0], len, 0);
StrPCopy(input, FLogin);
StrPCopy(input + Length(FLogin) + 7, FSharedKey);
StrPCopy(input + len - 10, sts);
MD5Init(ctx);
MD5Update(ctx, input, len);
MD5Final(ctx, digest);
if ByteArrayEqual(digest, p^.AuthenticatorClient) then begin
resp^.Header.Command_Status := htonl(STATUS_SUCCESS);
olen := 20 + Length(FSharedKey);
GetMem(output, olen);
FillChar(output[0], olen, 0);
CopyMemory(output, @resp.Header.Command_Status, 4);
CopyMemory(output + 4, @digest[0], 16);
StrPCopy(output + 20, FSharedKey);
MD5Init(ctx);
MD5Update(ctx, output, olen);
MD5Final(ctx, digest);
CopyMemory(@resp^.AuthenticatorServer[0], @digest[0], 16);
FreeMem(output, olen);
end
else
resp^.Header.Command_Status := htonl(STATUS_AUTHENTICATION_FAILED);
LockSock;
try
sock.WriteBuffer(resp^, sizeof(CNGPLoginResp), True);
finally
UnlockSock;
end;
finally
Dispose(resp);
Dispose(p);
end;
end;
procedure TSMGWSimThread.HandleOther(const pHdr: PHeader; sock: TIdTcpServerConnection);
var
p: Pointer;
len: integer;
begin
len := ntohl(pHdr^.Total_Length) - sizeof(CNGPHeader);
GetMem(p, len);
try
sock.ReadBuffer(p^, len);
finally
FreeMem(p, len);
end;
end;
procedure TSMGWSimThread.HandleSubmit(const pHdr: PHeader; sock: TIdTcpServerConnection);
procedure GenerateArr(var arr: array of Char);
var
iLen: integer;
l, h: integer;
begin
l := Low(arr);
h := High(arr);
for iLen := l to h do
arr[iLen] := Char(Random(255));
end;
var
submit: PSubmit;
p: PChar;
len, topLen: integer;
resp: PSubmitResp;
rpt: CNGPDeliver;
rnd: integer;
begin
New(submit);
New(resp);
ZeroMemory(submit, sizeof(CNGPSubmit));
ZeroMemory(resp, sizeof(CNGPSubmitResp));
try
CopyMemory(submit, pHdr, sizeof(CNGPHeader));
len := ntohl(pHdr.Total_Length) - sizeof(CNGPHeader);
GetMem(p, len);
sock.ReadBuffer(p^, len);
topLen := sizeof(CNGPSubmit)
- sizeof(CNGPHeader)
- sizeof(CNGPTLV)
- Length(submit^.msgContent)
- 1
- Length(submit^.DestTermId) * Length(submit^.DestTermId[0])
+ Length(submit^.DestTermId[0]);
CopyMemory(@submit.spid[0],
p,
topLen);
CopyMemory(@submit^.MsgLength,
p + topLen,
1);
CopyMemory(@submit^.msgContent[0],
p + topLen + 1,
submit^.MsgLength);
CopyMemory(@submit^.ProtocolId, p + len - 5, 5);
FreeMem(p, len);
rnd := Random(10255);
if rnd > 10000 then
rnd := rnd - 10000
else
rnd := 0;
resp^.Header.Command_Id := htonl(COMMAND_SUBMIT_RESP);
resp^.Header.Command_Status := htonl(rnd);
resp^.Header.Sequence_Id := submit^.Header.Sequence_Id;
resp^.Header.Total_Length := htonl(sizeof(CNGPSubmitResp));
GenerateArr(resp^.MsgId);
LockSock;
try
sock.WriteBuffer(resp^, sizeof(CNGPSubmitResp), True);
finally
UnlockSock;
end;
(***********************************************)
if submit^.NeedReport = 1 then begin
ZeroMemory(@rpt, sizeof(CNGPDeliver));
rpt.Header.Command_Id := htonl(COMMAND_DELIVER);
len := sizeof(CNGPDeliver) - 155;
rpt.Header.Total_Length := htonl(len);
rpt.IsReport := 1;
CopyMemory(@rpt.SrcTermId[0], @submit^.ChargeTermId[0], 21);
CopyMemory(@rpt.DestTermId[0], @submit^.SrcTermId[0], 21);
rpt.MsgLength := 101;
StrPCopy(rpt.msgContent, 'id:');
CopyMemory(@rpt.msgContent[3], @resp^.MsgId[0], 10);
StrPCopy(@rpt.msgContent[13],
' sub:001 dlvrd:001;submit_date:1122334455 done_date:5544332211 stat:DELIVRD;err:');
rnd := Random(110);
if rnd > 100 then
rnd := rnd - 100
else
rnd := 0;
StrPCopy(@rpt.msgContent[93], RightStr(IntToStr(1000 + rnd), 3));
StrPCopy(@rpt.msgContent[96], ';txt:');
{$IFDEF DEBUGMODE}
appendlog(rpt.msgContent[3], 10);
{$ENDIF}
GetMem(p, len);
CopyMemory(p, @rpt, len - 5);
CopyMemory(p + len - 5, @rpt.ProtocolId, 5);
LockSock;
try
sock.WriteBuffer(p^, len, True);
finally
UnlockSock;
FreeMem(p, len);
end;
end;
(***************************************************)
finally
Dispose(resp);
Dispose(submit);
end;
end;
procedure TSMGWSimThread.IdServerOnExecute(AThread: TIdPeerThread);
{$IFDEF DEBUGMODE}
procedure HandleException(e: Exception);
var
err: PChar;
len: integer;
begin
len := Length(e.Message);
GetMem(err, len + 1);
StrPCopy(err, e.Message);
appendlog(err^, len);
FreeMem(err, len + 1);
end;
{$ENDIF}
var
sock: TIdTcpServerConnection;
p: PHeader;
cmdId: DWord;
begin
sock := AThread.Connection;
Self.conn := sock;
try
New(p);
try
sock.ReadBuffer(p^, sizeof(CNGPHeader));
cmdId := ntohl(p^.Command_Id);
if cmdId = COMMAND_LOGIN then
HandleLogin(p, sock)
else if cmdId = COMMAND_SUBMIT then
HandleSubmit(p, sock)
else if cmdId = COMMAND_DELIVER_RESP then
HandleDeliverResp(p, sock)
else if cmdId = COMMAND_ACTIVE_TEST then
HandleActiveTest(p, sock)
else if cmdId = COMMAND_ACTIVE_TEST_RESP then
HandleActiveTestResp(p, sock)
else if cmdId = COMMAND_EXIT then
HandleExit(p, sock)
else if cmdId = COMMAND_EXIT_RESP then
HandleExitResp(p, sock)
else
HandleOther(p, sock);
finally
Dispose(p);
end;
except
{$IFDEF DEBUGMODE}
on e: Exception do begin
HandleException(e);
PostMessage(FMainHandle,
UM_THRD_EXECUTE,
0, 1);
AThread.Terminate;
end;
{$ELSE}
PostMessage(FMainHandle,
UM_THRD_EXECUTE,
0, 1);
AThread.Terminate;
{$ENDIF}
end;
end;
procedure TSMGWSimThread.LockSock;
begin
EnterCriticalSection(sockLock);
end;
procedure TSMGWSimThread.UnlockSock;
begin
LeaveCriticalSection(sockLock);
end;
initialization
InitializeCriticalSection(sockLock);
Randomize;
finalization
DeleteCriticalSection(sockLock);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -