source: trunk/UNetwork.pas

Last change on this file was 3, checked in by chronos, 8 years ago
  • Modified: Network address in each network interface should be full address not just single integer. Yet need to specify network subnets for routing.
File size: 10.7 KB
Line 
1unit UNetwork;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, Contnrs, Graphics, Dialogs, fgl;
9
10type
11 TNetworkNode = class;
12 TNetworkInterface = class;
13
14 { TNetworkAddress }
15
16 TNetworkAddress = record
17 Parts: array of Integer;
18 Context: Integer;
19 class operator Equal(A, B: TNetworkAddress): Boolean;
20 function GetString: string;
21 procedure Clear;
22 end;
23
24 TNetworkPacketProtocol = (nppDIA1);
25
26 TNetworkPacket = class
27 Protocol: TNetworkPacketProtocol;
28 Source: TNetworkAddress;
29 Destination: TNetworkAddress;
30 Data: string;
31 end;
32
33 TRecivePacketEvent = procedure(Sender: TNetworkInterface; Packet: TNetworkPacket) of object;
34 TLogEvent = procedure(Sender: TNetworkNode; Data: string) of object;
35
36 { TNetworkInterface }
37
38 TNetworkInterface = class
39 private
40 FOnReceivePacket: TRecivePacketEvent;
41 FRemote: TNetworkInterface;
42 function GetConnected: Boolean;
43 procedure SetRemote(AValue: TNetworkInterface);
44 procedure ReceivePacket(Packet: TNetworkPacket);
45 public
46 Node: TNetworkNode;
47 Address: TNetworkAddress;
48 Network: Integer;
49 procedure Connect(Remote: TNetworkInterface);
50 procedure Disconnet;
51 procedure SendPacket(Packet: TNetworkPacket);
52 constructor Create;
53 destructor Destroy; override;
54 property Remote: TNetworkInterface read FRemote
55 write SetRemote;
56 property OnReceivePacket: TRecivePacketEvent read FOnReceivePacket write FOnReceivePacket;
57 property Connected: Boolean read GetConnected;
58 end;
59
60 { TNetworkNode }
61
62 TNetworkNode = class
63 private
64 procedure ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket); virtual;
65 public
66 Name: string;
67 Position: TPoint;
68 Interfaces: TFPGObjectList<TNetworkInterface>;
69 function AddInterface: TNetworkInterface;
70 constructor Create; virtual;
71 destructor Destroy; override;
72 end;
73
74 { TNetworkSwitch }
75
76 TNetworkSwitch = class(TNetworkNode)
77 private
78 procedure ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket); override;
79 public
80 constructor Create; override;
81 end;
82
83 { TNetworkHost }
84
85 TNetworkHost = class(TNetworkNode)
86 private
87 FOnLog: TLogEvent;
88 procedure ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket); override;
89 procedure DoLog(Sender: TNetworkNode; Data: string);
90 public
91 procedure Ping(Address: TNetworkAddress);
92 property OnLog: TLogEvent read FOnLog write FOnLog;
93 end;
94
95 { TNetworkRouter }
96
97 TNetworkRouter = class(TNetworkHost)
98 private
99 procedure ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket); override;
100 public
101 end;
102
103 TNetwork = class
104 Nodes: TFPGObjectList<TNetworkNode>;
105 function AddRouter(Name: string; Position: TPoint; InterfaceCount: Integer; Log: TLogEvent): TNetworkRouter;
106 function AddHost(Name: string; Position: TPoint; InterfaceCount: Integer; Log: TLogEvent): TNetworkHost;
107 function AddNode(Name: string; Position: TPoint; InterfaceCount: Integer): TNetworkNode;
108 function AddSwitch(Name: string; Position: TPoint; InterfaceCount: Integer): TNetworkSwitch;
109 constructor Create;
110 destructor Destroy; override;
111 procedure Paint(Canvas: TCanvas);
112 end;
113
114function NetworkAddress(AParts: array of Integer): TNetworkAddress;
115
116
117implementation
118
119function NetworkAddress(AParts: array of Integer): TNetworkAddress;
120var
121 I: Integer;
122begin
123 SetLength(Result.Parts, Length(AParts));
124 for I := 0 to High(Result.Parts) do
125 Result.Parts[I] := AParts[I];
126end;
127
128{ TNetworkAddress }
129
130class operator TNetworkAddress.Equal(A, B: TNetworkAddress): Boolean;
131var
132 I: Integer;
133begin
134 Result := Length(A.Parts) = Length(B.Parts);
135 if Result then
136 for I := 0 to Length(A.Parts) - 1 do
137 Result := Result and (A.Parts[I] = B.Parts[I]);
138end;
139
140function TNetworkAddress.GetString: string;
141var
142 I: Integer;
143begin
144 Result := '';
145 for I := 0 to Length(Parts) - 1 do begin
146 if I > 0 then Result := Result + '.';
147 Result := Result + IntToStr(Parts[I]);
148 end;
149end;
150
151procedure TNetworkAddress.Clear;
152begin
153 SetLength(Parts, 0);
154end;
155
156{ TNetworkRouter }
157
158procedure TNetworkRouter.ReceivePacket(Sender: TNetworkInterface;
159 Packet: TNetworkPacket);
160var
161 I: Integer;
162begin
163 if Packet.Destination = Sender.Address then
164 DoLog(Self, 'Received ' + Packet.Data + ' from ' + Packet.Source.GetString)
165 else begin
166 if Length(Packet.Destination.Parts) > Packet.Destination.Context then
167 for I := 0 to Interfaces.Count - 1 do
168 with Interfaces[I] do begin
169 if Network = Packet.Destination.Parts[Packet.Destination.Context + 1] then begin
170 //Inc
171 //SendPacket(Packet);
172 Break;
173 end;
174 end;
175 end;
176end;
177
178{ TNetworkSwitch }
179
180procedure TNetworkSwitch.ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket);
181var
182 I: Integer;
183begin
184 for I := 0 to Interfaces.Count - 1 do
185 if Interfaces[I] <> Sender then
186 Interfaces[I].SendPacket(Packet);
187end;
188
189constructor TNetworkSwitch.Create;
190begin
191 inherited Create;
192
193end;
194
195{ TNetwork }
196
197function TNetwork.AddRouter(Name: string; Position: TPoint;
198 InterfaceCount: Integer; Log: TLogEvent): TNetworkRouter;
199var
200 I: Integer;
201begin
202 Result := TNetworkRouter.Create;
203 Result.Name := Name;
204 Result.Position := Position;
205 Result.OnLog := Log;
206 for I := 0 to InterfaceCount - 1 do
207 Result.AddInterface;
208 Nodes.Add(Result);
209end;
210
211function TNetwork.AddHost(Name: string; Position: TPoint;
212 InterfaceCount: Integer; Log: TLogEvent): TNetworkHost;
213var
214 I: Integer;
215begin
216 Result := TNetworkHost.Create;
217 Result.Name := Name;
218 Result.Position := Position;
219 Result.OnLog := Log;
220 for I := 0 to InterfaceCount - 1 do
221 Result.AddInterface;
222 Nodes.Add(Result);
223end;
224
225function TNetwork.AddNode(Name: string; Position: TPoint; InterfaceCount: Integer): TNetworkNode;
226var
227 I: Integer;
228begin
229 Result := TNetworkNode.Create;
230 Result.Name := Name;
231 Result.Position := Position;
232 for I := 0 to InterfaceCount - 1 do
233 Result.AddInterface;
234 Nodes.Add(Result);
235end;
236
237function TNetwork.AddSwitch(Name: string; Position: TPoint; InterfaceCount: Integer
238 ): TNetworkSwitch;
239var
240 I: Integer;
241begin
242 Result := TNetworkSwitch.Create;
243 Result.Name := Name;
244 Result.Position := Position;
245 for I := 0 to InterfaceCount - 1 do
246 Result.AddInterface;
247 Nodes.Add(Result);
248end;
249
250constructor TNetwork.Create;
251begin
252 Nodes := TFPGObjectList<TNetworkNode>.Create;
253end;
254
255destructor TNetwork.Destroy;
256begin
257 Nodes.Free;
258 inherited Destroy;
259end;
260
261procedure TNetwork.Paint(Canvas: TCanvas);
262var
263 I: Integer;
264 J: Integer;
265 RemoteInterface: TNetworkInterface;
266 RemoteInterfaceIndex: Integer;
267 RemoteNode: TNetworkNode;
268const
269 R = 30;
270begin
271 Canvas.Pen.Color := clRed;
272 Canvas.Pen.Style := psSolid;
273
274 for I := 0 to Nodes.Count - 1 do
275 with TNetworkNode(Nodes[I]) do begin
276 for J := 0 to Interfaces.Count - 1 do
277 Canvas.Rectangle(Position.X - R * Interfaces.Count div 2 + J * R, Position.Y - R div 2,
278 Position.X - R * Interfaces.Count div 2 + J * R + R, Position.Y + R div 2);
279 Canvas.TextOut(Position.X - Canvas.TextWidth(Name) div 2, Position.Y + R div 2, Name);
280 end;
281 for I := 0 to Nodes.Count - 1 do
282 with TNetworkNode(Nodes[I]) do begin
283 for J := 0 to Interfaces.Count - 1 do
284 if Assigned(Interfaces[J]) then begin
285 if Assigned(Interfaces[J].Remote) then begin
286 RemoteInterface := Interfaces[J].Remote;
287 RemoteNode := RemoteInterface.Node;
288 RemoteInterfaceIndex := RemoteNode.Interfaces.IndexOf(RemoteInterface);
289 Canvas.Line(Position.X + J * R - R * Interfaces.Count div 2 + R div 2, Position.Y,
290 RemoteInterface.Node.Position.X + RemoteInterfaceIndex * R - R *
291 RemoteNode.Interfaces.Count div 2 + R div 2, RemoteNode.Position.Y);
292 end;
293 end;
294 end;
295 for I := 0 to Nodes.Count - 1 do
296 with TNetworkNode(Nodes[I]) do begin
297 for J := 0 to Interfaces.Count - 1 do
298 if Assigned(Interfaces[J]) then begin
299 //if Interfaces[J].Address > 0 then
300 Canvas.TextOut(Position.X + J * R - R * Interfaces.Count div 2 + R div 2 - Canvas.TextWidth(Interfaces[J].Address.GetString) div 2,
301 Position.Y - Canvas.TextHeight(Interfaces[J].Address.GetString) div 2,
302 Interfaces[J].Address.GetString);
303 //if Interfaces[J].Network > 0 then
304 Canvas.TextOut(Position.X + J * R - R * Interfaces.Count div 2 + R div 2 - Canvas.TextWidth(IntToStr(Interfaces[J].Network)) div 2,
305 Position.Y - R - Canvas.TextHeight(IntToStr(Interfaces[J].Network)) div 2,
306 IntToStr(Interfaces[J].Network));
307 end;
308 end;
309end;
310
311{ TNetworkNode }
312
313procedure TNetworkNode.ReceivePacket(Sender: TNetworkInterface; Packet: TNetworkPacket
314 );
315begin
316end;
317
318procedure TNetworkHost.ReceivePacket(Sender: TNetworkInterface;
319 Packet: TNetworkPacket);
320begin
321 if Packet.Destination = Sender.Address then
322 DoLog(Self, 'Received ' + Packet.Data + ' from ' + Packet.Source.GetString);
323end;
324
325procedure TNetworkHost.DoLog(Sender: TNetworkNode; Data: string);
326begin
327 if Assigned(FOnLog) then FOnLog(Sender, Data);
328end;
329
330procedure TNetworkHost.Ping(Address: TNetworkAddress);
331var
332 NewPacket: TNetworkPacket;
333 UseInterface: TNetworkInterface;
334begin
335 UseInterface := TNetworkInterface(Interfaces[0]);
336 NewPacket := TNetworkPacket.Create;
337 NewPacket.Source := UseInterface.Address;
338 NewPacket.Destination := Address;
339 NewPacket.Data := 'ping';
340 DoLog(Self, 'Sent ping to address ' + Address.GetString);
341 UseInterface.SendPacket(NewPacket);
342 NewPacket.Free;
343end;
344
345function TNetworkNode.AddInterface: TNetworkInterface;
346begin
347 Result := TNetworkInterface.Create;
348 Result.Node := Self;
349 Result.Address.Clear;
350 Result.OnReceivePacket := ReceivePacket;
351 Interfaces.Add(Result);
352end;
353
354constructor TNetworkNode.Create;
355begin
356 Interfaces := TFPGObjectList<TNetworkInterface>.Create;
357end;
358
359destructor TNetworkNode.Destroy;
360begin
361 Interfaces.Free;
362 inherited Destroy;
363end;
364
365{ TNetworkInterface }
366
367procedure TNetworkInterface.SetRemote(AValue: TNetworkInterface);
368begin
369 if FRemote = AValue then Exit;
370 if Assigned(FRemote) then begin
371 FRemote.FRemote := nil;
372 end;
373 if Assigned(AValue) then begin
374 if Assigned(AValue.FRemote) then
375 AValue.FRemote.FRemote := nil;
376 AValue.FRemote := Self;
377 end;
378 FRemote := AValue;
379end;
380
381procedure TNetworkInterface.ReceivePacket(Packet: TNetworkPacket);
382begin
383 if Assigned(FOnReceivePacket) then
384 FOnReceivePacket(Self, Packet);
385end;
386
387procedure TNetworkInterface.Connect(Remote: TNetworkInterface);
388begin
389 Self.Remote := Remote;
390end;
391
392procedure TNetworkInterface.Disconnet;
393begin
394 Remote := nil;
395end;
396
397function TNetworkInterface.GetConnected: Boolean;
398begin
399 Result := Assigned(FRemote);
400end;
401
402procedure TNetworkInterface.SendPacket(Packet: TNetworkPacket);
403begin
404 if Assigned(Remote) then Remote.ReceivePacket(Packet);
405end;
406
407constructor TNetworkInterface.Create;
408begin
409 FRemote := nil;
410 Address.Clear;
411end;
412
413destructor TNetworkInterface.Destroy;
414begin
415 inherited Destroy;
416end;
417
418end.
419
Note: See TracBrowser for help on using the repository browser.