lnet.pp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. { lNet v0.4.0
  2. CopyRight (C) 2004-2006 Ales Katona
  3. This library is Free software; you can rediStribute it and/or modify it
  4. under the terms of the GNU Library General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or (at your
  6. option) any later version.
  7. This program is diStributed in the hope that it will be useful, but WITHOUT
  8. ANY WARRANTY; withOut even the implied warranty of MERCHANTABILITY or
  9. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  10. for more details.
  11. You should have received a Copy of the GNU Library General Public License
  12. along with This library; if not, Write to the Free Software Foundation,
  13. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. This license has been modified. See File LICENSE.ADDON for more inFormation.
  15. Should you find these sources without a LICENSE File, please contact
  16. me at [email protected]
  17. }
  18. unit lNet;
  19. {$mode objfpc}{$H+}{$T-}
  20. {$interfaces corba}
  21. interface
  22. uses
  23. Classes, lEvents,
  24. {$i sys/osunits.inc}
  25. const
  26. { Address constants }
  27. LADDR_ANY = '0.0.0.0';
  28. LADDR_BR = '255.255.255.255';
  29. LADDR_LO = '127.0.0.1';
  30. { ICMP }
  31. LICMP_ECHOREPLY = 0;
  32. LICMP_UNREACH = 3;
  33. LICMP_ECHO = 8;
  34. LICMP_TIME_EXCEEDED = 11;
  35. { Protocols }
  36. LPROTO_IP = 0;
  37. LPROTO_ICMP = 1;
  38. LPROTO_IGMP = 2;
  39. LPROTO_TCP = 6;
  40. LPROTO_UDP = 17;
  41. LPROTO_IPV6 = 41;
  42. LPROTO_ICMPV6 = 58;
  43. LPROTO_RAW = 255;
  44. LPROTO_MAX = 256;
  45. type
  46. PLIPHeader = ^TLIPHeader;
  47. TLIPHeader = record
  48. VerLen : Byte;
  49. TOS : Byte;
  50. TotalLen : Word;
  51. Identifer : Word;
  52. FragOffsets : Word;
  53. TTL : Byte;
  54. Protocol : Byte;
  55. CheckSum : Word;
  56. SourceIp : DWord;
  57. DestIp : DWord;
  58. Options : DWord;
  59. end; // TLIPHeader
  60. TLSocket = class;
  61. TLComponent = class;
  62. { Callback Event procedure for errors }
  63. TLSocketErrorEvent = procedure(const msg: string; aSocket: TLSocket) of object;
  64. { Callback Event procedure for others }
  65. TLSocketEvent = procedure(aSocket: TLSocket) of object;
  66. { Callback Event procedure for progress reports}
  67. TLSocketProgressEvent = procedure (aSocket: TLSocket; const Bytes: Integer) of object;
  68. { Base socket class, Holds Address and socket info, perForms basic
  69. socket operations, uses select always to figure out if it can work (slow) }
  70. { TLSocket }
  71. TLSocket = class(TLHandle)
  72. protected
  73. FAddress: TInetSockAddr;
  74. FPeerAddress: TInetSockAddr;
  75. FConnected: Boolean;
  76. FConnecting: Boolean;
  77. FSocketClass: Integer;
  78. FProtocol: Integer;
  79. FNextSock: TLSocket;
  80. FPrevSock: TLSocket;
  81. FIgnoreShutdown: Boolean;
  82. FCanSend: Boolean;
  83. FCanReceive: Boolean;
  84. FServerSocket: Boolean;
  85. FOnFree: TLSocketEvent;
  86. FBlocking: Boolean;
  87. FListenBacklog: Integer;
  88. FCreator: TLComponent;
  89. protected
  90. function DoSend(const TheData; const TheSize: Integer): Integer;
  91. function SetupSocket(const APort: Word; const Address: string): Boolean; virtual;
  92. function GetLocalPort: Word;
  93. function GetPeerPort: Word;
  94. function GetPeerAddress: string;
  95. function GetLocalAddress: string;
  96. function CanSend: Boolean; virtual;
  97. function CanReceive: Boolean; virtual;
  98. procedure SetBlocking(const aValue: Boolean);
  99. procedure SetOptions; virtual;
  100. function Bail(const msg: string; const ernum: Integer): Boolean;
  101. procedure LogError(const msg: string; const ernum: Integer); virtual;
  102. public
  103. constructor Create; override;
  104. destructor Destroy; override;
  105. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  106. function Accept(const SerSock: Integer): Boolean;
  107. function Connect(const Address: string; const APort: Word): Boolean;
  108. function Send(const aData; const aSize: Integer): Integer; virtual;
  109. function SendMessage(const msg: string): Integer;
  110. function Get(var aData; const aSize: Integer): Integer; virtual;
  111. function GetMessage(out msg: string): Integer;
  112. procedure Disconnect; virtual;
  113. public
  114. property Connected: Boolean read FConnected;
  115. property Connecting: Boolean read FConnecting;
  116. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  117. property Protocol: Integer read FProtocol write FProtocol;
  118. property SocketType: Integer read FSocketClass write FSocketClass;
  119. property Blocking: Boolean read FBlocking write SetBlocking;
  120. property PeerAddress: string read GetPeerAddress;
  121. property PeerPort: Word read GetPeerPort;
  122. property LocalAddress: string read GetLocalAddress;
  123. property LocalPort: Word read GetLocalPort;
  124. property NextSock: TLSocket read FNextSock write FNextSock;
  125. property PrevSock: TLSocket read FPrevSock write FPrevSock;
  126. property Creator: TLComponent read FCreator;
  127. end;
  128. TLSocketClass = class of TLSocket;
  129. { this is the socket used by TLConnection }
  130. TLActionEnum = (acConnect, acAccept, acSend, acReceive, acError);
  131. { Base interface common to ALL connections }
  132. ILComponent = interface
  133. procedure Disconnect;
  134. procedure CallAction;
  135. property SocketClass: TLSocketClass;
  136. property Host: string;
  137. property Port: Word;
  138. end;
  139. { Interface for protools with direct send/get capabilities }
  140. ILDirect = interface
  141. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer;
  142. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer;
  143. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer;
  144. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer;
  145. end;
  146. { Interface for all servers }
  147. ILServer = interface
  148. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  149. end;
  150. { Interface for all clients }
  151. ILClient = interface
  152. function Connect(const Address: string; const APort: Word): Boolean; overload;
  153. function Connect: Boolean; overload;
  154. end;
  155. { TLComponent }
  156. TLComponent = class(TComponent, ILComponent)
  157. protected
  158. FHost: string;
  159. FPort: Word;
  160. FSocketClass: TLSocketClass;
  161. FCreator: TLComponent;
  162. public
  163. constructor Create(aOwner: TComponent); override;
  164. procedure Disconnect; virtual; abstract;
  165. procedure CallAction; virtual; abstract;
  166. property SocketClass: TLSocketClass read FSocketClass write FSocketClass;
  167. property Host: string read FHost write FHost;
  168. property Port: Word read FPort write FPort;
  169. property Creator: TLComponent read FCreator write FCreator;
  170. end;
  171. { TLConnection
  172. Common ancestor for TLBaseTcp and TLUdp classes. Holds Event properties
  173. and common variables. }
  174. TLConnection = class(TLComponent, ILDirect, ILServer, ILClient)
  175. protected
  176. FTimeVal: TTimeVal;
  177. FOnReceive: TLSocketEvent;
  178. FOnAccept: TLSocketEvent;
  179. FOnConnect: TLSocketEvent;
  180. FOnDisconnect: TLSocketEvent;
  181. FOnCanSend: TLSocketEvent;
  182. FOnError: TLSocketErrorEvent;
  183. FRootSock: TLSocket;
  184. FIterator: TLSocket;
  185. FID: Integer; // internal number for server
  186. FEventer: TLEventer;
  187. FEventerClass: TLEventerClass;
  188. FTimeout: DWord;
  189. FListenBacklog: Integer;
  190. protected
  191. function InitSocket(aSocket: TLSocket): TLSocket; virtual;
  192. function GetConnected: Boolean; virtual; abstract;
  193. function GetCount: Integer; virtual;
  194. function GetItem(const i: Integer): TLSocket;
  195. function GetTimeout: DWord;
  196. procedure SetTimeout(const AValue: DWord);
  197. procedure SetEventer(Value: TLEventer);
  198. procedure ConnectAction(aSocket: TLHandle); virtual;
  199. procedure AcceptAction(aSocket: TLHandle); virtual;
  200. procedure ReceiveAction(aSocket: TLHandle); virtual;
  201. procedure SendAction(aSocket: TLHandle); virtual;
  202. procedure ErrorAction(aSocket: TLHandle; const msg: string); virtual;
  203. procedure ConnectEvent(aSocket: TLHandle); virtual;
  204. procedure DisconnectEvent(aSocket: TLHandle); virtual;
  205. procedure AcceptEvent(aSocket: TLHandle); virtual;
  206. procedure ReceiveEvent(aSocket: TLHandle); virtual;
  207. procedure CanSendEvent(aSocket: TLHandle); virtual;
  208. procedure ErrorEvent(const msg: string; aSocket: TLHandle); virtual;
  209. procedure EventerError(const msg: string; Sender: TLEventer);
  210. procedure RegisterWithEventer; virtual;
  211. procedure FreeSocks; virtual;
  212. public
  213. constructor Create(aOwner: TComponent); override;
  214. destructor Destroy; override;
  215. function Connect(const Address: string; const APort: Word): Boolean; virtual; overload;
  216. function Connect: Boolean; virtual; overload;
  217. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; virtual; abstract; overload;
  218. function Listen: Boolean; virtual; overload;
  219. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; virtual; abstract;
  220. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; virtual; abstract;
  221. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; virtual; abstract;
  222. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; virtual; abstract;
  223. function IterNext: Boolean; virtual; abstract;
  224. procedure IterReset; virtual; abstract;
  225. public
  226. property Host: string read FHost write FHost;
  227. property Port: Word read FPort write FPort;
  228. property OnError: TLSocketErrorEvent read FOnError write FOnError;
  229. property OnReceive: TLSocketEvent read FOnReceive write FOnReceive;
  230. property OnDisconnect: TLSocketEvent read FOnDisconnect write FOnDisconnect;
  231. property OnCanSend: TLSocketEvent read FOnCanSend write FOnCanSend;
  232. property Socks[index: Integer]: TLSocket read GetItem; default;
  233. property Count: Integer read GetCount;
  234. property Connected: Boolean read GetConnected;
  235. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  236. property Iterator: TLSocket read FIterator;
  237. property Timeout: DWord read GetTimeout write SetTimeout;
  238. property SocketClass: TLSocketClass read FSocketClass write FSocketClass;
  239. property Eventer: TLEventer read FEventer write SetEventer;
  240. property EventerClass: TLEventerClass read FEventerClass write FEventerClass;
  241. end;
  242. { UDP Client/Server class. Provided to enable usage of UDP sockets }
  243. { TLUdp }
  244. TLUdp = class(TLConnection)
  245. protected
  246. function InitSocket(aSocket: TLSocket): TLSocket; override;
  247. function GetConnected: Boolean; override;
  248. procedure ReceiveAction(aSocket: TLHandle); override;
  249. procedure SendAction(aSocket: TLHandle); override;
  250. procedure ErrorAction(aSocket: TLHandle; const msg: string); override;
  251. function Bail(const msg: string): Boolean;
  252. procedure SetAddress(const Address: string);
  253. public
  254. constructor Create(aOwner: TComponent); override;
  255. function Connect(const Address: string; const APort: Word): Boolean; override;
  256. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; override;
  257. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  258. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; override;
  259. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; override;
  260. function SendMessage(const msg: string; const Address: string): Integer; overload;
  261. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  262. function Send(const aData; const aSize: Integer; const Address: string): Integer; overload;
  263. function IterNext: Boolean; override;
  264. procedure IterReset; override;
  265. procedure Disconnect; override;
  266. procedure CallAction; override;
  267. end;
  268. { TCP Client/Server class. Provided to enable usage of TCP sockets }
  269. { TLTcp }
  270. TLTcp = class(TLConnection)
  271. protected
  272. FCount: Integer;
  273. function InitSocket(aSocket: TLSocket): TLSocket; override;
  274. function GetConnected: Boolean; override;
  275. function GetConnecting: Boolean;
  276. procedure ConnectAction(aSocket: TLHandle); override;
  277. procedure AcceptAction(aSocket: TLHandle); override;
  278. procedure ReceiveAction(aSocket: TLHandle); override;
  279. procedure SendAction(aSocket: TLHandle); override;
  280. procedure ErrorAction(aSocket: TLHandle; const msg: string); override;
  281. function Bail(const msg: string; aSocket: TLSocket): Boolean;
  282. procedure SocketDisconnect(aSocket: TLSocket);
  283. public
  284. constructor Create(aOwner: TComponent); override;
  285. function Connect(const Address: string; const APort: Word): Boolean; override;
  286. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; override;
  287. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  288. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; override;
  289. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  290. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; override;
  291. function IterNext: Boolean; override;
  292. procedure IterReset; override;
  293. procedure CallAction; override;
  294. procedure Disconnect; override;
  295. public
  296. property Connecting: Boolean read GetConnecting;
  297. property OnAccept: TLSocketEvent read FOnAccept write FOnAccept;
  298. property OnConnect: TLSocketEvent read FOnConnect write FOnConnect;
  299. end;
  300. implementation
  301. uses
  302. lCommon;
  303. //********************************TLSocket*************************************
  304. constructor TLSocket.Create;
  305. begin
  306. inherited Create;
  307. FHandle := INVALID_SOCKET;
  308. FBlocking := False;
  309. FListenBacklog := LDEFAULT_BACKLOG;
  310. FServerSocket := False;
  311. FPrevSock := nil;
  312. FNextSock := nil;
  313. FCanSend := True;
  314. FCanReceive := False;
  315. FConnected := False;
  316. FConnecting := False;
  317. FIgnoreShutdown := False;
  318. FSocketClass := SOCK_STREAM;
  319. FProtocol := LPROTO_TCP;
  320. end;
  321. destructor TLSocket.Destroy;
  322. begin
  323. if Assigned(FOnFree) then
  324. FOnFree(Self);
  325. Disconnect;
  326. inherited Destroy;
  327. end;
  328. procedure TLSocket.Disconnect;
  329. var
  330. WasConnected: Boolean;
  331. begin
  332. WasConnected := FConnected;
  333. FDispose := True;
  334. FCanSend := True;
  335. FCanReceive := True;
  336. FIgnoreWrite := True;
  337. if FConnected or FConnecting then begin
  338. FConnected := False;
  339. FConnecting := False;
  340. if (FSocketClass = SOCK_STREAM) and (not FIgnoreShutdown) and WasConnected then
  341. if ShutDown(FHandle, 2) <> 0 then
  342. LogError('Shutdown error', LSocketError);
  343. if CloseSocket(FHandle) <> 0 then
  344. LogError('Closesocket error', LSocketError);
  345. FHandle := INVALID_SOCKET;
  346. end;
  347. end;
  348. procedure TLSocket.LogError(const msg: string; const ernum: Integer);
  349. begin
  350. if Assigned(FOnError) then
  351. if ernum > 0 then
  352. FOnError(Self, msg + '[' + IntToStr(ernum) + ']: ' + LStrError(ernum))
  353. else
  354. FOnError(Self, msg);
  355. end;
  356. function TLSocket.Bail(const msg: string; const ernum: Integer): Boolean;
  357. begin
  358. Result := False; // return the result for the caller
  359. Disconnect;
  360. LogError(msg, ernum);
  361. end;
  362. function TLSocket.GetPeerAddress: string;
  363. begin
  364. Result := '';
  365. if FSocketClass = SOCK_STREAM then
  366. Result := NetAddrtoStr(FAddress.Addr)
  367. else
  368. Result := NetAddrtoStr(FPeerAddress.Addr);
  369. end;
  370. function TLSocket.GetLocalAddress: string;
  371. var
  372. a: TSockAddr;
  373. l: Integer;
  374. begin
  375. l := SizeOf(a);
  376. GetSocketName(FHandle, a, l);
  377. Result := HostAddrToStr(LongWord(a.sin_addr));
  378. end;
  379. function TLSocket.CanSend: Boolean;
  380. begin
  381. Result := FCanSend and FConnected;
  382. end;
  383. function TLSocket.CanReceive: Boolean;
  384. begin
  385. Result := FCanReceive and FConnected;
  386. end;
  387. procedure TLSocket.SetBlocking(const aValue: Boolean);
  388. begin
  389. FBlocking := aValue;
  390. if FHandle >= 0 then // we already set our socket
  391. if not lCommon.SetBlocking(FHandle, aValue) then
  392. Bail('Error on SetBlocking', LSocketError);
  393. end;
  394. procedure TLSocket.SetOptions;
  395. begin
  396. SetBlocking(FBlocking);
  397. end;
  398. function TLSocket.GetMessage(out msg: string): Integer;
  399. begin
  400. Result := 0;
  401. SetLength(msg, BUFFER_SIZE);
  402. SetLength(msg, Get(PChar(msg)^, Length(msg)));
  403. Result := Length(msg);
  404. end;
  405. function TLSocket.Get(var aData; const aSize: Integer): Integer;
  406. var
  407. AddressLength: Integer = SizeOf(FAddress);
  408. begin
  409. Result := 0;
  410. if CanReceive then begin
  411. if FSocketClass = SOCK_STREAM then
  412. Result := sockets.Recv(FHandle, aData, aSize, LMSG)
  413. else
  414. Result := sockets.Recvfrom(FHandle, aData, aSize, LMSG, FPeerAddress, AddressLength);
  415. if Result = 0 then
  416. Disconnect;
  417. if Result = SOCKET_ERROR then begin
  418. if IsBlockError(LSocketError) then begin
  419. FCanReceive := False;
  420. IgnoreRead := False;
  421. end else Bail('Receive Error', LSocketError);
  422. Result := 0;
  423. end;
  424. end;
  425. end;
  426. function TLSocket.DoSend(const TheData; const TheSize: Integer): Integer;
  427. begin
  428. if FSocketClass = SOCK_STREAM then
  429. Result := sockets.send(FHandle, TheData, TheSize, LMSG)
  430. else
  431. Result := sockets.sendto(FHandle, TheData, TheSize, LMSG, FPeerAddress, SizeOf(FPeerAddress));
  432. end;
  433. function TLSocket.SetupSocket(const APort: Word; const Address: string): Boolean;
  434. var
  435. Done: Boolean;
  436. Arg: Integer;
  437. begin
  438. Result := false;
  439. if not FConnected and not FConnecting then begin
  440. Done := true;
  441. FHandle := fpSocket(AF_INET, FSocketClass, FProtocol);
  442. if FHandle = INVALID_SOCKET then
  443. Bail('Socket error', LSocketError);
  444. SetOptions;
  445. if FSocketClass = SOCK_DGRAM then begin
  446. Arg := 1;
  447. if SetSocketOptions(FHandle, SOL_SOCKET, SO_BROADCAST, Arg, Sizeof(Arg)) = SOCKET_ERROR then
  448. Bail('SetSockOpt error', LSocketError);
  449. end;
  450. FillAddressInfo(FAddress, AF_INET, Address, aPort);
  451. FillAddressInfo(FPeerAddress, AF_INET, LADDR_BR, aPort);
  452. Result := Done;
  453. end;
  454. end;
  455. function TLSocket.GetLocalPort: Word;
  456. begin
  457. Result := FAddress.sin_port;
  458. end;
  459. function TLSocket.GetPeerPort: Word;
  460. begin
  461. Result := ntohs(FPeerAddress.sin_port);
  462. end;
  463. function TLSocket.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  464. begin
  465. if not Connected then begin
  466. Result := false;
  467. SetupSocket(APort, AIntf);
  468. if fpBind(FHandle, psockaddr(@FAddress), SizeOf(FAddress)) = SOCKET_ERROR then
  469. Bail('Error on bind', LSocketError)
  470. else
  471. Result := true;
  472. if (FSocketClass = SOCK_STREAM) and Result then
  473. if fpListen(FHandle, FListenBacklog) = SOCKET_ERROR then
  474. Result := Bail('Error on Listen', LSocketError)
  475. else
  476. Result := true;
  477. end;
  478. end;
  479. function TLSocket.Accept(const sersock: Integer): Boolean;
  480. var
  481. AddressLength: tsocklen = SizeOf(FAddress);
  482. begin
  483. Result := false;
  484. if not Connected then begin
  485. FHandle := fpAccept(sersock, psockaddr(@FAddress), @AddressLength);
  486. if FHandle <> INVALID_SOCKET then begin
  487. SetOptions;
  488. Result := true;
  489. FConnected := true;
  490. end else
  491. Bail('Error on accept', LSocketError);
  492. end;
  493. end;
  494. function TLSocket.Connect(const Address: string; const aPort: Word): Boolean;
  495. begin
  496. Result := False;
  497. if Connected or FConnecting then
  498. Disconnect;
  499. if SetupSocket(APort, Address) then begin
  500. fpConnect(FHandle, psockaddr(@FAddress), SizeOf(FAddress));
  501. FConnecting := True;
  502. Result := FConnecting;
  503. end;
  504. end;
  505. function TLSocket.SendMessage(const msg: string): Integer;
  506. begin
  507. Result := Send(PChar(msg)^, Length(msg));
  508. end;
  509. function TLSocket.Send(const aData; const aSize: Integer): Integer;
  510. begin
  511. Result := 0;
  512. if not FServerSocket then begin
  513. if aSize <= 0 then
  514. Bail('Send error: wrong size (Size <= 0)', -1);
  515. if CanSend then begin
  516. Result := DoSend(aData, aSize);
  517. if Result = SOCKET_ERROR then begin
  518. if IsBlockError(LSocketError) then begin
  519. FCanSend := False;
  520. IgnoreWrite := False;
  521. end else
  522. Bail('Send error', LSocketError);
  523. Result := 0;
  524. end;
  525. end;
  526. end;
  527. end;
  528. //*******************************TLConnection*********************************
  529. constructor TLConnection.Create(aOwner: TComponent);
  530. begin
  531. inherited Create(aOwner);
  532. FHost := '';
  533. FPort := 0;
  534. FListenBacklog := LDEFAULT_BACKLOG;
  535. FTimeout := 0;
  536. FSocketClass := TLSocket;
  537. FOnReceive := nil;
  538. FOnError := nil;
  539. FOnDisconnect := nil;
  540. FOnCanSend := nil;
  541. FOnConnect := nil;
  542. FOnAccept := nil;
  543. FTimeVal.tv_sec := 0;
  544. FTimeVal.tv_usec := 0;
  545. FIterator := nil;
  546. FEventer := nil;
  547. FEventerClass := BestEventerClass;
  548. end;
  549. destructor TLConnection.Destroy;
  550. begin
  551. FreeSocks;
  552. if Assigned(FEventer) then
  553. FEventer.DeleteRef;
  554. inherited Destroy;
  555. end;
  556. function TLConnection.Connect(const Address: string; const APort: Word
  557. ): Boolean;
  558. begin
  559. FHost := Address;
  560. FPort := aPort;
  561. Result := False;
  562. end;
  563. function TLConnection.Connect: Boolean;
  564. begin
  565. Result := Connect(FHost, FPort);
  566. end;
  567. function TLConnection.Listen: Boolean;
  568. begin
  569. Result := Listen(FPort, FHost);
  570. end;
  571. function TLConnection.InitSocket(aSocket: TLSocket): TLSocket;
  572. begin
  573. aSocket.OnRead := @ReceiveAction;
  574. aSocket.OnWrite := @SendAction;
  575. aSocket.OnError := @ErrorAction;
  576. aSocket.ListenBacklog := FListenBacklog;
  577. aSocket.FCreator := FCreator;
  578. Result := aSocket;
  579. end;
  580. function TLConnection.GetCount: Integer;
  581. begin
  582. Result := 1;
  583. end;
  584. function TLConnection.GetItem(const i: Integer): TLSocket;
  585. var
  586. Tmp: TLSocket;
  587. Jumps: Integer;
  588. begin
  589. Result := nil;
  590. Tmp := FRootSock;
  591. Jumps := 0;
  592. while Assigned(Tmp.NextSock) and (Jumps < i) do begin
  593. Tmp := Tmp.NextSock;
  594. Inc(Jumps);
  595. end;
  596. if Jumps = i then
  597. Result := Tmp;
  598. end;
  599. function TLConnection.GetTimeout: DWord;
  600. begin
  601. if Assigned(FEventer) then
  602. Result := FEventer.Timeout
  603. else
  604. Result := FTimeout;
  605. end;
  606. procedure TLConnection.ConnectAction(aSocket: TLHandle);
  607. begin
  608. end;
  609. procedure TLConnection.AcceptAction(aSocket: TLHandle);
  610. begin
  611. end;
  612. procedure TLConnection.ReceiveAction(aSocket: TLHandle);
  613. begin
  614. end;
  615. procedure TLConnection.SendAction(aSocket: TLHandle);
  616. begin
  617. end;
  618. procedure TLConnection.ErrorAction(aSocket: TLHandle; const msg: string);
  619. begin
  620. end;
  621. procedure TLConnection.ConnectEvent(aSocket: TLHandle);
  622. begin
  623. if Assigned(FOnConnect) then
  624. FOnConnect(TLSocket(aSocket));
  625. end;
  626. procedure TLConnection.DisconnectEvent(aSocket: TLHandle);
  627. begin
  628. if Assigned(FOnDisconnect) then
  629. FOnDisconnect(TLSocket(aSocket));
  630. end;
  631. procedure TLConnection.AcceptEvent(aSocket: TLHandle);
  632. begin
  633. if Assigned(FOnAccept) then
  634. FOnAccept(TLSocket(aSocket));
  635. end;
  636. procedure TLConnection.ReceiveEvent(aSocket: TLHandle);
  637. begin
  638. if Assigned(FOnReceive) then
  639. FOnReceive(TLSocket(aSocket));
  640. end;
  641. procedure TLConnection.CanSendEvent(aSocket: TLHandle);
  642. begin
  643. if Assigned(FOnCanSend) then
  644. FOnCanSend(TLSocket(aSocket));
  645. end;
  646. procedure TLConnection.ErrorEvent(const msg: string; aSocket: TLHandle);
  647. begin
  648. if Assigned(FOnError) then
  649. FOnError(msg, TLSocket(aSocket));
  650. end;
  651. procedure TLConnection.SetTimeout(const AValue: DWord);
  652. begin
  653. if Assigned(FEventer) then
  654. FEventer.Timeout := aValue;
  655. FTimeout := aValue;
  656. end;
  657. procedure TLConnection.SetEventer(Value: TLEventer);
  658. begin
  659. if Assigned(FEventer) then
  660. FEventer.DeleteRef;
  661. FEventer := Value;
  662. FEventer.AddRef;
  663. end;
  664. procedure TLConnection.EventerError(const msg: string; Sender: TLEventer);
  665. begin
  666. ErrorEvent(msg, nil);
  667. end;
  668. procedure TLConnection.RegisterWithEventer;
  669. begin
  670. if not Assigned(FEventer) then begin
  671. FEventer := FEventerClass.Create;
  672. FEventer.OnError := @EventerError;
  673. end;
  674. if Assigned(FRootSock) then
  675. FEventer.AddHandle(FRootSock);
  676. if (FEventer.Timeout = 0) and (FTimeout > 0) then
  677. FEventer.Timeout := FTimeout
  678. else
  679. FTimeout := FEventer.Timeout;
  680. end;
  681. procedure TLConnection.FreeSocks;
  682. var
  683. Tmp, Tmp2: TLSocket;
  684. begin
  685. Tmp := FRootSock;
  686. while Assigned(Tmp) do begin
  687. Tmp2 := Tmp;
  688. Tmp := Tmp.NextSock;
  689. Tmp2.Free;
  690. end;
  691. end;
  692. //*******************************TLUdp*********************************
  693. constructor TLUdp.Create(aOwner: TComponent);
  694. begin
  695. inherited Create(aOwner);
  696. FTimeVal.tv_usec := 0;
  697. FTimeVal.tv_sec := 0;
  698. end;
  699. procedure TLUdp.Disconnect;
  700. begin
  701. if Assigned(FRootSock) then begin
  702. FRootSock.Disconnect;
  703. FreeAndNil(FRootSock);
  704. end;
  705. end;
  706. function TLUdp.Connect(const Address: string; const APort: Word): Boolean;
  707. begin
  708. Result := inherited Connect(Address, aPort);
  709. if Assigned(FRootSock) and FRootSock.Connected then
  710. Disconnect;
  711. FRootSock := InitSocket(FSocketClass.Create);
  712. FIterator := FRootSock;
  713. Result := FRootSock.SetupSocket(APort, LADDR_ANY);
  714. FillAddressInfo(FRootSock.FPeerAddress, AF_INET, Address, aPort);
  715. FRootSock.FConnected := true;
  716. if Result then
  717. RegisterWithEventer;
  718. end;
  719. function TLUdp.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  720. begin
  721. Result := False;
  722. if Assigned(FRootSock) and FRootSock.Connected then
  723. Disconnect;
  724. FRootSock := InitSocket(FSocketClass.Create);
  725. FIterator := FRootSock;
  726. if FRootSock.Listen(APort, AIntf) then begin
  727. FillAddressInfo(FRootSock.FPeerAddress, AF_INET, LADDR_BR, aPort);
  728. FRootSock.FConnected := True;
  729. RegisterWithEventer;
  730. end;
  731. Result := FRootSock.Connected;
  732. end;
  733. function TLUdp.Bail(const msg: string): Boolean;
  734. begin
  735. Result := False;
  736. Disconnect;
  737. ErrorEvent(msg, FRootSock);
  738. end;
  739. procedure TLUdp.SetAddress(const Address: string);
  740. var
  741. n: Integer;
  742. s: string;
  743. p: Word;
  744. begin
  745. n := Pos(':', Address);
  746. if n > 0 then begin
  747. s := Copy(Address, 1, n-1);
  748. p := Word(StrToInt(Copy(Address, n+1, Length(Address))));
  749. FillAddressInfo(FRootSock.FPeerAddress, AF_INET, s, p);
  750. end else
  751. FillAddressInfo(FRootSock.FPeerAddress, AF_INET, Address,
  752. FRootSock.PeerPort);
  753. end;
  754. function TLUdp.InitSocket(aSocket: TLSocket): TLSocket;
  755. begin
  756. Result := FRootSock;
  757. if not Assigned(FRootSock) then begin
  758. Result := inherited InitSocket(aSocket);
  759. aSocket.SocketType := SOCK_DGRAM;
  760. aSocket.Protocol := LPROTO_UDP;
  761. end;
  762. end;
  763. procedure TLUdp.ReceiveAction(aSocket: TLHandle);
  764. begin
  765. with TLSocket(aSocket) do begin
  766. FCanReceive := True;
  767. ReceiveEvent(aSocket);
  768. end;
  769. end;
  770. procedure TLUdp.SendAction(aSocket: TLHandle);
  771. begin
  772. with TLSocket(aSocket) do begin
  773. FCanSend := True;
  774. IgnoreWrite := True;
  775. CanSendEvent(aSocket);
  776. end;
  777. end;
  778. procedure TLUdp.ErrorAction(aSocket: TLHandle; const msg: string);
  779. begin
  780. Bail(msg);
  781. end;
  782. function TLUdp.IterNext: Boolean;
  783. begin
  784. Result := False;
  785. end;
  786. procedure TLUdp.IterReset;
  787. begin
  788. end;
  789. procedure TLUdp.CallAction;
  790. begin
  791. if Assigned(FEventer) then
  792. FEventer.CallAction;
  793. end;
  794. function TLUdp.GetConnected: Boolean;
  795. begin
  796. Result := False;
  797. if Assigned(FRootSock) then
  798. Result := FRootSock.Connected;
  799. end;
  800. function TLUdp.Get(var aData; const aSize: Integer; aSocket: TLSocket): Integer;
  801. begin
  802. Result := 0;
  803. if Assigned(FRootSock) then
  804. Result := FRootSock.Get(aData, aSize);
  805. end;
  806. function TLUdp.GetMessage(out msg: string; aSocket: TLSocket): Integer;
  807. begin
  808. Result := 0;
  809. if Assigned(FRootSock) then
  810. Result := FRootSock.GetMessage(msg);
  811. end;
  812. function TLUdp.SendMessage(const msg: string; aSocket: TLSocket = nil): Integer;
  813. begin
  814. Result := 0;
  815. if Assigned(FRootSock) then
  816. Result := FRootSock.SendMessage(msg)
  817. end;
  818. function TLUdp.SendMessage(const msg: string; const Address: string): Integer;
  819. begin
  820. Result := 0;
  821. if Assigned(FRootSock) then begin
  822. SetAddress(Address);
  823. Result := FRootSock.SendMessage(msg)
  824. end;
  825. end;
  826. function TLUdp.Send(const aData; const aSize: Integer; aSocket: TLSocket): Integer;
  827. begin
  828. Result := 0;
  829. if Assigned(FRootSock) then
  830. Result := FRootSock.Send(aData, aSize)
  831. end;
  832. function TLUdp.Send(const aData; const aSize: Integer; const Address: string
  833. ): Integer;
  834. begin
  835. Result := 0;
  836. if Assigned(FRootSock) then begin
  837. SetAddress(Address);
  838. Result := FRootSock.Send(aData, aSize);
  839. end;
  840. end;
  841. //******************************TLTcp**********************************
  842. constructor TLTcp.Create(aOwner: TComponent);
  843. begin
  844. inherited Create(aOwner);
  845. FIterator := nil;
  846. FCount := 0;
  847. FRootSock := nil;
  848. end;
  849. function TLTcp.Connect(const Address: string; const APort: Word): Boolean;
  850. begin
  851. Result := inherited Connect(Address, aPort);
  852. if Assigned(FRootSock) then
  853. Disconnect;
  854. FRootSock := InitSocket(FSocketClass.Create);
  855. Result := FRootSock.Connect(Address, aPort);
  856. if Result then begin
  857. Inc(FCount);
  858. FIterator := FRootSock;
  859. RegisterWithEventer;
  860. end else begin
  861. FreeAndNil(FRootSock);
  862. FIterator := nil;
  863. end;
  864. end;
  865. function TLTcp.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  866. begin
  867. Result := false;
  868. if Assigned(FRootSock) then
  869. Disconnect;
  870. FRootSock := InitSocket(FSocketClass.Create);
  871. FRootSock.FIgnoreShutdown := True;
  872. if FRootSock.Listen(APort, AIntf) then begin
  873. FRootSock.FConnected := True;
  874. FRootSock.FServerSocket := True;
  875. RegisterWithEventer;
  876. Result := true;
  877. end;
  878. end;
  879. function TLTcp.Bail(const msg: string; aSocket: TLSocket): Boolean;
  880. begin
  881. Result := False;
  882. ErrorEvent(msg, aSocket);
  883. if Assigned(aSocket) then
  884. aSocket.Disconnect
  885. else
  886. Disconnect;
  887. end;
  888. procedure TLTcp.SocketDisconnect(aSocket: TLSocket);
  889. begin
  890. if aSocket = FIterator then begin
  891. if Assigned(FIterator.NextSock) then
  892. FIterator := FIterator.NextSock
  893. else if Assigned(FIterator.PrevSock) then
  894. FIterator := FIterator.PrevSock
  895. else FIterator := nil; // NOT iterreset, not reorganized yet
  896. if Assigned(FIterator) and FIterator.FServerSocket then
  897. FIterator := nil;
  898. end;
  899. if aSocket = FRootSock then
  900. FRootSock := aSocket.NextSock;
  901. if Assigned(aSocket.PrevSock) then
  902. aSocket.PrevSock.NextSock := aSocket.NextSock;
  903. if Assigned(aSocket.NextSock) then
  904. aSocket.NextSock.PrevSock := aSocket.PrevSock;
  905. Dec(FCount);
  906. end;
  907. function TLTcp.InitSocket(aSocket: TLSocket): TLSocket;
  908. begin
  909. Result := inherited InitSocket(aSocket);
  910. aSocket.SocketType := SOCK_STREAM;
  911. aSocket.Protocol := LPROTO_TCP;
  912. aSocket.FOnFree := @SocketDisconnect;
  913. end;
  914. function TLTcp.IterNext: Boolean;
  915. begin
  916. Result := False;
  917. if Assigned(FIterator.NextSock) then begin
  918. FIterator := FIterator.NextSock;
  919. Result := True;
  920. end else IterReset;
  921. end;
  922. procedure TLTcp.IterReset;
  923. begin
  924. if Assigned(FRootSock) and FRootSock.FServerSocket then
  925. FIterator := FRootSock.NextSock
  926. else
  927. FIterator := FRootSock;
  928. end;
  929. procedure TLTcp.Disconnect;
  930. begin
  931. FreeSocks;
  932. FRootSock := nil;
  933. FCount := 0;
  934. FIterator := nil;
  935. end;
  936. procedure TLTcp.CallAction;
  937. begin
  938. if Assigned(FEventer) then
  939. FEventer.CallAction;
  940. end;
  941. procedure TLTcp.ConnectAction(aSocket: TLHandle);
  942. var
  943. a: TInetSockAddr;
  944. l: Longint;
  945. begin
  946. with TLSocket(aSocket) do begin
  947. l := SizeOf(a);
  948. if Sockets.GetPeerName(FHandle, a, l) <> 0 then
  949. Self.Bail('Error on connect: connection refused', TLSocket(aSocket))
  950. else begin
  951. FConnected := True;
  952. FConnecting := False;
  953. ConnectEvent(aSocket);
  954. end;
  955. end;
  956. end;
  957. procedure TLTcp.AcceptAction(aSocket: TLHandle);
  958. var
  959. Tmp: TLSocket;
  960. begin
  961. Tmp := InitSocket(FSocketClass.Create);
  962. if Tmp.Accept(FRootSock.FHandle) then begin
  963. if Assigned(FRootSock.FNextSock) then begin
  964. Tmp.FNextSock := FRootSock.FNextSock;
  965. FRootSock.FNextSock.FPrevSock := Tmp;
  966. end;
  967. FRootSock.FNextSock := Tmp;
  968. Tmp.FPrevSock := FRootSock;
  969. if not Assigned(FIterator) then
  970. FIterator := Tmp;
  971. Inc(FCount);
  972. FEventer.AddHandle(Tmp);
  973. AcceptEvent(Tmp);
  974. end else Tmp.Free;
  975. end;
  976. procedure TLTcp.ReceiveAction(aSocket: TLHandle);
  977. begin
  978. if (TLSocket(aSocket) = FRootSock) and TLSocket(aSocket).FServerSocket then
  979. AcceptAction(aSocket)
  980. else with TLSocket(aSocket) do begin
  981. if Connected then begin
  982. FCanReceive := True;
  983. ReceiveEvent(aSocket);
  984. if not Connected then begin
  985. DisconnectEvent(aSocket);
  986. aSocket.Free;
  987. end;
  988. end;
  989. end;
  990. end;
  991. procedure TLTcp.SendAction(aSocket: TLHandle);
  992. begin
  993. with TLSocket(aSocket) do begin
  994. if Connecting then
  995. ConnectAction(aSocket);
  996. FCanSend := True;
  997. IgnoreWrite := True;
  998. CanSendEvent(aSocket);
  999. end;
  1000. end;
  1001. procedure TLTcp.ErrorAction(aSocket: TLHandle; const msg: string);
  1002. begin
  1003. with TLSocket(aSocket) do begin
  1004. if Connecting then
  1005. Self.Bail('Error on connect: connection refused' , TLSocket(aSocket))
  1006. else
  1007. Self.Bail(msg, TLSocket(aSocket));
  1008. end;
  1009. end;
  1010. function TLTcp.GetConnected: Boolean;
  1011. var
  1012. Tmp: TLSocket;
  1013. begin
  1014. Result := False;
  1015. Tmp := FRootSock;
  1016. while Assigned(Tmp) do begin
  1017. if Tmp.Connected then begin
  1018. Result := True;
  1019. Exit;
  1020. end else Tmp := Tmp.NextSock;
  1021. end;
  1022. end;
  1023. function TLTcp.GetConnecting: Boolean;
  1024. begin
  1025. Result := False;
  1026. if Assigned(FRootSock) then
  1027. Result := FRootSock.Connecting;
  1028. end;
  1029. function TLTcp.Get(var aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1030. begin
  1031. Result := 0;
  1032. if not Assigned(aSocket) then
  1033. aSocket := FIterator;
  1034. if Assigned(aSocket) then
  1035. Result := aSocket.Get(aData, aSize);
  1036. end;
  1037. function TLTcp.GetMessage(out msg: string; aSocket: TLSocket): Integer;
  1038. begin
  1039. Result := 0;
  1040. if not Assigned(aSocket) then
  1041. aSocket := FIterator;
  1042. if Assigned(aSocket) then
  1043. Result := aSocket.GetMessage(msg);
  1044. end;
  1045. function TLTcp.Send(const aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1046. begin
  1047. Result := 0;
  1048. if not Assigned(aSocket) then
  1049. aSocket := FIterator;
  1050. if Assigned(aSocket) and (aSize > 0) then
  1051. Result := aSocket.Send(aData, aSize);
  1052. end;
  1053. function TLTcp.SendMessage(const msg: string; aSocket: TLSocket): Integer;
  1054. begin
  1055. Result := Send(PChar(msg)^, Length(msg), aSocket);
  1056. end;
  1057. { TLComponent }
  1058. constructor TLComponent.Create(aOwner: TComponent);
  1059. begin
  1060. inherited Create(aOwner);
  1061. FCreator := Self;
  1062. end;
  1063. end.