lnet.pp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271
  1. { lNet v0.5.1
  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. FNextSock: TLSocket;
  78. FPrevSock: TLSocket;
  79. FIgnoreShutdown: Boolean;
  80. FCanSend: Boolean;
  81. FCanReceive: Boolean;
  82. FServerSocket: Boolean;
  83. FOnFree: TLSocketEvent;
  84. FBlocking: Boolean;
  85. FListenBacklog: Integer;
  86. FProtocol: Integer;
  87. FSocketType: 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 Blocking: Boolean read FBlocking write SetBlocking;
  117. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  118. property Protocol: Integer read FProtocol write FProtocol;
  119. property SocketType: Integer read FSocketType write FSocketType;
  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. FCreator: TLComponent;
  161. public
  162. constructor Create(aOwner: TComponent); override;
  163. procedure Disconnect; virtual; abstract;
  164. procedure CallAction; virtual; abstract;
  165. public
  166. SocketClass: TLSocketClass;
  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 OnError: TLSocketErrorEvent read FOnError write FOnError;
  227. property OnReceive: TLSocketEvent read FOnReceive write FOnReceive;
  228. property OnDisconnect: TLSocketEvent read FOnDisconnect write FOnDisconnect;
  229. property OnCanSend: TLSocketEvent read FOnCanSend write FOnCanSend;
  230. property Socks[index: Integer]: TLSocket read GetItem; default;
  231. property Count: Integer read GetCount;
  232. property Connected: Boolean read GetConnected;
  233. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  234. property Iterator: TLSocket read FIterator;
  235. property Timeout: DWord read GetTimeout write SetTimeout;
  236. property Eventer: TLEventer read FEventer write SetEventer;
  237. property EventerClass: TLEventerClass read FEventerClass write FEventerClass;
  238. end;
  239. { UDP Client/Server class. Provided to enable usage of UDP sockets }
  240. { TLUdp }
  241. TLUdp = class(TLConnection)
  242. protected
  243. function InitSocket(aSocket: TLSocket): TLSocket; override;
  244. function GetConnected: Boolean; override;
  245. procedure ReceiveAction(aSocket: TLHandle); override;
  246. procedure SendAction(aSocket: TLHandle); override;
  247. procedure ErrorAction(aSocket: TLHandle; const msg: string); override;
  248. function Bail(const msg: string): Boolean;
  249. procedure SetAddress(const Address: string);
  250. public
  251. constructor Create(aOwner: TComponent); override;
  252. function Connect(const Address: string; const APort: Word): Boolean; override;
  253. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; override;
  254. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  255. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; override;
  256. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; override;
  257. function SendMessage(const msg: string; const Address: string): Integer; overload;
  258. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  259. function Send(const aData; const aSize: Integer; const Address: string): Integer; overload;
  260. function IterNext: Boolean; override;
  261. procedure IterReset; override;
  262. procedure Disconnect; override;
  263. procedure CallAction; override;
  264. end;
  265. { TCP Client/Server class. Provided to enable usage of TCP sockets }
  266. { TLTcp }
  267. TLTcp = class(TLConnection)
  268. protected
  269. FCount: Integer;
  270. function InitSocket(aSocket: TLSocket): TLSocket; override;
  271. function GetConnected: Boolean; override;
  272. function GetConnecting: Boolean;
  273. procedure ConnectAction(aSocket: TLHandle); override;
  274. procedure AcceptAction(aSocket: TLHandle); override;
  275. procedure ReceiveAction(aSocket: TLHandle); override;
  276. procedure SendAction(aSocket: TLHandle); override;
  277. procedure ErrorAction(aSocket: TLHandle; const msg: string); override;
  278. function Bail(const msg: string; aSocket: TLSocket): Boolean;
  279. procedure SocketDisconnect(aSocket: TLSocket);
  280. public
  281. constructor Create(aOwner: TComponent); override;
  282. function Connect(const Address: string; const APort: Word): Boolean; override;
  283. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; override;
  284. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  285. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; override;
  286. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  287. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; override;
  288. function IterNext: Boolean; override;
  289. procedure IterReset; override;
  290. procedure CallAction; override;
  291. procedure Disconnect; override;
  292. public
  293. property Connecting: Boolean read GetConnecting;
  294. property OnAccept: TLSocketEvent read FOnAccept write FOnAccept;
  295. property OnConnect: TLSocketEvent read FOnConnect write FOnConnect;
  296. end;
  297. implementation
  298. uses
  299. lCommon;
  300. //********************************TLSocket*************************************
  301. constructor TLSocket.Create;
  302. begin
  303. inherited Create;
  304. FHandle := INVALID_SOCKET;
  305. FBlocking := False;
  306. FListenBacklog := LDEFAULT_BACKLOG;
  307. FServerSocket := False;
  308. FPrevSock := nil;
  309. FNextSock := nil;
  310. FCanSend := True;
  311. FCanReceive := False;
  312. FConnected := False;
  313. FConnecting := False;
  314. FIgnoreShutdown := False;
  315. FSocketType := SOCK_STREAM;
  316. FProtocol := LPROTO_TCP;
  317. end;
  318. destructor TLSocket.Destroy;
  319. begin
  320. if Assigned(FOnFree) then
  321. FOnFree(Self);
  322. Disconnect;
  323. inherited Destroy;
  324. end;
  325. procedure TLSocket.Disconnect;
  326. var
  327. WasConnected: Boolean;
  328. begin
  329. WasConnected := FConnected;
  330. FDispose := True;
  331. FCanSend := True;
  332. FCanReceive := True;
  333. FIgnoreWrite := True;
  334. if FConnected or FConnecting then begin
  335. FConnected := False;
  336. FConnecting := False;
  337. if (FSocketType = SOCK_STREAM) and (not FIgnoreShutdown) and WasConnected then
  338. if fpShutDown(FHandle, 2) <> 0 then
  339. LogError('Shutdown error', LSocketError);
  340. if CloseSocket(FHandle) <> 0 then
  341. LogError('Closesocket error', LSocketError);
  342. FHandle := INVALID_SOCKET;
  343. end;
  344. end;
  345. procedure TLSocket.LogError(const msg: string; const ernum: Integer);
  346. begin
  347. if Assigned(FOnError) then
  348. if ernum > 0 then
  349. FOnError(Self, msg + '[' + IntToStr(ernum) + ']: ' + LStrError(ernum))
  350. else
  351. FOnError(Self, msg);
  352. end;
  353. function TLSocket.Bail(const msg: string; const ernum: Integer): Boolean;
  354. begin
  355. Result := False; // return the result for the caller
  356. Disconnect;
  357. LogError(msg, ernum);
  358. end;
  359. function TLSocket.GetPeerAddress: string;
  360. begin
  361. Result := '';
  362. if FSocketType = SOCK_STREAM then
  363. Result := NetAddrtoStr(FAddress.Addr)
  364. else
  365. Result := NetAddrtoStr(FPeerAddress.Addr);
  366. end;
  367. function TLSocket.GetLocalAddress: string;
  368. var
  369. a: TSockAddr;
  370. l: Integer;
  371. begin
  372. l := SizeOf(a);
  373. fpGetSockName(FHandle, @a, @l);
  374. Result := HostAddrToStr(LongWord(a.sin_addr));
  375. end;
  376. function TLSocket.CanSend: Boolean;
  377. begin
  378. Result := FCanSend and FConnected;
  379. end;
  380. function TLSocket.CanReceive: Boolean;
  381. begin
  382. Result := FCanReceive and FConnected;
  383. end;
  384. procedure TLSocket.SetBlocking(const aValue: Boolean);
  385. begin
  386. FBlocking := aValue;
  387. if FHandle >= 0 then // we already set our socket
  388. if not lCommon.SetBlocking(FHandle, aValue) then
  389. Bail('Error on SetBlocking', LSocketError);
  390. end;
  391. procedure TLSocket.SetOptions;
  392. begin
  393. SetBlocking(FBlocking);
  394. end;
  395. function TLSocket.GetMessage(out msg: string): Integer;
  396. begin
  397. Result := 0;
  398. SetLength(msg, BUFFER_SIZE);
  399. SetLength(msg, Get(PChar(msg)^, Length(msg)));
  400. Result := Length(msg);
  401. end;
  402. function TLSocket.Get(var aData; const aSize: Integer): Integer;
  403. var
  404. AddressLength: Integer = SizeOf(FAddress);
  405. begin
  406. Result := 0;
  407. if CanReceive then begin
  408. if FSocketType = SOCK_STREAM then
  409. Result := sockets.fpRecv(FHandle, @aData, aSize, LMSG)
  410. else
  411. Result := sockets.fpRecvfrom(FHandle, @aData, aSize, LMSG, @FPeerAddress, @AddressLength);
  412. if Result = 0 then
  413. Disconnect;
  414. if Result = SOCKET_ERROR then begin
  415. if IsBlockError(LSocketError) then begin
  416. FCanReceive := False;
  417. IgnoreRead := False;
  418. end else Bail('Receive Error', LSocketError);
  419. Result := 0;
  420. end;
  421. end;
  422. end;
  423. function TLSocket.DoSend(const TheData; const TheSize: Integer): Integer;
  424. var
  425. AddressLength: Integer;
  426. begin
  427. AddressLength := SizeOf(FPeerAddress);
  428. if FSocketType = SOCK_STREAM then
  429. Result := sockets.fpsend(FHandle, @TheData, TheSize, LMSG)
  430. else
  431. Result := sockets.fpsendto(FHandle, @TheData, TheSize, LMSG, @FPeerAddress, AddressLength);
  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, FSocketType, FProtocol);
  442. if FHandle = INVALID_SOCKET then
  443. Bail('Socket error', LSocketError);
  444. SetOptions;
  445. if FSocketType = SOCK_DGRAM then begin
  446. Arg := 1;
  447. if fpsetsockopt(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 (FSocketType = 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. SocketClass := 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(SocketClass.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(SocketClass.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(SocketClass.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(SocketClass.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.fpGetPeerName(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(SocketClass.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.