lnet.pp 47 KB

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