⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smgwsimthread.pas

📁 支持CMPP/SGIP/SMGP/CNGP/SMPP协议的多功能网关模拟器:概述:基于CMPP v3.0 v2.0协议, SGIP v1.2协议...实现了正向订制/退订、反向订制/退订接口。同时提供
💻 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 + -