1 | unit UNetworkClient;
|
---|
2 |
|
---|
3 | interface
|
---|
4 |
|
---|
5 | uses
|
---|
6 | Classes, SysUtils{$IFDEF UNIX}, fpAsync, fpsock{$ENDIF}, Protocol;
|
---|
7 |
|
---|
8 | {$IFDEF UNIX}
|
---|
9 | type
|
---|
10 | { TTCPClientThread }
|
---|
11 |
|
---|
12 | TTCPClientThread = class(TThread)
|
---|
13 | TCPClient: TTCPClient;
|
---|
14 | procedure Execute; override;
|
---|
15 | end;
|
---|
16 |
|
---|
17 | { TNetworkClient }
|
---|
18 |
|
---|
19 | TNetworkClient = class
|
---|
20 | private
|
---|
21 | DataAvailableHandle: Pointer;
|
---|
22 | TCPClientThread: TTCPClientThread;
|
---|
23 | ReceiveBuffer: TMemoryStream;
|
---|
24 | procedure DataAvailableExecute(Sender: TObject);
|
---|
25 | procedure ConnectionStateChangeExecute(Sender: TClientConnectionSocket;
|
---|
26 | OldState, NewState: TConnectionState);
|
---|
27 | procedure DataAvailableSync;
|
---|
28 | public
|
---|
29 | AuxServer: TServerCall;
|
---|
30 | LocalClient: TClientCall;
|
---|
31 | TCPClient: TTCPClient;
|
---|
32 | ClientEventLoop: TEventLoop;
|
---|
33 | function Server(Command: TCommand; Player, Subject: Integer; var Data): Integer;
|
---|
34 | constructor Create;
|
---|
35 | destructor Destroy; override;
|
---|
36 | end;
|
---|
37 |
|
---|
38 | var
|
---|
39 | NetworkClient: TNetworkClient;
|
---|
40 | {$ENDIF}
|
---|
41 |
|
---|
42 | procedure Client(Command, Player: Integer; var Data); stdcall;
|
---|
43 |
|
---|
44 |
|
---|
45 | implementation
|
---|
46 |
|
---|
47 | uses
|
---|
48 | LocalPlayer{$IFDEF UNIX}, Global, UNetworkCommon{$ENDIF};
|
---|
49 |
|
---|
50 | procedure Client(Command, Player: Integer; var Data);
|
---|
51 | {$IFDEF UNIX}
|
---|
52 | var
|
---|
53 | Cmd: TCommand;
|
---|
54 | {$ENDIF}
|
---|
55 | begin
|
---|
56 | {$IFDEF UNIX}
|
---|
57 | Cmd := TCommand(Command);
|
---|
58 | case Cmd of
|
---|
59 | cmInitModule: begin
|
---|
60 | if not Assigned(NetworkClient) then
|
---|
61 | NetworkClient := TNetworkClient.Create;
|
---|
62 | NetworkClient.AuxServer := TInitModuleData(Data).Server;
|
---|
63 | TInitModuleData(Data).Flags := aiThreaded;
|
---|
64 | NetworkClient.LocalClient := LocalPlayer.Client;
|
---|
65 | end;
|
---|
66 | cmReleaseModule: begin
|
---|
67 | FreeAndNil(NetworkClient);
|
---|
68 | end;
|
---|
69 | end;
|
---|
70 | {$ENDIF}
|
---|
71 | end;
|
---|
72 |
|
---|
73 | {$IFDEF UNIX}
|
---|
74 | function LocalServer(Command, Player, Subject: Integer; var Data): Integer; stdcall;
|
---|
75 | begin
|
---|
76 | if Assigned(NetworkClient) then
|
---|
77 | Result := NetworkClient.Server(TCommand(Command), Player, Subject, Data);
|
---|
78 | end;
|
---|
79 |
|
---|
80 | { TTCPClientThread }
|
---|
81 |
|
---|
82 | procedure TTCPClientThread.Execute;
|
---|
83 | begin
|
---|
84 | TCPClient.EventLoop.Run;
|
---|
85 | end;
|
---|
86 |
|
---|
87 | { TNetworkClient }
|
---|
88 |
|
---|
89 | procedure TNetworkClient.DataAvailableExecute(Sender: TObject);
|
---|
90 | begin
|
---|
91 | TCPClientThread.Synchronize(TCPClientThread, DataAvailableSync);
|
---|
92 |
|
---|
93 | ClientEventLoop.ClearDataAvailableNotify(DataAvailableHandle);
|
---|
94 | DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
|
---|
95 | end;
|
---|
96 |
|
---|
97 | procedure TNetworkClient.ConnectionStateChangeExecute(
|
---|
98 | Sender: TClientConnectionSocket; OldState, NewState: TConnectionState);
|
---|
99 | begin
|
---|
100 | if NewState = connConnected then
|
---|
101 | DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
|
---|
102 | end;
|
---|
103 |
|
---|
104 | procedure TNetworkClient.DataAvailableSync;
|
---|
105 | var
|
---|
106 | Command: Integer;
|
---|
107 | ReadCount: Integer;
|
---|
108 | Player: Integer;
|
---|
109 | Data: array of Byte;
|
---|
110 | begin
|
---|
111 | StreamAppend(ReceiveBuffer, TCPClient.Stream);
|
---|
112 | while ReceiveBuffer.Size >= 2 * SizeOf(Integer) do begin
|
---|
113 | ReceiveBuffer.Position := 0;
|
---|
114 | Command := Integer(ReceiveBuffer.ReadDWord);
|
---|
115 | Player := Integer(ReceiveBuffer.ReadDWord);
|
---|
116 | SetLength(Data, GetCommandDataSize(TCommand(Command)));
|
---|
117 | if Length(Data) > 0 then begin
|
---|
118 | ReadCount := ReceiveBuffer.Read(Data[0], Length(Data));
|
---|
119 | SetLength(Data, ReadCount);
|
---|
120 | end;
|
---|
121 |
|
---|
122 | // Rewrite server address received from network by local handler
|
---|
123 | if Command = cInitModule then begin
|
---|
124 | PInitModuleData(@Data[0])^.Server := LocalServer;
|
---|
125 | end;
|
---|
126 |
|
---|
127 | if Length(Data) > 0 then
|
---|
128 | LocalClient(Command, Player, Data[0])
|
---|
129 | else LocalClient(Command, Player, nil^);
|
---|
130 |
|
---|
131 | StreamRemoveRead(ReceiveBuffer);
|
---|
132 | end;
|
---|
133 | end;
|
---|
134 |
|
---|
135 | function TNetworkClient.Server(Command: TCommand; Player, Subject: Integer;
|
---|
136 | var Data): Integer;
|
---|
137 | begin
|
---|
138 | with TCPClient.Stream do begin
|
---|
139 | WriteDWord(DWord(Command));
|
---|
140 | WriteDWord(Player);
|
---|
141 | WriteDWord(Subject);
|
---|
142 | if GetCommandDataSize(Command) > 0 then
|
---|
143 | Write(Data, GetCommandDataSize(Command));
|
---|
144 | Result := ReadDWord;
|
---|
145 | end;
|
---|
146 | end;
|
---|
147 |
|
---|
148 | constructor TNetworkClient.Create;
|
---|
149 | begin
|
---|
150 | ReceiveBuffer := TMemoryStream.Create;
|
---|
151 | ClientEventLoop := TEventLoop.Create;
|
---|
152 | TCPClient := TTCPClient.Create(nil);
|
---|
153 | with TCPClient do begin
|
---|
154 | EventLoop := ClientEventLoop;
|
---|
155 | Host := '127.0.0.1';
|
---|
156 | Port := CevoNetworkPort;
|
---|
157 | OnConnectionStateChange := ConnectionStateChangeExecute;
|
---|
158 | Active := True;
|
---|
159 | end;
|
---|
160 | TCPClientThread := TTCPClientThread.Create(True);
|
---|
161 | TCPClientThread.TCPClient := TCPClient;
|
---|
162 | TCPClientThread.Start;
|
---|
163 | end;
|
---|
164 |
|
---|
165 | destructor TNetworkClient.Destroy;
|
---|
166 | begin
|
---|
167 | ClientEventLoop.Break;
|
---|
168 | FreeAndNil(TCPClientThread);
|
---|
169 | FreeAndNil(TCPClient);
|
---|
170 | FreeAndNil(ClientEventLoop);
|
---|
171 | FreeAndNil(ReceiveBuffer);
|
---|
172 | inherited;
|
---|
173 | end;
|
---|
174 | {$ENDIF}
|
---|
175 |
|
---|
176 | end.
|
---|
177 |
|
---|