source: tags/1.3.1/Network/UNetworkClient.pas

Last change on this file was 423, checked in by chronos, 2 years ago
  • Modified: Do not use explicit mode delphi directive as it is already set in project.
  • Modified: Use UNIX instead of LINUX for conditional code to work also on FreeBSD.
File size: 4.5 KB
Line 
1unit UNetworkClient;
2
3interface
4
5uses
6 Classes, SysUtils{$IFDEF UNIX}, fpAsync, fpsock{$ENDIF}, Protocol;
7
8{$IFDEF UNIX}
9type
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
38var
39 NetworkClient: TNetworkClient;
40{$ENDIF}
41
42procedure Client(Command, Player: Integer; var Data); stdcall;
43
44
45implementation
46
47uses
48 LocalPlayer{$IFDEF UNIX}, Global, UNetworkCommon{$ENDIF};
49
50procedure Client(Command, Player: Integer; var Data);
51{$IFDEF UNIX}
52var
53 Cmd: TCommand;
54{$ENDIF}
55begin
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}
71end;
72
73{$IFDEF UNIX}
74function LocalServer(Command, Player, Subject: Integer; var Data): Integer; stdcall;
75begin
76 if Assigned(NetworkClient) then
77 Result := NetworkClient.Server(TCommand(Command), Player, Subject, Data);
78end;
79
80{ TTCPClientThread }
81
82procedure TTCPClientThread.Execute;
83begin
84 TCPClient.EventLoop.Run;
85end;
86
87{ TNetworkClient }
88
89procedure TNetworkClient.DataAvailableExecute(Sender: TObject);
90begin
91 TCPClientThread.Synchronize(TCPClientThread, DataAvailableSync);
92
93 ClientEventLoop.ClearDataAvailableNotify(DataAvailableHandle);
94 DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
95end;
96
97procedure TNetworkClient.ConnectionStateChangeExecute(
98 Sender: TClientConnectionSocket; OldState, NewState: TConnectionState);
99begin
100 if NewState = connConnected then
101 DataAvailableHandle := ClientEventLoop.SetDataAvailableNotify(TCPClient.Stream.Handle, DataAvailableExecute, nil);
102end;
103
104procedure TNetworkClient.DataAvailableSync;
105var
106 Command: Integer;
107 ReadCount: Integer;
108 Player: Integer;
109 Data: array of Byte;
110begin
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;
133end;
134
135function TNetworkClient.Server(Command: TCommand; Player, Subject: Integer;
136 var Data): Integer;
137begin
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;
146end;
147
148constructor TNetworkClient.Create;
149begin
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;
163end;
164
165destructor TNetworkClient.Destroy;
166begin
167 ClientEventLoop.Break;
168 FreeAndNil(TCPClientThread);
169 FreeAndNil(TCPClient);
170 FreeAndNil(ClientEventLoop);
171 FreeAndNil(ReceiveBuffer);
172 inherited;
173end;
174{$ENDIF}
175
176end.
177
Note: See TracBrowser for help on using the repository browser.