IdStack.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10343: IdStack.pas
  11. {
  12. { Rev 1.2 2003.06.04 10:49:12 PM czhower
  13. { Fixed bug which caused IsIP to fail on successive calls because of
  14. { unitialized values and therefore caused connect errors.
  15. }
  16. {
  17. { Rev 1.1 4/20/03 1:49:26 PM RLebeau
  18. { Added new methods: GetIPInfo(), GetIPType(), GetIPClass(), IPIsType(),
  19. { IPIsClass(), IsDottedIP(), and IsNumericIP().
  20. {
  21. { Added EIdInvalidIPAddress exception class.
  22. }
  23. {
  24. { Rev 1.0 2002.11.12 10:53:10 PM czhower
  25. }
  26. unit IdStack;
  27. interface
  28. uses
  29. Classes,
  30. IdException,
  31. IdStackConsts, IdGlobal;
  32. type
  33. TIdServeFile = function(ASocket: TIdStackSocketHandle; AFileName: string): cardinal;
  34. // Abstract IdStack class
  35. TIdSunB = packed record
  36. s_b1, s_b2, s_b3, s_b4: byte;
  37. end;
  38. TIdSunW = packed record
  39. s_w1, s_w2: word;
  40. end;
  41. PIdInAddr = ^TIdInAddr;
  42. TIdInAddr = record
  43. case integer of
  44. 0: (S_un_b: TIdSunB);
  45. 1: (S_un_w: TIdSunW);
  46. 2: (S_addr: longword);
  47. end;
  48. TIdIPType = (Id_IPInvalid, Id_IPDotted, Id_IPNumeric);
  49. PIdIPType = ^TIdIPType;
  50. TIdIPClass = (Id_IPClassUnkn, Id_IPClassA, Id_IPClassB, Id_IPClassC, Id_IPClassD, Id_IPClassE);
  51. PIdIPClass = ^TIdIPClass;
  52. TIdSocketListClass = class of TIdSocketList;
  53. TIdSocketList = class
  54. protected
  55. function GetItem(AIndex: Integer): TIdStackSocketHandle; virtual; abstract;
  56. public
  57. procedure Add(AHandle: TIdStackSocketHandle); virtual; abstract;
  58. class function CreateSocketList: TIdSocketList;
  59. procedure Remove(AHandle: TIdStackSocketHandle); virtual; abstract;
  60. function Count: Integer; virtual; abstract;
  61. property Items[AIndex: Integer]: TIdStackSocketHandle read GetItem; default;
  62. End;//TIdSocketList
  63. TIdStack = class
  64. protected
  65. FLastError: Integer;
  66. FLocalAddress: string;
  67. FLocalAddresses: TStrings;
  68. //
  69. procedure PopulateLocalAddresses; virtual; abstract;
  70. function WSGetLocalAddress: string; virtual; abstract;
  71. function WSGetLocalAddresses: TStrings; virtual; abstract;
  72. public
  73. function CheckForSocketError(const AResult: integer = Id_SOCKET_ERROR): boolean; overload;
  74. function CheckForSocketError(const AResult: integer; const AIgnore: array of integer)
  75. : boolean; overload;
  76. constructor Create; reintroduce; virtual;
  77. destructor Destroy; override;
  78. class function CreateStack: TIdStack;
  79. function CreateSocketHandle(const ASocketType: Integer;
  80. const AProtocol: Integer = Id_IPPROTO_IP): TIdStackSocketHandle;
  81. function GetIPInfo(const AIP: string; VB1: PByte = nil; VB2: PByte = nil;
  82. VB3: PByte = nil; VB4: PByte = nil; VType: PIdIPType = nil; VClass: PIdIPClass = nil): Boolean;
  83. function GetIPType(const AIP: string): TIdIPType;
  84. function GetIPClass(const AIP: string): TIdIPClass;
  85. function IsIP(const AIP: string): boolean;
  86. function IPIsType(const AIP: string; const AType: TIdIPType): boolean; overload;
  87. function IPIsType(const AIP: string; const ATypes: array of TIdIPType): boolean; overload;
  88. function IPIsClass(const AIP: string; const AClass: TIdIPClass): boolean; overload;
  89. function IPIsClass(const AIP: string; const AClasses: array of TIdIPClass): boolean; overload;
  90. function IsDottedIP(const AIP: string): boolean;
  91. function IsNumericIP(const AIP: string): boolean;
  92. procedure RaiseSocketError(const AErr: integer);
  93. function ResolveHost(const AHost: string): string;
  94. // Resolves host passed in sHost. sHost may be an IP or a HostName.
  95. // sIP returns string version of the IP
  96. function WSAccept(ASocket: TIdStackSocketHandle; var VIP: string; var VPort: Integer)
  97. : TIdStackSocketHandle; virtual; abstract;
  98. function WSBind(ASocket: TIdStackSocketHandle; const AFamily: Integer;
  99. const AIP: string; const APort: Integer): Integer; virtual; abstract;
  100. function WSCloseSocket(ASocket: TIdStackSocketHandle): Integer; virtual; abstract;
  101. function WSConnect(const ASocket: TIdStackSocketHandle; const AFamily: Integer;
  102. const AIP: string; const APort: Integer): Integer; virtual; abstract;
  103. function WSGetHostByName(const AHostName: string): string; virtual; abstract;
  104. function WSGetHostName: string; virtual; abstract;
  105. function WSGetHostByAddr(const AAddress: string): string; virtual; abstract;
  106. function WSGetServByName(const AServiceName: string): Integer; virtual; abstract;
  107. function WSGetServByPort(const APortNumber: Integer): TStrings; virtual; abstract;
  108. function WSHToNs(AHostShort: Word): Word; virtual; abstract;
  109. function WSListen(ASocket: TIdStackSocketHandle; ABackLog: Integer): Integer; virtual; abstract;
  110. function WSNToHs(ANetShort: Word): Word; virtual; abstract;
  111. function WSHToNL(AHostLong: LongWord): LongWord; virtual; abstract;
  112. function WSNToHL(ANetLong: LongWord): LongWord; virtual; abstract;
  113. function WSRecv(ASocket: TIdStackSocketHandle; var ABuffer; const ABufferLength, AFlags: Integer)
  114. : Integer; virtual; abstract;
  115. function WSRecvFrom(const ASocket: TIdStackSocketHandle; var ABuffer;
  116. const ALength, AFlags: Integer; var VIP: string; var VPort: Integer): Integer; virtual;
  117. abstract;
  118. function WSSelect(ARead, AWrite, AErrors: TList; ATimeout: Integer): Integer; virtual; abstract;
  119. function WSSend(ASocket: TIdStackSocketHandle; var ABuffer;
  120. const ABufferLength, AFlags: Integer): Integer; virtual; abstract;
  121. function WSSendTo(ASocket: TIdStackSocketHandle; var ABuffer;
  122. const ABufferLength, AFlags: Integer; const AIP: string; const APort: integer): Integer;
  123. virtual; abstract;
  124. function WSSetSockOpt(ASocket: TIdStackSocketHandle; ALevel, AOptName: Integer; AOptVal: PChar;
  125. AOptLen: Integer): Integer; virtual; abstract;
  126. function WSSocket(AFamily, AStruct, AProtocol: Integer): TIdStackSocketHandle; virtual; abstract;
  127. function WSShutdown(ASocket: TIdStackSocketHandle; AHow: Integer): Integer; virtual; abstract;
  128. function WSTranslateSocketErrorMsg(const AErr: integer): string; virtual;
  129. function WSGetLastError: Integer; virtual; abstract;
  130. procedure WSGetPeerName(ASocket: TIdStackSocketHandle; var AFamily: Integer;
  131. var AIP: string; var APort: Integer); virtual; abstract;
  132. procedure WSGetSockName(ASocket: TIdStackSocketHandle; var AFamily: Integer;
  133. var AIP: string; var APort: Integer); virtual; abstract;
  134. function WSGetSockOpt(ASocket: TIdStackSocketHandle; Alevel, AOptname: Integer; AOptval: PChar; var AOptlen: Integer) : Integer; virtual; abstract;
  135. function StringToTInAddr(AIP: string): TIdInAddr;
  136. function TInAddrToString(var AInAddr): string; virtual; abstract;
  137. procedure TranslateStringToTInAddr(AIP: string; var AInAddr); virtual; abstract;
  138. //
  139. property LastError: Integer read FLastError;
  140. property LocalAddress: string read WSGetLocalAddress;
  141. property LocalAddresses: TStrings read WSGetLocalAddresses;
  142. end;
  143. TIdStackClass = class of TIdStack;
  144. EIdStackError = class (EIdException);
  145. EIdStackInitializationFailed = class (EIdStackError);
  146. EIdStackSetSizeExceeded = class (EIdStackError);
  147. EIdInvalidIPAddress = class (EIdStackError);
  148. var
  149. GStack: TIdStack = nil;
  150. GStackClass: TIdStackClass = nil;
  151. GServeFileProc: TIdServeFile = nil;
  152. GSocketListClass: TIdSocketListClass;
  153. implementation
  154. uses
  155. IdResourceStrings,
  156. SysUtils;
  157. { TIdStack }
  158. function TIdStack.CheckForSocketError(const AResult: integer): boolean;
  159. begin
  160. Result := CheckForSocketError(AResult, []);
  161. end;
  162. function TIdStack.CheckForSocketError(const AResult: integer;
  163. const AIgnore: array of integer): boolean;
  164. var
  165. i: integer;
  166. begin
  167. Result := false;
  168. if AResult = Id_SOCKET_ERROR then begin
  169. FLastError := WSGetLastError;
  170. for i := Low(AIgnore) to High(AIgnore) do begin
  171. if LastError = AIgnore[i] then begin
  172. Result := True;
  173. exit;
  174. end;
  175. end;
  176. RaiseSocketError(LastError);
  177. end;
  178. end;
  179. function TIdStack.CreateSocketHandle(const ASocketType: Integer;
  180. const AProtocol: Integer = Id_IPPROTO_IP): TIdStackSocketHandle;
  181. begin
  182. result := WSSocket(Id_PF_INET, ASocketType, AProtocol);
  183. if result = Id_INVALID_SOCKET then begin
  184. raise EIdInvalidSocket.Create(RSCannotAllocateSocket);
  185. end;
  186. end;
  187. procedure TIdStack.RaiseSocketError(const AErr: integer);
  188. begin
  189. (*
  190. RRRRR EEEEEE AAAA DDDDD MM MM EEEEEE !! !! !!
  191. RR RR EE AA AA DD DD MMMM MMMM EE !! !! !!
  192. RRRRR EEEE AAAAAA DD DD MM MMM MM EEEE !! !! !!
  193. RR RR EE AA AA DD DD MM MM EE
  194. RR RR EEEEEE AA AA DDDDD MM MM EEEEEE .. .. ..
  195. Please read the note in the next comment.
  196. *)
  197. raise EIdSocketError.CreateError(AErr, WSTranslateSocketErrorMsg(AErr));
  198. (*
  199. It is normal to receive a 10038 exception (10038, NOT others!) here when
  200. *shutting down* (NOT at other times!) servers (NOT clients!).
  201. If you receive a 10038 exception here please see the FAQ at:
  202. http://www.nevrona.com/Indy/FAQ.html
  203. If you get a 10038 exception here, and HAVE NOT read the FAQ and ask about this in the public
  204. forums
  205. you will be publicly flogged, tarred and feathered and your name added to every chain
  206. letter in existence today.
  207. If you insist upon requesting help via our email boxes on the 10038 error that is already
  208. answered in the FAQ and you are simply too slothful to search for your answer and ask your
  209. question in the public forums you may be publicly flogged, tarred and feathered and your name
  210. may be added to every chain letter / EMail in existence today."
  211. Otherwise, if you DID read the FAQ and have further questions, please feel free to ask using
  212. one of the methods (Carefullly note that these methods do not list email) listed on the Tech
  213. Support link at http://www.nevrona.com/Indy/
  214. RRRRR EEEEEE AAAA DDDDD MM MM EEEEEE !! !! !!
  215. RR RR EE AA AA DD DD MMMM MMMM EE !! !! !!
  216. RRRRR EEEE AAAAAA DD DD MM MMM MM EEEE !! !! !!
  217. RR RR EE AA AA DD DD MM MM EE
  218. RR RR EEEEEE AA AA DDDDD MM MM EEEEEE .. .. ..
  219. *)
  220. end;
  221. constructor TIdStack.Create;
  222. begin
  223. // Here so descendants can override and call inherited for future exp since TObject's Create {Do not Localize}
  224. // is not virtual
  225. end;
  226. class function TIdStack.CreateStack: TIdStack;
  227. begin
  228. Result := GStackClass.Create;
  229. end;
  230. function TIdStack.ResolveHost(const AHost: string): string;
  231. begin
  232. // Sometimes 95 forgets who localhost is
  233. if AnsiSameText(AHost, 'LOCALHOST') then begin {Do not Localize}
  234. result := '127.0.0.1'; {Do not Localize}
  235. end else if IsIP(AHost) then begin
  236. result := AHost;
  237. end else begin
  238. result := WSGetHostByName(AHost);
  239. end;
  240. end;
  241. function TIdStack.WSTranslateSocketErrorMsg(const AErr: integer): string;
  242. begin
  243. Result := ''; {Do not Localize}
  244. case AErr of
  245. Id_WSAEINTR: Result := RSStackEINTR;
  246. Id_WSAEBADF: Result := RSStackEBADF;
  247. Id_WSAEACCES: Result := RSStackEACCES;
  248. Id_WSAEFAULT: Result := RSStackEFAULT;
  249. Id_WSAEINVAL: Result := RSStackEINVAL;
  250. Id_WSAEMFILE: Result := RSStackEMFILE;
  251. Id_WSAEWOULDBLOCK: Result := RSStackEWOULDBLOCK;
  252. Id_WSAEINPROGRESS: Result := RSStackEINPROGRESS;
  253. Id_WSAEALREADY: Result := RSStackEALREADY;
  254. Id_WSAENOTSOCK: Result := RSStackENOTSOCK;
  255. Id_WSAEDESTADDRREQ: Result := RSStackEDESTADDRREQ;
  256. Id_WSAEMSGSIZE: Result := RSStackEMSGSIZE;
  257. Id_WSAEPROTOTYPE: Result := RSStackEPROTOTYPE;
  258. Id_WSAENOPROTOOPT: Result := RSStackENOPROTOOPT;
  259. Id_WSAEPROTONOSUPPORT: Result := RSStackEPROTONOSUPPORT;
  260. Id_WSAESOCKTNOSUPPORT: Result := RSStackESOCKTNOSUPPORT;
  261. Id_WSAEOPNOTSUPP: Result := RSStackEOPNOTSUPP;
  262. Id_WSAEPFNOSUPPORT: Result := RSStackEPFNOSUPPORT;
  263. Id_WSAEAFNOSUPPORT: Result := RSStackEAFNOSUPPORT;
  264. Id_WSAEADDRINUSE: Result := RSStackEADDRINUSE;
  265. Id_WSAEADDRNOTAVAIL: Result := RSStackEADDRNOTAVAIL;
  266. Id_WSAENETDOWN: Result := RSStackENETDOWN;
  267. Id_WSAENETUNREACH: Result := RSStackENETUNREACH;
  268. Id_WSAENETRESET: Result := RSStackENETRESET;
  269. Id_WSAECONNABORTED: Result := RSStackECONNABORTED;
  270. Id_WSAECONNRESET: Result := RSStackECONNRESET;
  271. Id_WSAENOBUFS: Result := RSStackENOBUFS;
  272. Id_WSAEISCONN: Result := RSStackEISCONN;
  273. Id_WSAENOTCONN: Result := RSStackENOTCONN;
  274. Id_WSAESHUTDOWN: Result := RSStackESHUTDOWN;
  275. Id_WSAETOOMANYREFS: Result := RSStackETOOMANYREFS;
  276. Id_WSAETIMEDOUT: Result := RSStackETIMEDOUT;
  277. Id_WSAECONNREFUSED: Result := RSStackECONNREFUSED;
  278. Id_WSAELOOP: Result := RSStackELOOP;
  279. Id_WSAENAMETOOLONG: Result := RSStackENAMETOOLONG;
  280. Id_WSAEHOSTDOWN: Result := RSStackEHOSTDOWN;
  281. Id_WSAEHOSTUNREACH: Result := RSStackEHOSTUNREACH;
  282. Id_WSAENOTEMPTY: Result := RSStackENOTEMPTY;
  283. end;
  284. Result := Format(RSStackError, [AErr, Result]);
  285. end;
  286. function TIdStack.GetIPInfo(const AIP: string; VB1: PByte = nil;
  287. VB2: PByte = nil; VB3: PByte = nil; VB4: PByte = nil; VType: PIdIPType = nil;
  288. VClass: PIdIPClass = nil): Boolean;
  289. var
  290. sTemp, s1, s2, s3, s4: string;
  291. b1, b2, b3, b4: Byte;
  292. LType: TIdIPType;
  293. LClass: TIdIPClass;
  294. i: Integer;
  295. w: Word;
  296. c: Cardinal;
  297. function ByteIsOk(const AByte: string; var VB: Byte): boolean;
  298. var
  299. i: Integer;
  300. begin
  301. i := StrToIntDef(AByte, -1);
  302. Result := (i > -1) and (i < 256);
  303. if Result then VB := Byte(i);
  304. end;
  305. function WordIsOk(const AWord: string; var VW: Word): boolean;
  306. var
  307. i: Integer;
  308. begin
  309. i := StrToIntDef(AWord, -1);
  310. Result := (i > -1) and (i < 65536);
  311. if Result then VW := Word(i);
  312. end;
  313. function TwentyFourBitValueIsOk(const AValue: string; var VI: Integer): boolean;
  314. var
  315. i: Integer;
  316. begin
  317. i := StrToIntDef(AValue, -1);
  318. Result := (i > -1) and (i < 16777216);
  319. if Result then VI := i;
  320. end;
  321. function LongIsOk(const ALong: string; var VC: Cardinal): boolean;
  322. var
  323. i: Int64;
  324. begin
  325. i := StrToInt64Def(ALong, -1);
  326. Result := (i > -1) and (i < 4294967296);
  327. if Result then VC := Cardinal(i);
  328. end;
  329. begin
  330. Result := False;
  331. LType := Id_IPInvalid;
  332. LClass := Id_IPClassUnkn;
  333. sTemp := AIP;
  334. s1 := Fetch(sTemp, '.'); {Do not Localize}
  335. s2 := Fetch(sTemp, '.'); {Do not Localize}
  336. s3 := Fetch(sTemp, '.'); {Do not Localize}
  337. s4 := sTemp;
  338. if s2 = '' then
  339. begin
  340. // RL: 4/13/2003: this probably needs to be tweaked better
  341. if LongIsOk(s1, c) then
  342. begin
  343. b1 := (c and $FF000000) shr 24;
  344. b2 := (c and $00FF0000) shr 16;
  345. b3 := (c and $0000FF00) shr 8;
  346. b4 := (c and $000000FF);
  347. LType := Id_IPNumeric;
  348. end;
  349. end
  350. else if s3 = '' then
  351. begin
  352. // class A address
  353. if ByteIsOk(s1, b1) and TwentyFourBitValueIsOk(s2, i) then
  354. begin
  355. b2 := (i and $00FF0000) shr 16;
  356. b3 := (i and $0000FF00) shr 8;
  357. b4 := (i and $000000FF);
  358. LType := Id_IPDotted;
  359. LClass := Id_IPClassA;
  360. end
  361. end
  362. else if s4 = '' then
  363. begin
  364. // class B address
  365. if ByteIsOk(s1, b1) and ByteIsOk(s2, b2) and WordIsOk(s3, w) then
  366. begin
  367. b3 := (w and $FF00) shr 8;
  368. b4 := (w and $00FF);
  369. LType := Id_IPDotted;
  370. LClass := Id_IPClassB;
  371. end
  372. end
  373. else
  374. begin
  375. // class C-E address
  376. if ByteIsOk(s1, b1) and ByteIsOk(s2, b2) and
  377. ByteIsOk(s3, b3) and ByteIsOk(s4, b4) then
  378. begin
  379. LType := Id_IPDotted;
  380. Case b1 of
  381. 0..127: LClass := Id_IPClassA;
  382. 128..191: LClass := Id_IPClassB;
  383. 192..223: LClass := Id_IPClassC;
  384. 224..239: LClass := Id_IPClassD;
  385. else
  386. LClass := Id_IPClassE;
  387. end
  388. end
  389. end;
  390. if LType <> Id_IPInvalid then
  391. begin
  392. if (VB1 <> nil) then begin
  393. VB1^ := b1;
  394. end;
  395. if (VB2 <> nil) then begin
  396. VB2^ := b2;
  397. end;
  398. if (VB3 <> nil) then begin
  399. VB3^ := b3;
  400. end;
  401. if (VB4 <> nil) then begin
  402. VB4^ := b4;
  403. end;
  404. Result := True;
  405. end;
  406. if (VType <> nil) then begin
  407. VType^ := LType;
  408. end;
  409. if (VClass <> nil) then begin
  410. VClass^ := LClass;
  411. end;
  412. end;
  413. function TIdStack.GetIPType(const AIP: string): TIdIPType;
  414. begin
  415. GetIPInfo(AIP, nil, nil, nil, nil, @Result);
  416. end;
  417. function TIdStack.GetIPClass(const AIP: string): TIdIPClass;
  418. begin
  419. GetIPInfo(AIP, nil, nil, nil, nil, nil, @Result);
  420. end;
  421. function TIdStack.IsIP(const AIP: string): boolean;
  422. begin
  423. Result := not IPIsType(AIP, Id_IPInvalid);
  424. end;
  425. function TIdStack.IPIsType(const AIP: string; const AType: TIdIPType): boolean;
  426. begin
  427. Result := GetIPType(AIP) = AType;
  428. end;
  429. function TIdStack.IPIsType(const AIP: string; const ATypes: array of TIdIPType): boolean;
  430. var
  431. i: Integer;
  432. LType: TIdIPType;
  433. begin
  434. Result := False;
  435. LType := GetIPType(AIP);
  436. for i := Low(ATypes) to High(ATypes) do begin
  437. if LType = ATypes[i] then begin
  438. Result := True;
  439. Break;
  440. end;
  441. end;
  442. end;
  443. function TIdStack.IPIsClass(const AIP: string; const AClass: TIdIPClass): boolean;
  444. begin
  445. Result := GetIPClass(AIP) = AClass;
  446. end;
  447. function TIdStack.IPIsClass(const AIP: string; const AClasses: array of TIdIPClass): boolean;
  448. var
  449. i: Integer;
  450. LClass: TIdIPClass;
  451. begin
  452. Result := False;
  453. LClass := GetIPClass(AIP);
  454. for i := Low(AClasses) to High(AClasses) do begin
  455. if LClass = AClasses[i] then begin
  456. Result := True;
  457. Break;
  458. end;
  459. end;
  460. end;
  461. function TIdStack.IsDottedIP(const AIP: string): boolean;
  462. begin
  463. Result := IPIsType(AIP, Id_IPDotted);
  464. end;
  465. function TIdStack.IsNumericIP(const AIP: string): boolean;
  466. begin
  467. Result := IPIsType(AIP, Id_IPNumeric);
  468. end;
  469. destructor TIdStack.Destroy;
  470. begin
  471. FLocalAddresses.Free;
  472. inherited;
  473. end;
  474. function TIdStack.StringToTInAddr(AIP: string): TIdInAddr;
  475. begin
  476. TranslateStringToTInAddr(AIP, result);
  477. end;
  478. { TIdSocketList }
  479. class function TIdSocketList.CreateSocketList: TIdSocketList;
  480. Begin
  481. Result := GSocketListClass.Create;
  482. End;//
  483. end.