lnet.pp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694
  1. { lNet v0.6.2
  2. CopyRight (C) 2004-2008 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, lCommon,
  24. {$i sys/osunits.inc}
  25. const
  26. { API compatibility, these had to be moved to prevent circular unit usage and a
  27. fpc bug with inline }
  28. LADDR_ANY = lCommon.LADDR_ANY;
  29. LADDR_BR = lCommon.LADDR_BR;
  30. LADDR_LO = lCommon.LADDR_LO;
  31. LADDR6_ANY = lCommon.LADDR6_ANY;
  32. LADDR6_LO = lCommon.LADDR6_LO;
  33. type
  34. TLSocket = class;
  35. TLComponent = class;
  36. TLConnection = class;
  37. TLSession = class;
  38. { Callback Event procedure for errors }
  39. TLSocketErrorEvent = procedure(const msg: string; aSocket: TLSocket) of object;
  40. { Callback Event procedure for others }
  41. TLSocketEvent = procedure(aSocket: TLSocket) of object;
  42. { Callback Event procedure for progress reports}
  43. TLSocketProgressEvent = procedure (aSocket: TLSocket; const Bytes: Integer) of object;
  44. { TLSocketState }
  45. TLSocketState = (ssServerSocket, ssBlocking, ssReuseAddress, ssCanSend,
  46. ssCanReceive, ssSSLActive{, ssNoDelay});
  47. { TLSocketStates }
  48. TLSocketStates = set of TLSocketState;
  49. { TLSocketConnection }
  50. TLSocketConnectionStatus = (scNone, scConnecting, scConnected, scDisconnecting);
  51. { TLSocketOperation }
  52. TLSocketOperation = (soSend, soReceive);
  53. { TLSocket }
  54. TLSocket = class(TLHandle)
  55. protected
  56. FAddress: TLSocketAddress;
  57. FPeerAddress: TLSocketAddress;
  58. FReuseAddress: Boolean;
  59. FConnectionStatus: TLSocketConnectionStatus;
  60. FNextSock: TLSocket;
  61. FPrevSock: TLSocket;
  62. FSocketState: TLSocketStates;
  63. FOnFree: TLSocketEvent;
  64. FBlocking: Boolean;
  65. FListenBacklog: Integer;
  66. FProtocol: Integer;
  67. FSocketType: Integer;
  68. FSocketNet: Integer;
  69. FCreator: TLComponent;
  70. FSession: TLSession;
  71. FConnection: TLConnection;
  72. protected
  73. function GetConnected: Boolean; virtual; deprecated;
  74. function GetConnecting: Boolean; virtual; deprecated;
  75. function GetConnectionStatus: TLSocketConnectionStatus; virtual;
  76. function GetIPAddressPointer: psockaddr;
  77. function GetIPAddressLength: TSocklen;
  78. function SetupSocket(const APort: Word; const Address: string): Boolean; virtual;
  79. function DoSend(const aData; const aSize: Integer): Integer; virtual;
  80. function DoGet(out aData; const aSize: Integer): Integer; virtual;
  81. function HandleResult(const aResult: Integer; aOp: TLSocketOperation): Integer; virtual;
  82. function GetLocalPort: Word;
  83. function GetPeerPort: Word;
  84. function GetPeerAddress: string;
  85. function GetLocalAddress: string;
  86. function SendPossible: Boolean; inline;
  87. function ReceivePossible: Boolean; inline;
  88. procedure SetOptions; virtual;
  89. procedure SetBlocking(const aValue: Boolean);
  90. procedure SetReuseAddress(const aValue: Boolean);
  91. // procedure SetNoDelay(const aValue: Boolean);
  92. procedure HardDisconnect(const NoShutdown: Boolean = False);
  93. procedure SoftDisconnect;
  94. function Bail(const msg: string; const ernum: Integer): Boolean;
  95. function LogError(const msg: string; const ernum: Integer): Boolean; virtual;
  96. property SocketType: Integer read FSocketType write FSocketType; // inherit and publicize if you need to set this outside
  97. public
  98. constructor Create; override;
  99. destructor Destroy; override;
  100. function SetState(const aState: TLSocketState; const TurnOn: Boolean = True): Boolean; virtual;
  101. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  102. function Accept(const SerSock: TSocket): Boolean;
  103. function Connect(const Address: string; const APort: Word): Boolean;
  104. function Send(const aData; const aSize: Integer): Integer; virtual;
  105. function SendMessage(const msg: string): Integer;
  106. function Get(out aData; const aSize: Integer): Integer; virtual;
  107. function GetMessage(out msg: string): Integer;
  108. procedure Disconnect(const Forced: Boolean = True); virtual;
  109. public
  110. property Connected: Boolean read GetConnected; deprecated;
  111. property Connecting: Boolean read GetConnecting; deprecated;
  112. property ConnectionStatus: TLSocketConnectionStatus read GetConnectionStatus;
  113. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  114. property Protocol: Integer read FProtocol write FProtocol;
  115. property SocketNet: Integer read FSocketNet write FSocketNet;
  116. property PeerAddress: string read GetPeerAddress;
  117. property PeerPort: Word read GetPeerPort;
  118. property LocalAddress: string read GetLocalAddress;
  119. property LocalPort: Word read GetLocalPort;
  120. property NextSock: TLSocket read FNextSock write FNextSock;
  121. property PrevSock: TLSocket read FPrevSock write FPrevSock;
  122. property SocketState: TLSocketStates read FSocketState;
  123. property Creator: TLComponent read FCreator;
  124. property Session: TLSession read FSession;
  125. end;
  126. TLSocketClass = class of TLSocket;
  127. { this is the socket used by TLConnection }
  128. TLActionEnum = (acConnect, acAccept, acSend, acReceive, acError);
  129. { Base interface common to ALL connections }
  130. ILComponent = interface
  131. procedure Disconnect(const Forced: Boolean = True);
  132. procedure CallAction;
  133. property SocketClass: TLSocketClass;
  134. property Host: string;
  135. property Port: Word;
  136. end;
  137. { Interface for protools with direct send/get capabilities }
  138. ILDirect = interface
  139. function Get(out aData; const aSize: Integer; aSocket: TLSocket = nil): Integer;
  140. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer;
  141. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer;
  142. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer;
  143. end;
  144. { Interface for all servers }
  145. ILServer = interface
  146. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  147. end;
  148. { Interface for all clients }
  149. ILClient = interface
  150. function Connect(const Address: string; const APort: Word): Boolean; overload;
  151. function Connect: Boolean; overload;
  152. end;
  153. { TLComponent }
  154. TLComponent = class(TComponent, ILComponent)
  155. protected
  156. FHost: string;
  157. FPort: Word;
  158. FCreator: TLComponent;
  159. FActive: Boolean;
  160. procedure SetCreator(AValue: TLComponent); virtual;
  161. public
  162. constructor Create(aOwner: TComponent); override;
  163. procedure Disconnect(const Forced: Boolean = True); 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 SetCreator;
  170. property Active: Boolean read FActive;
  171. end;
  172. { TLConnection
  173. Common ancestor for TLTcp and TLUdp classes. Holds Event properties
  174. and common variables. }
  175. TLConnection = class(TLComponent, ILDirect, ILServer, ILClient)
  176. protected
  177. FTimeVal: TTimeVal;
  178. FOnReceive: TLSocketEvent;
  179. FOnAccept: TLSocketEvent;
  180. FOnConnect: TLSocketEvent;
  181. FOnDisconnect: TLSocketEvent;
  182. FOnCanSend: TLSocketEvent;
  183. FOnError: TLSocketErrorEvent;
  184. FRootSock: TLSocket;
  185. FIterator: TLSocket;
  186. FID: Integer; // internal number for server
  187. FEventer: TLEventer;
  188. FEventerClass: TLEventerClass;
  189. FTimeout: Integer;
  190. FListenBacklog: Integer;
  191. FSession: TLSession;
  192. protected
  193. function InitSocket(aSocket: TLSocket): TLSocket; virtual;
  194. function GetConnected: Boolean; virtual; abstract;
  195. function GetCount: Integer; virtual;
  196. function GetItem(const i: Integer): TLSocket;
  197. function GetTimeout: Integer;
  198. procedure SetTimeout(const AValue: Integer);
  199. procedure SetEventer(Value: TLEventer);
  200. procedure SetSession(aSession: TLSession);
  201. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  202. procedure ConnectAction(aSocket: TLHandle); virtual;
  203. procedure AcceptAction(aSocket: TLHandle); virtual;
  204. procedure ReceiveAction(aSocket: TLHandle); virtual;
  205. procedure SendAction(aSocket: TLHandle); virtual;
  206. procedure ErrorAction(aSocket: TLHandle; const msg: string); virtual;
  207. procedure ConnectEvent(aSocket: TLHandle); virtual;
  208. procedure DisconnectEvent(aSocket: TLHandle); virtual;
  209. procedure AcceptEvent(aSocket: TLHandle); virtual;
  210. procedure ReceiveEvent(aSocket: TLHandle); virtual;
  211. procedure CanSendEvent(aSocket: TLHandle); virtual;
  212. procedure ErrorEvent(aSocket: TLHandle; const msg: string); virtual;
  213. procedure EventerError(const msg: string; Sender: TLEventer);
  214. procedure RegisterWithEventer; virtual;
  215. procedure FreeSocks(const Forced: Boolean); virtual;
  216. public
  217. constructor Create(aOwner: TComponent); override;
  218. destructor Destroy; override;
  219. function Connect(const Address: string; const APort: Word): Boolean; virtual; overload;
  220. function Connect: Boolean; virtual; overload;
  221. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; virtual; abstract; overload;
  222. function Listen: Boolean; virtual; overload;
  223. function Get(out aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; virtual; abstract;
  224. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; virtual; abstract;
  225. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; virtual; abstract;
  226. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; virtual; abstract;
  227. function IterNext: Boolean; virtual; abstract;
  228. procedure IterReset; virtual; abstract;
  229. public
  230. property OnError: TLSocketErrorEvent read FOnError write FOnError;
  231. property OnReceive: TLSocketEvent read FOnReceive write FOnReceive;
  232. property OnDisconnect: TLSocketEvent read FOnDisconnect write FOnDisconnect;
  233. property OnCanSend: TLSocketEvent read FOnCanSend write FOnCanSend;
  234. property Socks[index: Integer]: TLSocket read GetItem; default;
  235. property Count: Integer read GetCount;
  236. property Connected: Boolean read GetConnected;
  237. property ListenBacklog: Integer read FListenBacklog write FListenBacklog;
  238. property Iterator: TLSocket read FIterator;
  239. property Timeout: Integer read GetTimeout write SetTimeout;
  240. property Eventer: TLEventer read FEventer write SetEventer;
  241. property EventerClass: TLEventerClass read FEventerClass write FEventerClass;
  242. property Session: TLSession read FSession write SetSession;
  243. end;
  244. { TLUdp }
  245. TLUdp = class(TLConnection)
  246. protected
  247. function InitSocket(aSocket: TLSocket): TLSocket; override;
  248. function GetConnected: Boolean; override;
  249. procedure ReceiveAction(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(out 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(const Forced: Boolean = True); override;
  266. procedure CallAction; override;
  267. end;
  268. { TLTcp }
  269. TLTcp = class(TLConnection)
  270. protected
  271. FSocketNet: Integer;
  272. FCount: Integer;
  273. FReuseAddress: Boolean;
  274. function InitSocket(aSocket: TLSocket): TLSocket; override;
  275. function GetConnected: Boolean; override;
  276. function GetConnecting: Boolean;
  277. function GetCount: Integer; override;
  278. function GetValidSocket: TLSocket;
  279. procedure SetReuseAddress(const aValue: Boolean);
  280. procedure SetSocketNet(const aValue: Integer);
  281. procedure ConnectAction(aSocket: TLHandle); override;
  282. procedure AcceptAction(aSocket: TLHandle); override;
  283. procedure ReceiveAction(aSocket: TLHandle); override;
  284. procedure SendAction(aSocket: TLHandle); override;
  285. procedure ErrorAction(aSocket: TLHandle; const msg: string); override;
  286. function Bail(const msg: string; aSocket: TLSocket): Boolean;
  287. procedure SocketDisconnect(aSocket: TLSocket);
  288. public
  289. constructor Create(aOwner: TComponent); override;
  290. function Connect(const Address: string; const APort: Word): Boolean; override;
  291. function Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean; override;
  292. function Get(out aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  293. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; override;
  294. function Send(const aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; override;
  295. function SendMessage(const msg: string; aSocket: TLSocket = nil): Integer; override;
  296. function IterNext: Boolean; override;
  297. procedure IterReset; override;
  298. procedure CallAction; override;
  299. procedure Disconnect(const Forced: Boolean = True); override;
  300. public
  301. property Connecting: Boolean read GetConnecting;
  302. property OnAccept: TLSocketEvent read FOnAccept write FOnAccept;
  303. property OnConnect: TLSocketEvent read FOnConnect write FOnConnect;
  304. property ReuseAddress: Boolean read FReuseAddress write SetReuseAddress;
  305. property SocketNet: Integer read FSocketNet write SetSocketNet;
  306. end;
  307. { TLSession }
  308. TLSession = class(TComponent)
  309. protected
  310. FActive: Boolean;
  311. public
  312. procedure RegisterWithComponent(aConnection: TLConnection); virtual;
  313. procedure InitHandle(aHandle: TLHandle); virtual;
  314. procedure ReceiveEvent(aHandle: TLHandle); virtual;
  315. procedure SendEvent(aHandle: TLHandle); virtual;
  316. procedure ErrorEvent(aHandle: TLHandle; const msg: string); virtual;
  317. procedure ConnectEvent(aHandle: TLHandle); virtual;
  318. procedure AcceptEvent(aHandle: TLHandle); virtual;
  319. procedure DisconnectEvent(aHandle: TLHandle); virtual;
  320. procedure CallReceiveEvent(aHandle: TLHandle); inline;
  321. procedure CallSendEvent(aHandle: TLHandle); inline;
  322. procedure CallErrorEvent(aHandle: TLHandle; const msg: string); inline;
  323. procedure CallConnectEvent(aHandle: TLHandle); inline;
  324. procedure CallAcceptEvent(aHandle: TLHandle); inline;
  325. procedure CallDisconnectEvent(aHandle: TLHandle); inline;
  326. public
  327. property Active: Boolean read FActive;
  328. end;
  329. implementation
  330. //********************************TLSocket*************************************
  331. constructor TLSocket.Create;
  332. begin
  333. inherited Create;
  334. FHandle := INVALID_SOCKET;
  335. FListenBacklog := LDEFAULT_BACKLOG;
  336. FPrevSock := nil;
  337. FNextSock := nil;
  338. FSocketState := [ssCanSend];
  339. FConnectionStatus := scNone;
  340. FSocketType := SOCK_STREAM;
  341. FSocketNet := LAF_INET;
  342. FProtocol := LPROTO_TCP;
  343. end;
  344. destructor TLSocket.Destroy;
  345. begin
  346. if Assigned(FOnFree) then
  347. FOnFree(Self);
  348. inherited Destroy; // important! must be called before disconnect
  349. Disconnect(True);
  350. end;
  351. function TLSocket.SetState(const aState: TLSocketState; const TurnOn: Boolean = True): Boolean;
  352. begin
  353. Result := False;
  354. case aState of
  355. ssServerSocket : if TurnOn then
  356. FSocketState := FSocketState + [aState]
  357. else
  358. raise Exception.Create('Can not turn off server socket feature');
  359. ssBlocking : SetBlocking(TurnOn);
  360. ssReuseAddress : SetReuseAddress(TurnOn);
  361. ssCanSend,
  362. ssCanReceive : if TurnOn then
  363. FSocketState := FSocketState + [aState]
  364. else
  365. FSocketState := FSocketState - [aState];
  366. ssSSLActive : raise Exception.Create('Can not turn SSL/TLS on in TLSocket instance');
  367. { ssNoDelay : SetNoDelay(TurnOn);}
  368. end;
  369. Result := True;
  370. end;
  371. procedure TLSocket.Disconnect(const Forced: Boolean = True);
  372. begin
  373. if Forced then
  374. HardDisconnect
  375. else
  376. SoftDisconnect;
  377. end;
  378. function TLSocket.LogError(const msg: string; const ernum: Integer): Boolean;
  379. begin
  380. Result := False;
  381. if Assigned(FOnError) then
  382. if ernum > 0 then
  383. FOnError(Self, msg + LStrError(ernum))
  384. else
  385. FOnError(Self, msg);
  386. end;
  387. function TLSocket.Bail(const msg: string; const ernum: Integer): Boolean;
  388. begin
  389. Result := False; // return the result for the caller
  390. if FDispose then // why?
  391. Exit;
  392. Disconnect(True);
  393. LogError(msg, ernum);
  394. end;
  395. function TLSocket.GetPeerAddress: string;
  396. begin
  397. Result := '';
  398. if FSocketType = SOCK_STREAM then
  399. Result := NetAddrtoStr(FAddress.IPv4.sin_addr)
  400. else
  401. Result := NetAddrtoStr(FPeerAddress.IPv4.sin_addr);
  402. end;
  403. function TLSocket.GetLocalAddress: string;
  404. var
  405. a: TSockAddr;
  406. l: Integer;
  407. begin
  408. Result := '';
  409. l := SizeOf(a);
  410. if fpGetSockName(FHandle, @a, @l) = 0 then
  411. Result := NetAddrToStr(a.sin_addr);
  412. end;
  413. function TLSocket.SendPossible: Boolean; inline;
  414. begin
  415. Result := True;
  416. if FConnectionStatus <> scConnected then
  417. Exit(LogError('Can''t send when not connected', -1));
  418. if not (ssCanSend in FSocketState) then begin
  419. if not Assigned(FConnection)
  420. or not Assigned(FConnection.FOnCanSend) then
  421. LogError('Send buffer full, try again later', -1);
  422. Exit(False);
  423. end;
  424. if ssServerSocket in FSocketState then
  425. Exit(LogError('Can''t send on server socket', -1));
  426. end;
  427. function TLSocket.ReceivePossible: Boolean; inline;
  428. begin
  429. Result := (FConnectionStatus in [scConnected, scDisconnecting])
  430. and (ssCanReceive in FSocketState) and not (ssServerSocket in FSocketState);
  431. end;
  432. procedure TLSocket.SetOptions;
  433. begin
  434. SetBlocking(FBlocking);
  435. end;
  436. procedure TLSocket.SetBlocking(const aValue: Boolean);
  437. begin
  438. if FHandle >= 0 then // we already set our socket
  439. if not lCommon.SetBlocking(FHandle, aValue) then
  440. Bail('Error on SetBlocking', LSocketError)
  441. else begin
  442. FBlocking := aValue;
  443. if aValue then
  444. FSocketState := FSocketState + [ssBlocking]
  445. else
  446. FSocketState := FSocketState - [ssBlocking];
  447. end;
  448. end;
  449. procedure TLSocket.SetReuseAddress(const aValue: Boolean);
  450. begin
  451. if FConnectionStatus = scNone then begin
  452. FReuseAddress := aValue;
  453. if aValue then
  454. FSocketState := FSocketState + [ssReuseAddress]
  455. else
  456. FSocketState := FSocketState - [ssReuseAddress];
  457. end;
  458. end;
  459. procedure TLSocket.HardDisconnect(const NoShutdown: Boolean = False);
  460. var
  461. NeedsShutdown: Boolean;
  462. begin
  463. NeedsShutdown := (FConnectionStatus = scConnected) and (FSocketType = SOCK_STREAM)
  464. and (not (ssServerSocket in FSocketState));
  465. if NoShutdown then
  466. NeedsShutdown := False;
  467. FDispose := True;
  468. FSocketState := FSocketState + [ssCanSend, ssCanReceive];
  469. FIgnoreWrite := True;
  470. if FConnectionStatus in [scConnected, scConnecting] then begin
  471. FConnectionStatus := scNone;
  472. if NeedsShutdown then
  473. if fpShutDown(FHandle, SHUT_RDWR) <> 0 then
  474. LogError('Shutdown error', LSocketError);
  475. if Assigned(FEventer) then
  476. FEventer.UnregisterHandle(Self);
  477. if CloseSocket(FHandle) <> 0 then
  478. LogError('Closesocket error', LSocketError);
  479. FHandle := INVALID_SOCKET;
  480. end;
  481. end;
  482. procedure TLSocket.SoftDisconnect;
  483. begin
  484. if FConnectionStatus in [scConnected, scConnecting] then begin
  485. if (FConnectionStatus = scConnected) and (not (ssServerSocket in FSocketState))
  486. and (FSocketType = SOCK_STREAM) then begin
  487. FConnectionStatus := scDisconnecting;
  488. if fpShutDown(FHandle, SHUT_WR) <> 0 then
  489. LogError('Shutdown error', LSocketError);
  490. end else
  491. HardDisconnect; // UDP or ServerSocket
  492. end;
  493. end;
  494. {procedure TLSocket.SetNoDelay(const aValue: Boolean);
  495. begin
  496. if FHandle >= 0 then // we already set our socket
  497. if not lCommon.SetNoDelay(FHandle, aValue) then
  498. Bail('Error on SetNoDelay', LSocketError)
  499. else begin
  500. if aValue then
  501. FSocketState := FSocketState + [ssNoDelay]
  502. else
  503. FSocketState := FSocketState - [ssNoDelay];
  504. end;
  505. end;}
  506. function TLSocket.GetMessage(out msg: string): Integer;
  507. begin
  508. Result := 0;
  509. SetLength(msg, BUFFER_SIZE);
  510. SetLength(msg, Get(PChar(msg)^, Length(msg)));
  511. Result := Length(msg);
  512. end;
  513. function TLSocket.Get(out aData; const aSize: Integer): Integer;
  514. begin
  515. Result := 0;
  516. if aSize = 0 then
  517. raise Exception.Create('Invalid buffer size 0 in Get');
  518. if ReceivePossible then begin
  519. Result := DoGet(aData, aSize);
  520. if Result = 0 then
  521. if FSocketType = SOCK_STREAM then
  522. Disconnect(True)
  523. else begin
  524. Bail('Receive Error [0 on recvfrom with UDP]', 0);
  525. Exit(0);
  526. end;
  527. Result := HandleResult(Result, soReceive);
  528. end;
  529. end;
  530. function TLSocket.GetConnected: Boolean;
  531. begin
  532. Result := (FConnectionStatus = scConnected);
  533. end;
  534. function TLSocket.GetConnecting: Boolean;
  535. begin
  536. Result := FConnectionStatus = scConnecting;
  537. end;
  538. function TLSocket.GetConnectionStatus: TLSocketConnectionStatus;
  539. begin
  540. Result := FConnectionStatus;
  541. end;
  542. function TLSocket.GetIPAddressPointer: psockaddr;
  543. begin
  544. case FSocketNet of
  545. LAF_INET : Result := psockaddr(@FAddress.IPv4);
  546. LAF_INET6 : Result := psockaddr(@FAddress.IPv6);
  547. else
  548. raise Exception.Create('Unknown socket network type (not IPv4 or IPv6)');
  549. end;
  550. end;
  551. function TLSocket.GetIPAddressLength: TSocklen;
  552. begin
  553. case FSocketNet of
  554. LAF_INET : Result := SizeOf(FAddress.IPv4);
  555. LAF_INET6 : Result := SizeOf(FAddress.IPv6);
  556. else
  557. raise Exception.Create('Unknown socket network type (not IPv4 or IPv6)');
  558. end;
  559. end;
  560. function TLSocket.SetupSocket(const APort: Word; const Address: string): Boolean;
  561. var
  562. Done: Boolean;
  563. Arg, Opt: Integer;
  564. begin
  565. Result := false;
  566. if FConnectionStatus = scNone then begin
  567. Done := true;
  568. FHandle := fpSocket(FSocketNet, FSocketType, FProtocol);
  569. if FHandle = INVALID_SOCKET then
  570. Exit(Bail('Socket error', LSocketError));
  571. SetOptions;
  572. Arg := 1;
  573. if FSocketType = SOCK_DGRAM then begin
  574. if fpsetsockopt(FHandle, SOL_SOCKET, SO_BROADCAST, @Arg, Sizeof(Arg)) = SOCKET_ERROR then
  575. Exit(Bail('SetSockOpt error', LSocketError));
  576. end else if FReuseAddress then begin
  577. Opt := SO_REUSEADDR;
  578. {$ifdef WIN32} // I expect 64 has it oddly, so screw them for now
  579. if (Win32Platform = 2) and (Win32MajorVersion >= 5) then
  580. Opt := Integer(not Opt);
  581. {$endif}
  582. if fpsetsockopt(FHandle, SOL_SOCKET, Opt, @Arg, Sizeof(Arg)) = SOCKET_ERROR then
  583. Exit(Bail('SetSockOpt error', LSocketError));
  584. end;
  585. {$ifdef darwin}
  586. Arg := 1;
  587. if fpsetsockopt(FHandle, SOL_SOCKET, SO_NOSIGPIPE, @Arg, Sizeof(Arg)) = SOCKET_ERROR then
  588. Exit(Bail('SetSockOpt error', LSocketError));
  589. {$endif}
  590. FillAddressInfo(FAddress, FSocketNet, Address, aPort);
  591. FillAddressInfo(FPeerAddress, FSocketNet, LADDR_BR, aPort);
  592. Result := Done;
  593. end;
  594. end;
  595. function TLSocket.DoSend(const aData; const aSize: Integer): Integer;
  596. var
  597. AddressLength: Longint = SizeOf(FPeerAddress);
  598. begin
  599. if FSocketType = SOCK_STREAM then
  600. Result := Sockets.fpSend(FHandle, @aData, aSize, LMSG)
  601. else
  602. Result := sockets.fpsendto(FHandle, @aData, aSize, LMSG, @FPeerAddress, AddressLength);
  603. end;
  604. function TLSocket.DoGet(out aData; const aSize: Integer): Integer;
  605. var
  606. AddressLength: Longint = SizeOf(FPeerAddress);
  607. begin
  608. if FSocketType = SOCK_STREAM then
  609. Result := sockets.fpRecv(FHandle, @aData, aSize, LMSG)
  610. else
  611. Result := sockets.fpRecvfrom(FHandle, @aData, aSize, LMSG, @FPeerAddress, @AddressLength);
  612. end;
  613. function TLSocket.HandleResult(const aResult: Integer; aOp: TLSocketOperation): Integer;
  614. const
  615. GSStr: array[TLSocketOperation] of string = ('Send', 'Get');
  616. var
  617. LastError: Longint;
  618. begin
  619. Result := aResult;
  620. if Result = SOCKET_ERROR then begin
  621. LastError := LSocketError;
  622. if IsBlockError(LastError) then case aOp of
  623. soSend:
  624. begin
  625. FSocketState := FSocketState - [ssCanSend];
  626. IgnoreWrite := False;
  627. end;
  628. soReceive:
  629. begin
  630. FSocketState := FSocketState - [ssCanReceive];
  631. IgnoreRead := False;
  632. end;
  633. end else if IsNonFatalError(LastError) then
  634. LogError(GSStr[aOp] + ' error', LastError) // non fatals don't cause disconnect
  635. else if (aOp = soSend) and IsPipeError(LastError) then begin
  636. LogError(GSStr[aOp] + ' error', LastError);
  637. HardDisconnect(True); {$warning check if we need aOp = soSend in the IF, perhaps bad recv is possible?}
  638. end else
  639. Bail(GSStr[aOp] + ' error', LastError);
  640. Result := 0;
  641. end;
  642. end;
  643. function TLSocket.GetLocalPort: Word;
  644. begin
  645. Result := ntohs(FAddress.IPv4.sin_port);
  646. end;
  647. function TLSocket.GetPeerPort: Word;
  648. begin
  649. Result := ntohs(FPeerAddress.IPv4.sin_port);
  650. end;
  651. function TLSocket.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  652. begin
  653. Result := False;
  654. if FConnectionStatus <> scNone then
  655. Disconnect(True);
  656. SetupSocket(APort, AIntf);
  657. if fpBind(FHandle, GetIPAddressPointer, GetIPAddressLength) = SOCKET_ERROR then
  658. Bail('Error on bind', LSocketError)
  659. else
  660. Result := true;
  661. if (FSocketType = SOCK_STREAM) and Result then
  662. if fpListen(FHandle, FListenBacklog) = SOCKET_ERROR then
  663. Result := Bail('Error on Listen', LSocketError)
  664. else
  665. Result := true;
  666. end;
  667. function TLSocket.Accept(const sersock: TSocket): Boolean;
  668. var
  669. AddressLength: tsocklen;
  670. begin
  671. Result := false;
  672. AddressLength := GetIPAddressLength;
  673. if FConnectionStatus <> scNone then
  674. Disconnect(True);
  675. FHandle := fpAccept(sersock, GetIPAddressPointer, @AddressLength);
  676. if FHandle <> INVALID_SOCKET then begin
  677. SetOptions;
  678. Result := true;
  679. end else
  680. Bail('Error on accept', LSocketError);
  681. end;
  682. function TLSocket.Connect(const Address: string; const aPort: Word): Boolean;
  683. begin
  684. Result := False;
  685. if FConnectionStatus <> scNone then
  686. Disconnect(True);
  687. if SetupSocket(APort, Address) then begin
  688. fpConnect(FHandle, GetIPAddressPointer, GetIPAddressLength);
  689. FConnectionStatus := scConnecting;
  690. Result := True;
  691. end;
  692. end;
  693. function TLSocket.SendMessage(const msg: string): Integer;
  694. begin
  695. Result := Send(PChar(msg)^, Length(msg));
  696. end;
  697. function TLSocket.Send(const aData; const aSize: Integer): Integer;
  698. begin
  699. Result := 0;
  700. if aSize = 0 then
  701. raise Exception.Create('Invalid buffersize 0 in Send');
  702. if SendPossible then begin
  703. if aSize <= 0 then begin
  704. LogError('Send error: Size <= 0', -1);
  705. Exit(0);
  706. end;
  707. Result := HandleResult(DoSend(aData, aSize), soSend);
  708. end;
  709. end;
  710. //*******************************TLComponent*********************************
  711. procedure TLComponent.SetCreator(AValue: TLComponent);
  712. begin
  713. FCreator := aValue;
  714. end;
  715. constructor TLComponent.Create(aOwner: TComponent);
  716. begin
  717. inherited Create(aOwner);
  718. FCreator := Self;
  719. end;
  720. //*******************************TLConnection*********************************
  721. constructor TLConnection.Create(aOwner: TComponent);
  722. begin
  723. inherited Create(aOwner);
  724. FHost := '';
  725. FPort := 0;
  726. FListenBacklog := LDEFAULT_BACKLOG;
  727. FTimeout := 0;
  728. SocketClass := TLSocket;
  729. FOnReceive := nil;
  730. FOnError := nil;
  731. FOnDisconnect := nil;
  732. FOnCanSend := nil;
  733. FOnConnect := nil;
  734. FOnAccept := nil;
  735. FTimeVal.tv_sec := 0;
  736. FTimeVal.tv_usec := 0;
  737. FIterator := nil;
  738. FEventer := nil;
  739. FEventerClass := BestEventerClass;
  740. end;
  741. destructor TLConnection.Destroy;
  742. begin
  743. FreeSocks(True);
  744. if Assigned(FEventer) then
  745. FEventer.DeleteRef;
  746. inherited Destroy;
  747. end;
  748. function TLConnection.Connect(const Address: string; const APort: Word
  749. ): Boolean;
  750. begin
  751. FHost := Address;
  752. FPort := aPort;
  753. Result := False;
  754. end;
  755. function TLConnection.Connect: Boolean;
  756. begin
  757. Result := Connect(FHost, FPort);
  758. end;
  759. function TLConnection.Listen: Boolean;
  760. begin
  761. Result := Listen(FPort, FHost);
  762. end;
  763. procedure TLConnection.SetSession(aSession: TLSession);
  764. begin
  765. if FSession = aSession then Exit;
  766. if FActive then
  767. raise Exception.Create('Cannot change session on active component');
  768. FSession := aSession;
  769. if Assigned(FSession) then begin
  770. FSession.FreeNotification(Self);
  771. FSession.RegisterWithComponent(Self);
  772. end;
  773. end;
  774. procedure TLConnection.Notification(AComponent: TComponent;
  775. Operation: TOperation);
  776. begin
  777. inherited Notification(AComponent, Operation);
  778. if (Operation = opRemove) and (AComponent = FSession) then
  779. FSession := nil;
  780. end;
  781. function TLConnection.InitSocket(aSocket: TLSocket): TLSocket;
  782. begin
  783. FActive := True; // once we got a socket, we're considered active
  784. aSocket.OnRead := @ReceiveAction;
  785. aSocket.OnWrite := @SendAction;
  786. aSocket.OnError := @ErrorAction;
  787. aSocket.ListenBacklog := FListenBacklog;
  788. aSocket.FCreator := FCreator;
  789. aSocket.FConnection := Self;
  790. aSocket.FSession := FSession;
  791. if Assigned(FSession) then
  792. FSession.InitHandle(aSocket);
  793. Result := aSocket;
  794. end;
  795. function TLConnection.GetCount: Integer;
  796. begin
  797. Result := 1;
  798. end;
  799. function TLConnection.GetItem(const i: Integer): TLSocket;
  800. var
  801. Tmp: TLSocket;
  802. Jumps: Integer;
  803. begin
  804. Result := nil;
  805. Tmp := FRootSock;
  806. Jumps := 0;
  807. while Assigned(Tmp.NextSock) and (Jumps < i) do begin
  808. Tmp := Tmp.NextSock;
  809. Inc(Jumps);
  810. end;
  811. if Jumps = i then
  812. Result := Tmp;
  813. end;
  814. function TLConnection.GetTimeout: Integer;
  815. begin
  816. if Assigned(FEventer) then
  817. Result := FEventer.Timeout
  818. else
  819. Result := FTimeout;
  820. end;
  821. procedure TLConnection.ConnectAction(aSocket: TLHandle);
  822. begin
  823. end;
  824. procedure TLConnection.AcceptAction(aSocket: TLHandle);
  825. begin
  826. end;
  827. procedure TLConnection.ReceiveAction(aSocket: TLHandle);
  828. begin
  829. end;
  830. procedure TLConnection.SendAction(aSocket: TLHandle);
  831. begin
  832. with TLSocket(aSocket) do begin
  833. SetState(ssCanSend);
  834. IgnoreWrite := True;
  835. if Assigned(FSession) then
  836. FSession.SendEvent(aSocket)
  837. else
  838. CanSendEvent(aSocket);
  839. end;
  840. end;
  841. procedure TLConnection.ErrorAction(aSocket: TLHandle; const msg: string);
  842. begin
  843. end;
  844. procedure TLConnection.ConnectEvent(aSocket: TLHandle);
  845. begin
  846. if Assigned(FOnConnect) then
  847. FOnConnect(TLSocket(aSocket));
  848. end;
  849. procedure TLConnection.DisconnectEvent(aSocket: TLHandle);
  850. begin
  851. if Assigned(FOnDisconnect) then
  852. FOnDisconnect(TLSocket(aSocket));
  853. end;
  854. procedure TLConnection.AcceptEvent(aSocket: TLHandle);
  855. begin
  856. if Assigned(FOnAccept) then
  857. FOnAccept(TLSocket(aSocket));
  858. end;
  859. procedure TLConnection.ReceiveEvent(aSocket: TLHandle);
  860. begin
  861. if Assigned(FOnReceive) then
  862. FOnReceive(TLSocket(aSocket));
  863. end;
  864. procedure TLConnection.CanSendEvent(aSocket: TLHandle);
  865. begin
  866. if Assigned(FOnCanSend) then
  867. FOnCanSend(TLSocket(aSocket));
  868. end;
  869. procedure TLConnection.ErrorEvent(aSocket: TLHandle; const msg: string);
  870. begin
  871. if Assigned(FOnError) then
  872. FOnError(msg, TLSocket(aSocket));
  873. end;
  874. procedure TLConnection.SetTimeout(const AValue: Integer);
  875. begin
  876. if Assigned(FEventer) then
  877. FEventer.Timeout := aValue;
  878. FTimeout := aValue;
  879. end;
  880. procedure TLConnection.SetEventer(Value: TLEventer);
  881. begin
  882. if Assigned(FEventer) then
  883. FEventer.DeleteRef;
  884. FEventer := Value;
  885. FEventer.AddRef;
  886. end;
  887. procedure TLConnection.EventerError(const msg: string; Sender: TLEventer);
  888. begin
  889. ErrorEvent(nil, msg);
  890. end;
  891. procedure TLConnection.RegisterWithEventer;
  892. begin
  893. if not Assigned(FEventer) then begin
  894. FEventer := FEventerClass.Create;
  895. FEventer.OnError := @EventerError;
  896. end;
  897. if Assigned(FRootSock) then
  898. FEventer.AddHandle(FRootSock);
  899. if (FEventer.Timeout = 0) and (FTimeout <> 0) then
  900. FEventer.Timeout := FTimeout
  901. else
  902. FTimeout := FEventer.Timeout;
  903. end;
  904. procedure TLConnection.FreeSocks(const Forced: Boolean);
  905. var
  906. Tmp, Tmp2: TLSocket;
  907. begin
  908. Tmp := FRootSock;
  909. while Assigned(Tmp) do begin
  910. Tmp2 := Tmp;
  911. Tmp := Tmp.NextSock;
  912. Tmp2.Disconnect(Forced);
  913. if Forced then
  914. Tmp2.Free;
  915. end;
  916. end;
  917. //*******************************TLUdp*********************************
  918. constructor TLUdp.Create(aOwner: TComponent);
  919. begin
  920. inherited Create(aOwner);
  921. FTimeVal.tv_usec := 0;
  922. FTimeVal.tv_sec := 0;
  923. end;
  924. procedure TLUdp.Disconnect(const Forced: Boolean = True);
  925. begin
  926. if Assigned(FRootSock) then begin
  927. FRootSock.Disconnect(True);
  928. FRootSock := nil; // even if the old one exists, eventer takes care of it
  929. end;
  930. end;
  931. function TLUdp.Connect(const Address: string; const APort: Word): Boolean;
  932. begin
  933. Result := inherited Connect(Address, aPort);
  934. if Assigned(FRootSock) and (FRootSock.FConnectionStatus <> scNone) then
  935. Disconnect(True);
  936. FRootSock := InitSocket(SocketClass.Create);
  937. FIterator := FRootSock;
  938. Result := FRootSock.SetupSocket(APort, LADDR_ANY);
  939. if Result then begin
  940. FillAddressInfo(FRootSock.FPeerAddress, FRootSock.FSocketNet, Address, aPort);
  941. FRootSock.FConnectionStatus := scConnected;
  942. RegisterWithEventer;
  943. end;
  944. end;
  945. function TLUdp.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  946. begin
  947. Result := False;
  948. if Assigned(FRootSock) and (FRootSock.FConnectionStatus <> scNone) then
  949. Disconnect(True);
  950. FRootSock := InitSocket(SocketClass.Create);
  951. FIterator := FRootSock;
  952. if FRootSock.Listen(APort, AIntf) then begin
  953. FillAddressInfo(FRootSock.FPeerAddress, FRootSock.FSocketNet, LADDR_BR, aPort);
  954. FRootSock.FConnectionStatus := scConnected;
  955. RegisterWithEventer;
  956. Result := True;
  957. end;
  958. end;
  959. function TLUdp.Bail(const msg: string): Boolean;
  960. begin
  961. Result := False;
  962. Disconnect(True);
  963. if Assigned(FSession) then
  964. FSession.ErrorEvent(nil, msg)
  965. else
  966. ErrorEvent(FRootSock, msg);
  967. end;
  968. procedure TLUdp.SetAddress(const Address: string);
  969. var
  970. n: Integer;
  971. s: string;
  972. p: Word;
  973. begin
  974. n := Pos(':', Address);
  975. if n > 0 then begin
  976. s := Copy(Address, 1, n-1);
  977. p := Word(StrToInt(Copy(Address, n+1, Length(Address))));
  978. FillAddressInfo(FRootSock.FPeerAddress, FRootSock.FSocketNet, s, p);
  979. end else
  980. FillAddressInfo(FRootSock.FPeerAddress, FRootSock.FSocketNet, Address,
  981. FRootSock.PeerPort);
  982. end;
  983. function TLUdp.InitSocket(aSocket: TLSocket): TLSocket;
  984. begin
  985. Result := FRootSock;
  986. if not Assigned(FRootSock) then begin
  987. aSocket.SocketType := SOCK_DGRAM;
  988. aSocket.Protocol := LPROTO_UDP;
  989. Result := inherited InitSocket(aSocket); // call last, to make sure sessions get their turn in overriding
  990. end;
  991. end;
  992. procedure TLUdp.ReceiveAction(aSocket: TLHandle);
  993. begin
  994. with TLSocket(aSocket) do begin
  995. SetState(ssCanReceive);
  996. if Assigned(FSession) then
  997. FSession.ReceiveEvent(aSocket)
  998. else
  999. ReceiveEvent(aSocket);
  1000. end;
  1001. end;
  1002. procedure TLUdp.ErrorAction(aSocket: TLHandle; const msg: string);
  1003. begin
  1004. if Assigned(FSession) then
  1005. FSession.ErrorEvent(aSocket, msg)
  1006. else
  1007. ErrorEvent(aSocket, msg);
  1008. end;
  1009. function TLUdp.IterNext: Boolean;
  1010. begin
  1011. Result := False;
  1012. end;
  1013. procedure TLUdp.IterReset;
  1014. begin
  1015. end;
  1016. procedure TLUdp.CallAction;
  1017. begin
  1018. if Assigned(FEventer) then
  1019. FEventer.CallAction;
  1020. end;
  1021. function TLUdp.GetConnected: Boolean;
  1022. begin
  1023. Result := False;
  1024. if Assigned(FRootSock) then
  1025. Result := FRootSock.ConnectionStatus = scConnected;
  1026. end;
  1027. function TLUdp.Get(out aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1028. begin
  1029. Result := 0;
  1030. if Assigned(FRootSock) then
  1031. Result := FRootSock.Get(aData, aSize);
  1032. end;
  1033. function TLUdp.GetMessage(out msg: string; aSocket: TLSocket): Integer;
  1034. begin
  1035. Result := 0;
  1036. if Assigned(FRootSock) then
  1037. Result := FRootSock.GetMessage(msg);
  1038. end;
  1039. function TLUdp.SendMessage(const msg: string; aSocket: TLSocket = nil): Integer;
  1040. begin
  1041. Result := 0;
  1042. if Assigned(FRootSock) then
  1043. Result := FRootSock.SendMessage(msg)
  1044. end;
  1045. function TLUdp.SendMessage(const msg: string; const Address: string): Integer;
  1046. begin
  1047. Result := 0;
  1048. if Assigned(FRootSock) then begin
  1049. SetAddress(Address);
  1050. Result := FRootSock.SendMessage(msg)
  1051. end;
  1052. end;
  1053. function TLUdp.Send(const aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1054. begin
  1055. Result := 0;
  1056. if Assigned(FRootSock) then
  1057. Result := FRootSock.Send(aData, aSize)
  1058. end;
  1059. function TLUdp.Send(const aData; const aSize: Integer; const Address: string
  1060. ): Integer;
  1061. begin
  1062. Result := 0;
  1063. if Assigned(FRootSock) then begin
  1064. SetAddress(Address);
  1065. Result := FRootSock.Send(aData, aSize);
  1066. end;
  1067. end;
  1068. //******************************TLTcp**********************************
  1069. constructor TLTcp.Create(aOwner: TComponent);
  1070. begin
  1071. inherited Create(aOwner);
  1072. FSocketNet := LAF_INET; // default to IPv4
  1073. FIterator := nil;
  1074. FCount := 0;
  1075. FRootSock := nil;
  1076. end;
  1077. function TLTcp.Connect(const Address: string; const APort: Word): Boolean;
  1078. begin
  1079. Result := inherited Connect(Address, aPort);
  1080. if Assigned(FRootSock) then
  1081. Disconnect(True);
  1082. FRootSock := InitSocket(SocketClass.Create);
  1083. Result := FRootSock.Connect(Address, aPort);
  1084. if Result then begin
  1085. Inc(FCount);
  1086. FIterator := FRootSock;
  1087. RegisterWithEventer;
  1088. end else begin
  1089. FreeAndNil(FRootSock); // one possible use, since we're not in eventer yet
  1090. FIterator := nil;
  1091. end;
  1092. end;
  1093. function TLTcp.Listen(const APort: Word; const AIntf: string = LADDR_ANY): Boolean;
  1094. begin
  1095. Result := false;
  1096. if Assigned(FRootSock) then
  1097. Disconnect(True);
  1098. FRootSock := InitSocket(SocketClass.Create);
  1099. FRootSock.SetReuseAddress(FReuseAddress);
  1100. if FRootSock.Listen(APort, AIntf) then begin
  1101. FRootSock.SetState(ssServerSocket);
  1102. FRootSock.FConnectionStatus := scConnected;
  1103. FIterator := FRootSock;
  1104. Inc(FCount);
  1105. RegisterWithEventer;
  1106. Result := true;
  1107. end;
  1108. end;
  1109. function TLTcp.Bail(const msg: string; aSocket: TLSocket): Boolean;
  1110. begin
  1111. Result := False;
  1112. if Assigned(FSession) then
  1113. FSession.ErrorEvent(aSocket, msg)
  1114. else
  1115. ErrorEvent(aSocket, msg);
  1116. if Assigned(aSocket) then
  1117. aSocket.Disconnect(True)
  1118. else
  1119. Disconnect(True);
  1120. end;
  1121. procedure TLTcp.SocketDisconnect(aSocket: TLSocket);
  1122. begin
  1123. if aSocket = FIterator then begin
  1124. if Assigned(FIterator.NextSock) then
  1125. FIterator := FIterator.NextSock
  1126. else if Assigned(FIterator.PrevSock) then
  1127. FIterator := FIterator.PrevSock
  1128. else FIterator := nil; // NOT iterreset, not reorganized yet
  1129. if Assigned(FIterator) and (ssServerSocket in FIterator.SocketState) then
  1130. FIterator := nil;
  1131. end;
  1132. if aSocket = FRootSock then
  1133. FRootSock := aSocket.NextSock;
  1134. if Assigned(aSocket.PrevSock) then
  1135. aSocket.PrevSock.NextSock := aSocket.NextSock;
  1136. if Assigned(aSocket.NextSock) then
  1137. aSocket.NextSock.PrevSock := aSocket.PrevSock;
  1138. Dec(FCount);
  1139. end;
  1140. function TLTcp.InitSocket(aSocket: TLSocket): TLSocket;
  1141. begin
  1142. aSocket.SocketType := SOCK_STREAM;
  1143. aSocket.Protocol := LPROTO_TCP;
  1144. aSocket.SocketNet := FSocketNet;
  1145. aSocket.FOnFree := @SocketDisconnect;
  1146. Result := inherited InitSocket(aSocket); // call last to make sure session can override options
  1147. end;
  1148. function TLTcp.IterNext: Boolean;
  1149. begin
  1150. Result := False;
  1151. if Assigned(FIterator.NextSock) then begin
  1152. FIterator := FIterator.NextSock;
  1153. Result := True;
  1154. end else IterReset;
  1155. end;
  1156. procedure TLTcp.IterReset;
  1157. begin
  1158. FIterator := FRootSock;
  1159. end;
  1160. procedure TLTcp.Disconnect(const Forced: Boolean = True);
  1161. begin
  1162. FreeSocks(Forced);
  1163. FRootSock := nil;
  1164. FCount := 0;
  1165. FIterator := nil;
  1166. end;
  1167. procedure TLTcp.CallAction;
  1168. begin
  1169. if Assigned(FEventer) then
  1170. FEventer.CallAction;
  1171. end;
  1172. procedure TLTcp.ConnectAction(aSocket: TLHandle);
  1173. var
  1174. a: TInetSockAddr;
  1175. l: Longint;
  1176. begin
  1177. with TLSocket(aSocket) do begin
  1178. l := SizeOf(a);
  1179. if Sockets.fpGetPeerName(FHandle, @a, @l) <> 0 then
  1180. Self.Bail('Error on connect: connection refused', TLSocket(aSocket))
  1181. else begin
  1182. FConnectionStatus := scConnected;
  1183. IgnoreWrite := True;
  1184. if Assigned(FSession) then
  1185. FSession.ConnectEvent(aSocket)
  1186. else
  1187. ConnectEvent(aSocket);
  1188. end;
  1189. end;
  1190. end;
  1191. procedure TLTcp.AcceptAction(aSocket: TLHandle);
  1192. var
  1193. Tmp: TLSocket;
  1194. begin
  1195. Tmp := InitSocket(SocketClass.Create);
  1196. if Tmp.Accept(FRootSock.FHandle) then begin
  1197. if Assigned(FRootSock.FNextSock) then begin
  1198. Tmp.FNextSock := FRootSock.FNextSock;
  1199. FRootSock.FNextSock.FPrevSock := Tmp;
  1200. end;
  1201. FRootSock.FNextSock := Tmp;
  1202. Tmp.FPrevSock := FRootSock;
  1203. if not Assigned(FIterator) // if we don't have (bug?) an iterator yet
  1204. or (ssServerSocket in FIterator.SocketState) then // or if it's the first socket accepted
  1205. FIterator := Tmp; // assign it as iterator (don't assign later acceptees)
  1206. Inc(FCount);
  1207. FEventer.AddHandle(Tmp);
  1208. Tmp.FConnectionStatus := scConnected;
  1209. Tmp.IgnoreWrite := True;
  1210. if Assigned(FSession) then
  1211. FSession.AcceptEvent(Tmp)
  1212. else
  1213. AcceptEvent(Tmp);
  1214. end else
  1215. Tmp.Free;
  1216. end;
  1217. procedure TLTcp.ReceiveAction(aSocket: TLHandle);
  1218. begin
  1219. if (TLSocket(aSocket) = FRootSock) and (ssServerSocket in TLSocket(aSocket).SocketState) then
  1220. AcceptAction(aSocket)
  1221. else with TLSocket(aSocket) do begin
  1222. if FConnectionStatus in [scConnected, scDisconnecting] then begin
  1223. SetState(ssCanReceive);
  1224. if Assigned(FSession) then
  1225. FSession.ReceiveEvent(aSocket)
  1226. else
  1227. ReceiveEvent(aSocket);
  1228. if not (FConnectionStatus = scConnected) then begin
  1229. DisconnectEvent(aSocket);
  1230. aSocket.Free;
  1231. end;
  1232. end;
  1233. end;
  1234. end;
  1235. procedure TLTcp.SendAction(aSocket: TLHandle);
  1236. begin
  1237. with TLSocket(aSocket) do begin
  1238. if FConnectionStatus = scConnecting then
  1239. ConnectAction(aSocket)
  1240. else
  1241. inherited;
  1242. end;
  1243. end;
  1244. procedure TLTcp.ErrorAction(aSocket: TLHandle; const msg: string);
  1245. begin
  1246. if TLSocket(aSocket).ConnectionStatus = scConnecting then begin
  1247. Self.Bail('Error on connect: connection refused', TLSocket(aSocket));
  1248. Exit;
  1249. end;
  1250. if Assigned(FSession) then
  1251. FSession.ErrorEvent(aSocket, msg)
  1252. else
  1253. ErrorEvent(aSocket, msg);
  1254. end;
  1255. function TLTcp.GetConnected: Boolean;
  1256. var
  1257. Tmp: TLSocket;
  1258. begin
  1259. Result := False;
  1260. Tmp := FRootSock;
  1261. while Assigned(Tmp) do begin
  1262. if Tmp.ConnectionStatus = scConnected then begin
  1263. Result := True;
  1264. Exit;
  1265. end else Tmp := Tmp.NextSock;
  1266. end;
  1267. end;
  1268. function TLTcp.GetConnecting: Boolean;
  1269. begin
  1270. Result := False;
  1271. if Assigned(FRootSock) then
  1272. Result := FRootSock.ConnectionStatus = scConnecting;
  1273. end;
  1274. function TLTcp.GetCount: Integer;
  1275. begin
  1276. Result := FCount;
  1277. end;
  1278. function TLTcp.GetValidSocket: TLSocket;
  1279. begin
  1280. Result := nil;
  1281. if Assigned(FIterator) and not (ssServerSocket in FIterator.SocketState) then
  1282. Result := FIterator
  1283. else if Assigned(FRootSock) and Assigned(FRootSock.FNextSock) then
  1284. Result := FRootSock.FNextSock;
  1285. end;
  1286. procedure TLTcp.SetReuseAddress(const aValue: Boolean);
  1287. begin
  1288. if not Assigned(FRootSock)
  1289. or (FRootSock.FConnectionStatus = scNone) then
  1290. FReuseAddress := aValue;
  1291. end;
  1292. procedure TLTcp.SetSocketNet(const aValue: Integer);
  1293. begin
  1294. if GetConnected then
  1295. raise Exception.Create('Cannot set socket network on a connected system');
  1296. FSocketNet := aValue;
  1297. end;
  1298. function TLTcp.Get(out aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1299. begin
  1300. Result := 0;
  1301. if not Assigned(aSocket) then
  1302. aSocket := GetValidSocket;
  1303. if Assigned(aSocket) then
  1304. Result := aSocket.Get(aData, aSize)
  1305. else
  1306. Bail('No connected socket to get through', nil);
  1307. end;
  1308. function TLTcp.GetMessage(out msg: string; aSocket: TLSocket): Integer;
  1309. begin
  1310. Result := 0;
  1311. if not Assigned(aSocket) then
  1312. aSocket := GetValidSocket;
  1313. if Assigned(aSocket) then
  1314. Result := aSocket.GetMessage(msg)
  1315. else
  1316. Bail('No connected socket to get through', nil);
  1317. end;
  1318. function TLTcp.Send(const aData; const aSize: Integer; aSocket: TLSocket): Integer;
  1319. begin
  1320. Result := 0;
  1321. if not Assigned(aSocket) then
  1322. aSocket := GetValidSocket;
  1323. if Assigned(aSocket) then
  1324. Result := aSocket.Send(aData, aSize)
  1325. else
  1326. Bail('No connected socket to send through', nil);
  1327. end;
  1328. function TLTcp.SendMessage(const msg: string; aSocket: TLSocket): Integer;
  1329. begin
  1330. Result := Send(PChar(msg)^, Length(msg), aSocket);
  1331. end;
  1332. //*******************************TLSession*********************************
  1333. procedure TLSession.RegisterWithComponent(aConnection: TLConnection);
  1334. begin
  1335. if not Assigned(aConnection) then
  1336. raise Exception.Create('Cannot register session with nil connection');
  1337. end;
  1338. procedure TLSession.InitHandle(aHandle: TLHandle);
  1339. begin
  1340. TLSocket(aHandle).FSession := Self;
  1341. end;
  1342. procedure TLSession.ReceiveEvent(aHandle: TLHandle);
  1343. begin
  1344. FActive := True;
  1345. CallReceiveEvent(aHandle);
  1346. end;
  1347. procedure TLSession.SendEvent(aHandle: TLHandle);
  1348. begin
  1349. FActive := True;
  1350. CallSendEvent(aHandle);
  1351. end;
  1352. procedure TLSession.ErrorEvent(aHandle: TLHandle; const msg: string);
  1353. begin
  1354. FActive := True;
  1355. CallErrorEvent(aHandle, msg);
  1356. end;
  1357. procedure TLSession.ConnectEvent(aHandle: TLHandle);
  1358. begin
  1359. FActive := True;
  1360. CallConnectEvent(aHandle);
  1361. end;
  1362. procedure TLSession.AcceptEvent(aHandle: TLHandle);
  1363. begin
  1364. FActive := True;
  1365. CallAcceptEvent(aHandle);
  1366. end;
  1367. procedure TLSession.DisconnectEvent(aHandle: TLHandle);
  1368. begin
  1369. FActive := True;
  1370. CallDisconnectEvent(aHandle);
  1371. end;
  1372. procedure TLSession.CallReceiveEvent(aHandle: TLHandle); inline;
  1373. begin
  1374. TLSocket(aHandle).FConnection.ReceiveEvent(TLSocket(aHandle));
  1375. end;
  1376. procedure TLSession.CallSendEvent(aHandle: TLHandle); inline;
  1377. begin
  1378. TLSocket(aHandle).FConnection.CanSendEvent(TLSocket(aHandle));
  1379. end;
  1380. procedure TLSession.CallErrorEvent(aHandle: TLHandle; const msg: string);
  1381. inline;
  1382. begin
  1383. TLSocket(aHandle).FConnection.ErrorEvent(TLSocket(aHandle), msg);
  1384. end;
  1385. procedure TLSession.CallConnectEvent(aHandle: TLHandle); inline;
  1386. begin
  1387. TLSocket(aHandle).FConnection.ConnectEvent(TLSocket(aHandle));
  1388. end;
  1389. procedure TLSession.CallAcceptEvent(aHandle: TLHandle); inline;
  1390. begin
  1391. TLSocket(aHandle).FConnection.AcceptEvent(TLSocket(aHandle));
  1392. end;
  1393. procedure TLSession.CallDisconnectEvent(aHandle: TLHandle); inline;
  1394. begin
  1395. TLSocket(aHandle).FConnection.DisconnectEvent(TLSocket(aHandle));
  1396. end;
  1397. end.