lnet.pp 47 KB

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