ssfpc.inc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.001.005 |
  3. |==============================================================================|
  4. | Content: Socket Independent Platform Layer - FreePascal definition include |
  5. |==============================================================================|
  6. | Copyright (c)2006-2013, Lukas Gebauer |
  7. | All rights reserved. |
  8. | |
  9. | Redistribution and use in source and binary forms, with or without |
  10. | modification, are permitted provided that the following conditions are met: |
  11. | |
  12. | Redistributions of source code must retain the above copyright notice, this |
  13. | list of conditions and the following disclaimer. |
  14. | |
  15. | Redistributions in binary form must reproduce the above copyright notice, |
  16. | this list of conditions and the following disclaimer in the documentation |
  17. | and/or other materials provided with the distribution. |
  18. | |
  19. | Neither the name of Lukas Gebauer nor the names of its contributors may |
  20. | be used to endorse or promote products derived from this software without |
  21. | specific prior written permission. |
  22. | |
  23. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
  24. | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
  25. | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
  26. | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
  27. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
  28. | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
  29. | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
  30. | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  31. | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
  32. | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
  33. | DAMAGE. |
  34. |==============================================================================|
  35. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  36. | Portions created by Lukas Gebauer are Copyright (c)2006-2013. |
  37. | All Rights Reserved. |
  38. |==============================================================================|
  39. | Contributor(s): |
  40. |==============================================================================|
  41. | History: see HISTORY.HTM from distribution package |
  42. | (Found at URL: http://www.ararat.cz/synapse/) |
  43. |==============================================================================}
  44. {:@exclude}
  45. {$IFDEF FPC}
  46. {For FreePascal 2.x.x}
  47. //{$DEFINE FORCEOLDAPI}
  48. {Note about define FORCEOLDAPI:
  49. If you activate this compiler directive, then is allways used old socket API
  50. for name resolution. If you leave this directive inactive, then the new API
  51. is used, when running system allows it.
  52. For IPv6 support you must have new API!
  53. }
  54. {$IFDEF FPC}
  55. {$MODE DELPHI}
  56. {$ENDIF}
  57. {$H+}
  58. {$ifdef FreeBSD}
  59. {$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
  60. {$endif}
  61. {$ifdef darwin}
  62. {$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
  63. {$endif}
  64. {$ifdef haiku}
  65. {$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
  66. {$endif}
  67. interface
  68. uses
  69. SyncObjs, SysUtils, Classes,
  70. synafpc, BaseUnix, Unix, termio, sockets, netdb;
  71. function InitSocketInterface(stack: string): Boolean;
  72. function DestroySocketInterface: Boolean;
  73. const
  74. DLLStackName = '';
  75. WinsockLevel = $0202;
  76. cLocalHost = '127.0.0.1';
  77. cAnyHost = '0.0.0.0';
  78. c6AnyHost = '::0';
  79. c6Localhost = '::1';
  80. cLocalHostStr = 'localhost';
  81. type
  82. TSocket = longint;
  83. TAddrFamily = integer;
  84. TMemory = pointer;
  85. type
  86. TFDSet = Baseunix.TFDSet;
  87. PFDSet = ^TFDSet;
  88. Ptimeval = Baseunix.ptimeval;
  89. Ttimeval = Baseunix.ttimeval;
  90. const
  91. FIONREAD = termio.FIONREAD;
  92. FIONBIO = termio.FIONBIO;
  93. {$IFNDEF HAIKU}
  94. FIOASYNC = termio.FIOASYNC;
  95. {$ENDIF}
  96. const
  97. IPPROTO_IP = 0; { Dummy }
  98. IPPROTO_ICMP = 1; { Internet Control Message Protocol }
  99. IPPROTO_IGMP = 2; { Internet Group Management Protocol}
  100. IPPROTO_TCP = 6; { TCP }
  101. IPPROTO_UDP = 17; { User Datagram Protocol }
  102. IPPROTO_IPV6 = 41;
  103. IPPROTO_ICMPV6 = 58;
  104. IPPROTO_RM = 113;
  105. IPPROTO_RAW = 255;
  106. IPPROTO_MAX = 256;
  107. type
  108. PInAddr = ^TInAddr;
  109. TInAddr = sockets.in_addr;
  110. PSockAddrIn = ^TSockAddrIn;
  111. TSockAddrIn = sockets.TInetSockAddr;
  112. TIP_mreq = record
  113. imr_multiaddr: TInAddr; // IP multicast address of group
  114. imr_interface: TInAddr; // local IP address of interface
  115. end;
  116. PInAddr6 = ^TInAddr6;
  117. TInAddr6 = sockets.Tin6_addr;
  118. PSockAddrIn6 = ^TSockAddrIn6;
  119. TSockAddrIn6 = sockets.TInetSockAddr6;
  120. TIPv6_mreq = record
  121. ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
  122. ipv6mr_interface: integer; // Interface index.
  123. end;
  124. const
  125. INADDR_ANY = $00000000;
  126. INADDR_LOOPBACK = $7F000001;
  127. INADDR_BROADCAST = $FFFFFFFF;
  128. INADDR_NONE = $FFFFFFFF;
  129. ADDR_ANY = INADDR_ANY;
  130. INVALID_SOCKET = TSocket(NOT(0));
  131. SOCKET_ERROR = -1;
  132. Const
  133. IP_TOS = sockets.IP_TOS; { int; IP type of service and precedence. }
  134. IP_TTL = sockets.IP_TTL; { int; IP time to live. }
  135. IP_HDRINCL = sockets.IP_HDRINCL; { int; Header is included with data. }
  136. IP_OPTIONS = sockets.IP_OPTIONS; { ip_opts; IP per-packet options. }
  137. // IP_ROUTER_ALERT = sockets.IP_ROUTER_ALERT; { bool }
  138. IP_RECVOPTS = sockets.IP_RECVOPTS; { bool }
  139. IP_RETOPTS = sockets.IP_RETOPTS; { bool }
  140. // IP_PKTINFO = sockets.IP_PKTINFO; { bool }
  141. // IP_PKTOPTIONS = sockets.IP_PKTOPTIONS;
  142. // IP_PMTUDISC = sockets.IP_PMTUDISC; { obsolete name? }
  143. // IP_MTU_DISCOVER = sockets.IP_MTU_DISCOVER; { int; see below }
  144. // IP_RECVERR = sockets.IP_RECVERR; { bool }
  145. // IP_RECVTTL = sockets.IP_RECVTTL; { bool }
  146. // IP_RECVTOS = sockets.IP_RECVTOS; { bool }
  147. IP_MULTICAST_IF = sockets.IP_MULTICAST_IF; { in_addr; set/get IP multicast i/f }
  148. IP_MULTICAST_TTL = sockets.IP_MULTICAST_TTL; { u_char; set/get IP multicast ttl }
  149. IP_MULTICAST_LOOP = sockets.IP_MULTICAST_LOOP; { i_char; set/get IP multicast loopback }
  150. IP_ADD_MEMBERSHIP = sockets.IP_ADD_MEMBERSHIP; { ip_mreq; add an IP group membership }
  151. IP_DROP_MEMBERSHIP = sockets.IP_DROP_MEMBERSHIP; { ip_mreq; drop an IP group membership }
  152. SOL_SOCKET = sockets.SOL_SOCKET;
  153. SO_DEBUG = sockets.SO_DEBUG;
  154. SO_REUSEADDR = sockets.SO_REUSEADDR;
  155. SO_TYPE = sockets.SO_TYPE;
  156. SO_ERROR = sockets.SO_ERROR;
  157. SO_DONTROUTE = sockets.SO_DONTROUTE;
  158. SO_BROADCAST = sockets.SO_BROADCAST;
  159. SO_SNDBUF = sockets.SO_SNDBUF;
  160. SO_RCVBUF = sockets.SO_RCVBUF;
  161. SO_KEEPALIVE = sockets.SO_KEEPALIVE;
  162. SO_OOBINLINE = sockets.SO_OOBINLINE;
  163. // SO_NO_CHECK = sockets.SO_NO_CHECK;
  164. // SO_PRIORITY = sockets.SO_PRIORITY;
  165. SO_LINGER = sockets.SO_LINGER;
  166. // SO_BSDCOMPAT = sockets.SO_BSDCOMPAT;
  167. // SO_REUSEPORT = sockets.SO_REUSEPORT;
  168. // SO_PASSCRED = sockets.SO_PASSCRED;
  169. // SO_PEERCRED = sockets.SO_PEERCRED;
  170. SO_RCVLOWAT = sockets.SO_RCVLOWAT;
  171. SO_SNDLOWAT = sockets.SO_SNDLOWAT;
  172. SO_RCVTIMEO = sockets.SO_RCVTIMEO;
  173. SO_SNDTIMEO = sockets.SO_SNDTIMEO;
  174. { Security levels - as per NRL IPv6 - don't actually do anything }
  175. // SO_SECURITY_AUTHENTICATION = sockets.SO_SECURITY_AUTHENTICATION;
  176. // SO_SECURITY_ENCRYPTION_TRANSPORT = sockets.SO_SECURITY_ENCRYPTION_TRANSPORT;
  177. // SO_SECURITY_ENCRYPTION_NETWORK = sockets.SO_SECURITY_ENCRYPTION_NETWORK;
  178. // SO_BINDTODEVICE = sockets.SO_BINDTODEVICE;
  179. { Socket filtering }
  180. // SO_ATTACH_FILTER = sockets.SO_ATTACH_FILTER;
  181. // SO_DETACH_FILTER = sockets.SO_DETACH_FILTER;
  182. {$IFDEF DARWIN}
  183. SO_NOSIGPIPE = $1022;
  184. {$ENDIF}
  185. SOMAXCONN = 1024;
  186. {$IFDEF HAIKU}
  187. IPV6_UNICAST_HOPS = 27;
  188. {$ELSE}
  189. IPV6_UNICAST_HOPS = sockets.IPV6_UNICAST_HOPS;
  190. {$ENDIF}
  191. IPV6_MULTICAST_IF = sockets.IPV6_MULTICAST_IF;
  192. IPV6_MULTICAST_HOPS = sockets.IPV6_MULTICAST_HOPS;
  193. IPV6_MULTICAST_LOOP = sockets.IPV6_MULTICAST_LOOP;
  194. {$IFDEF HAIKU}
  195. IPV6_JOIN_GROUP = 28;
  196. IPV6_LEAVE_GROUP = 29;
  197. {$ELSE}
  198. IPV6_JOIN_GROUP = sockets.IPV6_JOIN_GROUP;
  199. IPV6_LEAVE_GROUP = sockets.IPV6_LEAVE_GROUP;
  200. {$ENDIF}
  201. const
  202. SOCK_STREAM = 1; { stream socket }
  203. SOCK_DGRAM = 2; { datagram socket }
  204. SOCK_RAW = 3; { raw-protocol interface }
  205. SOCK_RDM = 4; { reliably-delivered message }
  206. SOCK_SEQPACKET = 5; { sequenced packet stream }
  207. { TCP options. }
  208. TCP_NODELAY = $0001;
  209. { Address families. }
  210. AF_UNSPEC = 0; { unspecified }
  211. AF_INET = sockets.AF_INET; { internetwork: UDP, TCP, etc. }
  212. AF_INET6 = sockets.AF_INET6; { Internetwork Version 6 }
  213. AF_MAX = 24;
  214. { Protocol families, same as address families for now. }
  215. PF_UNSPEC = AF_UNSPEC;
  216. PF_INET = AF_INET;
  217. PF_INET6 = AF_INET6;
  218. PF_MAX = AF_MAX;
  219. type
  220. { Structure used for manipulating linger option. }
  221. PLinger = ^TLinger;
  222. TLinger = packed record
  223. l_onoff: integer;
  224. l_linger: integer;
  225. end;
  226. const
  227. MSG_OOB = sockets.MSG_OOB; // Process out-of-band data.
  228. MSG_PEEK = sockets.MSG_PEEK; // Peek at incoming messages.
  229. {$if defined(DARWIN)}
  230. MSG_NOSIGNAL = $20000; // Do not generate SIGPIPE.
  231. // Works under MAC OS X, but is undocumented,
  232. // So FPC doesn't include it
  233. {$elseif defined(HAIKU)}
  234. MSG_NOSIGNAL = $0800;
  235. {$else}
  236. MSG_NOSIGNAL = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
  237. {$endif}
  238. {$IF DEFINED(HAIKU)}
  239. const
  240. ESysESTALE = (B_POSIX_ERROR_BASE + 40);
  241. ESysENOTSOCK = (B_POSIX_ERROR_BASE + 44);
  242. ESysEHOSTDOWN = (B_POSIX_ERROR_BASE + 45);
  243. ESysEDESTADDRREQ = (B_POSIX_ERROR_BASE + 48);
  244. ESysEDQUOT = (B_POSIX_ERROR_BASE + 49);
  245. // Fake error codes
  246. ESysEUSERS = (B_POSIX_ERROR_BASE + 128);
  247. ESysEREMOTE = (B_POSIX_ERROR_BASE + 129);
  248. ESysETOOMANYREFS = (B_POSIX_ERROR_BASE + 130);
  249. ESysESOCKTNOSUPPORT = (B_POSIX_ERROR_BASE + 131);
  250. {$ENDIF}
  251. const
  252. WSAEINTR = ESysEINTR;
  253. WSAEBADF = ESysEBADF;
  254. WSAEACCES = ESysEACCES;
  255. WSAEFAULT = ESysEFAULT;
  256. WSAEINVAL = ESysEINVAL;
  257. WSAEMFILE = ESysEMFILE;
  258. WSAEWOULDBLOCK = ESysEWOULDBLOCK;
  259. WSAEINPROGRESS = ESysEINPROGRESS;
  260. WSAEALREADY = ESysEALREADY;
  261. WSAENOTSOCK = ESysENOTSOCK;
  262. WSAEDESTADDRREQ = ESysEDESTADDRREQ;
  263. WSAEMSGSIZE = ESysEMSGSIZE;
  264. WSAEPROTOTYPE = ESysEPROTOTYPE;
  265. WSAENOPROTOOPT = ESysENOPROTOOPT;
  266. WSAEPROTONOSUPPORT = ESysEPROTONOSUPPORT;
  267. WSAESOCKTNOSUPPORT = ESysESOCKTNOSUPPORT;
  268. WSAEOPNOTSUPP = ESysEOPNOTSUPP;
  269. WSAEPFNOSUPPORT = ESysEPFNOSUPPORT;
  270. WSAEAFNOSUPPORT = ESysEAFNOSUPPORT;
  271. WSAEADDRINUSE = ESysEADDRINUSE;
  272. WSAEADDRNOTAVAIL = ESysEADDRNOTAVAIL;
  273. WSAENETDOWN = ESysENETDOWN;
  274. WSAENETUNREACH = ESysENETUNREACH;
  275. WSAENETRESET = ESysENETRESET;
  276. WSAECONNABORTED = ESysECONNABORTED;
  277. WSAECONNRESET = ESysECONNRESET;
  278. WSAENOBUFS = ESysENOBUFS;
  279. WSAEISCONN = ESysEISCONN;
  280. WSAENOTCONN = ESysENOTCONN;
  281. WSAESHUTDOWN = ESysESHUTDOWN;
  282. WSAETOOMANYREFS = ESysETOOMANYREFS;
  283. WSAETIMEDOUT = ESysETIMEDOUT;
  284. WSAECONNREFUSED = ESysECONNREFUSED;
  285. WSAELOOP = ESysELOOP;
  286. WSAENAMETOOLONG = ESysENAMETOOLONG;
  287. WSAEHOSTDOWN = ESysEHOSTDOWN;
  288. WSAEHOSTUNREACH = ESysEHOSTUNREACH;
  289. WSAENOTEMPTY = ESysENOTEMPTY;
  290. WSAEPROCLIM = -1;
  291. WSAEUSERS = ESysEUSERS;
  292. WSAEDQUOT = ESysEDQUOT;
  293. WSAESTALE = ESysESTALE;
  294. WSAEREMOTE = ESysEREMOTE;
  295. WSASYSNOTREADY = -2;
  296. WSAVERNOTSUPPORTED = -3;
  297. WSANOTINITIALISED = -4;
  298. WSAEDISCON = -5;
  299. WSAHOST_NOT_FOUND = 1;
  300. WSATRY_AGAIN = 2;
  301. WSANO_RECOVERY = 3;
  302. WSANO_DATA = -6;
  303. const
  304. WSADESCRIPTION_LEN = 256;
  305. WSASYS_STATUS_LEN = 128;
  306. type
  307. PWSAData = ^TWSAData;
  308. TWSAData = packed record
  309. wVersion: Word;
  310. wHighVersion: Word;
  311. szDescription: array[0..WSADESCRIPTION_LEN] of Char;
  312. szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
  313. iMaxSockets: Word;
  314. iMaxUdpDg: Word;
  315. lpVendorInfo: PChar;
  316. end;
  317. function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
  318. function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
  319. function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
  320. function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
  321. function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
  322. function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
  323. procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
  324. procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
  325. var
  326. in6addr_any, in6addr_loopback : TInAddr6;
  327. procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
  328. function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
  329. procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
  330. procedure FD_ZERO(var FDSet: TFDSet);
  331. {=============================================================================}
  332. var
  333. SynSockCS: SyncObjs.TCriticalSection;
  334. SockEnhancedApi: Boolean;
  335. SockWship6Api: Boolean;
  336. type
  337. TVarSin = packed record
  338. {$ifdef SOCK_HAS_SINLEN}
  339. sin_len : cuchar;
  340. {$endif}
  341. case integer of
  342. 0: (AddressFamily: sa_family_t);
  343. 1: (
  344. case sin_family: sa_family_t of
  345. AF_INET: (sin_port: word;
  346. sin_addr: TInAddr;
  347. sin_zero: array[0..7] of Char);
  348. AF_INET6: (sin6_port: word;
  349. sin6_flowinfo: longword;
  350. sin6_addr: TInAddr6;
  351. sin6_scope_id: longword);
  352. );
  353. end;
  354. function SizeOfVarSin(sin: TVarSin): integer;
  355. function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
  356. function WSACleanup: Integer;
  357. function WSAGetLastError: Integer;
  358. function GetHostName: string;
  359. function Shutdown(s: TSocket; how: Integer): Integer;
  360. function SetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
  361. optlen: Integer): Integer;
  362. function GetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
  363. var optlen: Integer): Integer;
  364. function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  365. function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  366. function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
  367. function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
  368. function ntohs(netshort: word): word;
  369. function ntohl(netlong: longword): longword;
  370. function Listen(s: TSocket; backlog: Integer): Integer;
  371. function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
  372. function htons(hostshort: word): word;
  373. function htonl(hostlong: longword): longword;
  374. function GetSockName(s: TSocket; var name: TVarSin): Integer;
  375. function GetPeerName(s: TSocket; var name: TVarSin): Integer;
  376. function Connect(s: TSocket; const name: TVarSin): Integer;
  377. function CloseSocket(s: TSocket): Integer;
  378. function Bind(s: TSocket; const addr: TVarSin): Integer;
  379. function Accept(s: TSocket; var addr: TVarSin): TSocket;
  380. function Socket(af, Struc, Protocol: Integer): TSocket;
  381. function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
  382. timeout: PTimeVal): Longint;
  383. function IsNewApi(Family: integer): Boolean;
  384. function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
  385. function GetSinIP(Sin: TVarSin): string;
  386. function GetSinPort(Sin: TVarSin): Integer;
  387. procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
  388. function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
  389. function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
  390. {==============================================================================}
  391. implementation
  392. uses
  393. InitC;
  394. {$if defined(LINUX) or defined(OPENBSD)}
  395. {$define FIRST_ADDR_THEN_CANONNAME}
  396. {$elseif defined(FREEBSD) or defined(NETBSD) or defined(DRAGONFLY) or defined(SOLARIS) or defined(ANDROID) or defined(DARWIN) or defined(HAIKU)}
  397. {$define FIRST_CANONNAME_THEN_ADDR}
  398. {$else}
  399. {$error fatal 'Please consult the netdb.h file for your system to determine the order of ai_addr and ai_canonname'}
  400. {$endif}
  401. {$push}{$packrecords c}
  402. type
  403. PAddrInfo = ^addrinfo;
  404. addrinfo = record
  405. ai_flags: cint; {* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST *}
  406. ai_family: cint; {* PF_xxx *}
  407. ai_socktype: cint; {* SOCK_xxx *}
  408. ai_protocol: cint; {* 0 or IPPROTO_xxx for IPv4 and IPv6 *}
  409. ai_addrlen: TSockLen; {* length of ai_addr *}
  410. {$ifdef FIRST_CANONNAME_THEN_ADDR}
  411. ai_canonname: PAnsiChar; {* canonical name for hostname *}
  412. ai_addr: psockaddr; {* binary address *}
  413. {$endif}
  414. {$ifdef FIRST_ADDR_THEN_CANONNAME}
  415. ai_addr: psockaddr; {* binary address *}
  416. ai_canonname: PAnsiChar; {* canonical name for hostname *}
  417. {$endif}
  418. ai_next: PAddrInfo; {* next structure in linked list *}
  419. end;
  420. TAddrInfo = addrinfo;
  421. PPAddrInfo = ^PAddrInfo;
  422. {$pop}
  423. function getaddrinfo(name, service: PAnsiChar; hints: PAddrInfo; res: PPAddrInfo): cint; cdecl; external clib;
  424. procedure freeaddrinfo(ai: PAddrInfo); cdecl; external clib;
  425. function ResolveName(const HostName: String; Addresses: Pointer; MaxAddresses, Family: Integer): Integer; overload;
  426. var
  427. hints: TAddrInfo;
  428. res, ai: PAddrInfo;
  429. begin
  430. Result:= -1;
  431. if MaxAddresses = 0 then Exit;
  432. res:= nil;
  433. hints:= Default(TAddrInfo);
  434. hints.ai_family:= Family;
  435. hints.ai_socktype:= SOCK_STREAM;
  436. if (getaddrinfo(PAnsiChar(HostName), nil, @hints, @res) <> 0) or (res = nil) then
  437. Exit;
  438. ai:= res;
  439. Result:= 0;
  440. repeat
  441. if ai^.ai_family = Family then
  442. begin
  443. if Family = AF_INET then
  444. begin
  445. Move(PInetSockAddr(ai^.ai_addr)^.sin_addr, Addresses^, SizeOf(TInAddr));
  446. Inc(PInAddr(Addresses));
  447. end
  448. else begin
  449. Move(PInetSockAddr6(ai^.ai_addr)^.sin6_addr, Addresses^, SizeOf(TIn6Addr));
  450. Inc(PIn6Addr(Addresses));
  451. end;
  452. Inc(Result);
  453. end;
  454. ai:= ai^.ai_next;
  455. until (ai = nil) or (Result >= MaxAddresses);
  456. freeaddrinfo(res);
  457. end;
  458. function ResolveName(HostName: String; var Addresses: array of THostAddr): Integer; overload;
  459. begin
  460. Result:= ResolveName(HostName, @Addresses, Length(Addresses), AF_INET);
  461. end;
  462. function ResolveName6(HostName: String; var Addresses: array of THostAddr6): Integer;
  463. begin
  464. Result:= ResolveName(HostName, @Addresses, Length(Addresses), AF_INET6);
  465. end;
  466. function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
  467. begin
  468. Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
  469. (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
  470. end;
  471. function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
  472. begin
  473. Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
  474. (a^.u6_addr32[2] = 0) and
  475. (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
  476. (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
  477. end;
  478. function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
  479. begin
  480. Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
  481. end;
  482. function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
  483. begin
  484. Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
  485. end;
  486. function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
  487. begin
  488. Result := (a^.u6_addr8[0] = $FF);
  489. end;
  490. function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
  491. begin
  492. Result := (CompareMem( a, b, sizeof(TInAddr6)));
  493. end;
  494. procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
  495. begin
  496. FillChar(a^, sizeof(TInAddr6), 0);
  497. end;
  498. procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
  499. begin
  500. FillChar(a^, sizeof(TInAddr6), 0);
  501. a^.u6_addr8[15] := 1;
  502. end;
  503. {=============================================================================}
  504. function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
  505. begin
  506. with WSData do
  507. begin
  508. wVersion := wVersionRequired;
  509. wHighVersion := $202;
  510. szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
  511. szSystemStatus := 'Running on Unix/Linux by FreePascal';
  512. iMaxSockets := 32768;
  513. iMaxUdpDg := 8192;
  514. end;
  515. Result := 0;
  516. end;
  517. function WSACleanup: Integer;
  518. begin
  519. Result := 0;
  520. end;
  521. function WSAGetLastError: Integer;
  522. begin
  523. Result := fpGetErrno;
  524. end;
  525. function FD_ISSET(Socket: TSocket; var fdset: TFDSet): Boolean;
  526. begin
  527. Result := fpFD_ISSET(socket, fdset) <> 0;
  528. end;
  529. procedure FD_SET(Socket: TSocket; var fdset: TFDSet);
  530. begin
  531. fpFD_SET(Socket, fdset);
  532. end;
  533. procedure FD_CLR(Socket: TSocket; var fdset: TFDSet);
  534. begin
  535. fpFD_CLR(Socket, fdset);
  536. end;
  537. procedure FD_ZERO(var fdset: TFDSet);
  538. begin
  539. fpFD_ZERO(fdset);
  540. end;
  541. {=============================================================================}
  542. function SizeOfVarSin(sin: TVarSin): integer;
  543. begin
  544. case sin.sin_family of
  545. AF_INET:
  546. Result := SizeOf(TSockAddrIn);
  547. AF_INET6:
  548. Result := SizeOf(TSockAddrIn6);
  549. else
  550. Result := 0;
  551. end;
  552. end;
  553. {=============================================================================}
  554. function Bind(s: TSocket; const addr: TVarSin): Integer;
  555. begin
  556. if fpBind(s, @addr, SizeOfVarSin(addr)) = 0 then
  557. Result := 0
  558. else
  559. Result := SOCKET_ERROR;
  560. end;
  561. function Connect(s: TSocket; const name: TVarSin): Integer;
  562. begin
  563. if fpConnect(s, @name, SizeOfVarSin(name)) = 0 then
  564. Result := 0
  565. else
  566. Result := SOCKET_ERROR;
  567. end;
  568. function GetSockName(s: TSocket; var name: TVarSin): Integer;
  569. var
  570. len: integer;
  571. begin
  572. len := SizeOf(name);
  573. FillChar(name, len, 0);
  574. Result := fpGetSockName(s, @name, @Len);
  575. end;
  576. function GetPeerName(s: TSocket; var name: TVarSin): Integer;
  577. var
  578. len: integer;
  579. begin
  580. len := SizeOf(name);
  581. FillChar(name, len, 0);
  582. Result := fpGetPeerName(s, @name, @Len);
  583. end;
  584. function GetHostName: string;
  585. begin
  586. Result := unix.GetHostName;
  587. end;
  588. function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  589. begin
  590. Result := fpSend(s, pointer(Buf), len, flags);
  591. end;
  592. function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  593. begin
  594. Result := fpRecv(s, pointer(Buf), len, flags);
  595. end;
  596. function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
  597. begin
  598. Result := fpSendTo(s, pointer(Buf), len, flags, @addrto, SizeOfVarSin(addrto));
  599. end;
  600. function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
  601. var
  602. x: integer;
  603. begin
  604. x := SizeOf(from);
  605. Result := fpRecvFrom(s, pointer(Buf), len, flags, @from, @x);
  606. end;
  607. function Accept(s: TSocket; var addr: TVarSin): TSocket;
  608. var
  609. x: integer;
  610. begin
  611. x := SizeOf(addr);
  612. Result := fpAccept(s, @addr, @x);
  613. end;
  614. function Shutdown(s: TSocket; how: Integer): Integer;
  615. begin
  616. Result := fpShutdown(s, how);
  617. end;
  618. function SetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
  619. optlen: Integer): Integer;
  620. begin
  621. Result := fpsetsockopt(s, level, optname, pointer(optval), optlen);
  622. end;
  623. function GetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
  624. var optlen: Integer): Integer;
  625. begin
  626. Result := fpgetsockopt(s, level, optname, pointer(optval), @optlen);
  627. end;
  628. function ntohs(netshort: word): word;
  629. begin
  630. Result := sockets.ntohs(NetShort);
  631. end;
  632. function ntohl(netlong: longword): longword;
  633. begin
  634. Result := sockets.ntohl(NetLong);
  635. end;
  636. function Listen(s: TSocket; backlog: Integer): Integer;
  637. begin
  638. if fpListen(s, backlog) = 0 then
  639. Result := 0
  640. else
  641. Result := SOCKET_ERROR;
  642. end;
  643. function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
  644. begin
  645. Result := fpIoctl(s, cmd, @arg);
  646. end;
  647. function htons(hostshort: word): word;
  648. begin
  649. Result := sockets.htons(Hostshort);
  650. end;
  651. function htonl(hostlong: longword): longword;
  652. begin
  653. Result := sockets.htonl(HostLong);
  654. end;
  655. function CloseSocket(s: TSocket): Integer;
  656. begin
  657. Result := sockets.CloseSocket(s);
  658. end;
  659. function Socket(af, Struc, Protocol: Integer): TSocket;
  660. {$IFDEF DARWIN}
  661. var
  662. on_off: integer;
  663. {$ENDIF}
  664. begin
  665. Result := fpSocket(af, struc, protocol);
  666. // ##### Patch for Mac OS to avoid "Project XXX raised exception class 'External: SIGPIPE'" error.
  667. {$IFDEF DARWIN}
  668. if Result <> INVALID_SOCKET then
  669. begin
  670. on_off := 1;
  671. synsock.SetSockOpt(Result, integer(SOL_SOCKET), integer(SO_NOSIGPIPE), @on_off, SizeOf(integer));
  672. end;
  673. {$ENDIF}
  674. end;
  675. function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
  676. timeout: PTimeVal): Longint;
  677. begin
  678. Result := fpSelect(nfds, readfds, writefds, exceptfds, timeout);
  679. end;
  680. {=============================================================================}
  681. function IsNewApi(Family: integer): Boolean;
  682. begin
  683. Result := SockEnhancedApi;
  684. if not Result then
  685. Result := (Family = AF_INET6) and SockWship6Api;
  686. end;
  687. function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
  688. var
  689. TwoPass: boolean;
  690. f1, f2: integer;
  691. function GetAddr(f:integer): integer;
  692. var
  693. a4: array [1..1] of in_addr;
  694. a6: array [1..1] of Tin6_addr;
  695. he: THostEntry;
  696. begin
  697. Result := WSAEPROTONOSUPPORT;
  698. case f of
  699. AF_INET:
  700. begin
  701. if IP = cAnyHost then
  702. begin
  703. Sin.sin_family := AF_INET;
  704. Result := 0;
  705. end
  706. else
  707. begin
  708. if lowercase(IP) = cLocalHostStr then
  709. a4[1].s_addr := htonl(INADDR_LOOPBACK)
  710. else
  711. begin
  712. a4[1].s_addr := 0;
  713. Result := WSAHOST_NOT_FOUND;
  714. a4[1] := StrTonetAddr(IP);
  715. if a4[1].s_addr = INADDR_ANY then
  716. if GetHostByName(ip, he) then
  717. a4[1]:=HostToNet(he.Addr)
  718. else
  719. Resolvename(ip, a4);
  720. end;
  721. if a4[1].s_addr <> INADDR_ANY then
  722. begin
  723. Sin.sin_family := AF_INET;
  724. sin.sin_addr := a4[1];
  725. Result := 0;
  726. end;
  727. end;
  728. end;
  729. AF_INET6:
  730. begin
  731. if IP = c6AnyHost then
  732. begin
  733. Sin.sin_family := AF_INET6;
  734. Result := 0;
  735. end
  736. else
  737. begin
  738. if lowercase(IP) = cLocalHostStr then
  739. SET_LOOPBACK_ADDR6(@a6[1])
  740. else
  741. begin
  742. Result := WSAHOST_NOT_FOUND;
  743. SET_IN6_IF_ADDR_ANY(@a6[1]);
  744. a6[1] := StrTonetAddr6(IP);
  745. if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  746. Resolvename6(ip, a6);
  747. end;
  748. if not IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  749. begin
  750. Sin.sin_family := AF_INET6;
  751. sin.sin6_addr := a6[1];
  752. Result := 0;
  753. end;
  754. end;
  755. end;
  756. end;
  757. end;
  758. begin
  759. Result := 0;
  760. FillChar(Sin, Sizeof(Sin), 0);
  761. Sin.sin_port := htons(Resolveport(port, family, SockProtocol, SockType));
  762. TwoPass := False;
  763. if Family = AF_UNSPEC then
  764. begin
  765. if PreferIP4 then
  766. begin
  767. f1 := AF_INET;
  768. f2 := AF_INET6;
  769. TwoPass := True;
  770. end
  771. else
  772. begin
  773. f2 := AF_INET;
  774. f1 := AF_INET6;
  775. TwoPass := True;
  776. end;
  777. end
  778. else
  779. f1 := Family;
  780. Result := GetAddr(f1);
  781. if Result <> 0 then
  782. if TwoPass then
  783. Result := GetAddr(f2);
  784. end;
  785. function GetSinIP(Sin: TVarSin): string;
  786. begin
  787. Result := '';
  788. case sin.AddressFamily of
  789. AF_INET:
  790. begin
  791. result := NetAddrToStr(sin.sin_addr);
  792. end;
  793. AF_INET6:
  794. begin
  795. result := NetAddrToStr6(sin.sin6_addr);
  796. end;
  797. end;
  798. end;
  799. function GetSinPort(Sin: TVarSin): Integer;
  800. begin
  801. if (Sin.sin_family = AF_INET6) then
  802. Result := synsock.ntohs(Sin.sin6_port)
  803. else
  804. Result := synsock.ntohs(Sin.sin_port);
  805. end;
  806. procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
  807. var
  808. x, n: integer;
  809. a4: array [1..255] of in_addr;
  810. a6: array [1..255] of Tin6_addr;
  811. he: THostEntry;
  812. begin
  813. IPList.Clear;
  814. if (family = AF_INET) or (family = AF_UNSPEC) then
  815. begin
  816. if lowercase(name) = cLocalHostStr then
  817. IpList.Add(cLocalHost)
  818. else
  819. begin
  820. a4[1] := StrTonetAddr(name);
  821. if a4[1].s_addr = INADDR_ANY then
  822. if GetHostByName(name, he) then
  823. begin
  824. a4[1]:=HostToNet(he.Addr);
  825. x := 1;
  826. end
  827. else
  828. x := Resolvename(name, a4)
  829. else
  830. x := 1;
  831. for n := 1 to x do
  832. IpList.Add(netaddrToStr(a4[n]));
  833. end;
  834. end;
  835. if (family = AF_INET6) or (family = AF_UNSPEC) then
  836. begin
  837. if lowercase(name) = cLocalHostStr then
  838. IpList.Add(c6LocalHost)
  839. else
  840. begin
  841. a6[1] := StrTonetAddr6(name);
  842. if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  843. x := Resolvename6(name, a6)
  844. else
  845. x := 1;
  846. for n := 1 to x do
  847. IpList.Add(netaddrToStr6(a6[n]));
  848. end;
  849. end;
  850. if IPList.Count = 0 then
  851. IPList.Add(cLocalHost);
  852. end;
  853. function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
  854. var
  855. ProtoEnt: TProtocolEntry;
  856. ServEnt: TServiceEntry;
  857. begin
  858. Result := StrToIntDef(Port, 0);
  859. if Result = 0 then
  860. begin
  861. ProtoEnt.Name := '';
  862. GetProtocolByNumber(SockProtocol, ProtoEnt);
  863. ServEnt.port := 0;
  864. GetServiceByName(Port, ProtoEnt.Name, ServEnt);
  865. Result := ntohs(ServEnt.port);
  866. end;
  867. end;
  868. function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
  869. var
  870. n: integer;
  871. a4: array [1..1] of in_addr;
  872. a6: array [1..1] of Tin6_addr;
  873. a: array [1..1] of string;
  874. begin
  875. Result := IP;
  876. a4[1] := StrToNetAddr(IP);
  877. if a4[1].s_addr <> INADDR_ANY then
  878. begin
  879. //why ResolveAddress need address in HOST order? :-O
  880. n := ResolveAddress(nettohost(a4[1]), a);
  881. if n > 0 then
  882. Result := a[1];
  883. end
  884. else
  885. begin
  886. a6[1] := StrToNetAddr6(IP);
  887. n := ResolveAddress6(a6[1], a);
  888. if n > 0 then
  889. Result := a[1];
  890. end;
  891. end;
  892. {=============================================================================}
  893. function InitSocketInterface(stack: string): Boolean;
  894. begin
  895. SockEnhancedApi := False;
  896. SockWship6Api := False;
  897. // Libc.Signal(Libc.SIGPIPE, TSignalHandler(Libc.SIG_IGN));
  898. Result := True;
  899. end;
  900. function DestroySocketInterface: Boolean;
  901. begin
  902. Result := True;
  903. end;
  904. initialization
  905. begin
  906. SynSockCS := SyncObjs.TCriticalSection.Create;
  907. SET_IN6_IF_ADDR_ANY (@in6addr_any);
  908. SET_LOOPBACK_ADDR6 (@in6addr_loopback);
  909. end;
  910. finalization
  911. begin
  912. SynSockCS.Free;
  913. end;
  914. {$ENDIF}