ssfpc.inc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.001.008 |
  3. |==============================================================================|
  4. | Content: Socket Independent Platform Layer - FreePascal definition include |
  5. |==============================================================================|
  6. | Copyright (c)2006-2021, 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-2021. |
  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. interface
  65. uses
  66. SyncObjs, SysUtils, Classes,
  67. synafpc, BaseUnix, Unix, termio, sockets, netdb;
  68. function InitSocketInterface(stack: string): Boolean;
  69. function DestroySocketInterface: Boolean;
  70. const
  71. DLLStackName = '';
  72. WinsockLevel = $0202;
  73. cLocalHost = '127.0.0.1';
  74. cAnyHost = '0.0.0.0';
  75. c6AnyHost = '::0';
  76. c6Localhost = '::1';
  77. cLocalHostStr = 'localhost';
  78. type
  79. TSocket = longint;
  80. TAddrFamily = integer;
  81. TMemory = pointer;
  82. type
  83. TFDSet = Baseunix.TFDSet;
  84. PFDSet = ^TFDSet;
  85. Ptimeval = Baseunix.ptimeval;
  86. Ttimeval = Baseunix.ttimeval;
  87. const
  88. FIONREAD = termio.FIONREAD;
  89. FIONBIO = termio.FIONBIO;
  90. FIOASYNC = termio.FIOASYNC;
  91. const
  92. IPPROTO_IP = 0; { Dummy }
  93. IPPROTO_ICMP = 1; { Internet Control Message Protocol }
  94. IPPROTO_IGMP = 2; { Internet Group Management Protocol}
  95. IPPROTO_TCP = 6; { TCP }
  96. IPPROTO_UDP = 17; { User Datagram Protocol }
  97. IPPROTO_IPV6 = 41;
  98. IPPROTO_ICMPV6 = 58;
  99. IPPROTO_RM = 113;
  100. IPPROTO_RAW = 255;
  101. IPPROTO_MAX = 256;
  102. type
  103. PInAddr = ^TInAddr;
  104. TInAddr = sockets.in_addr;
  105. PSockAddrIn = ^TSockAddrIn;
  106. TSockAddrIn = sockets.TInetSockAddr;
  107. TIP_mreq = record
  108. imr_multiaddr: TInAddr; // IP multicast address of group
  109. imr_interface: TInAddr; // local IP address of interface
  110. end;
  111. PInAddr6 = ^TInAddr6;
  112. TInAddr6 = sockets.Tin6_addr;
  113. PSockAddrIn6 = ^TSockAddrIn6;
  114. TSockAddrIn6 = sockets.TInetSockAddr6;
  115. TIPv6_mreq = record
  116. ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
  117. ipv6mr_interface: integer; // Interface index.
  118. end;
  119. const
  120. INADDR_ANY = $00000000;
  121. INADDR_LOOPBACK = $7F000001;
  122. INADDR_BROADCAST = $FFFFFFFF;
  123. INADDR_NONE = $FFFFFFFF;
  124. ADDR_ANY = INADDR_ANY;
  125. INVALID_SOCKET = TSocket(NOT(0));
  126. SOCKET_ERROR = -1;
  127. Const
  128. IP_TOS = sockets.IP_TOS; { int; IP type of service and precedence. }
  129. IP_TTL = sockets.IP_TTL; { int; IP time to live. }
  130. IP_HDRINCL = sockets.IP_HDRINCL; { int; Header is included with data. }
  131. IP_OPTIONS = sockets.IP_OPTIONS; { ip_opts; IP per-packet options. }
  132. // IP_ROUTER_ALERT = sockets.IP_ROUTER_ALERT; { bool }
  133. IP_RECVOPTS = sockets.IP_RECVOPTS; { bool }
  134. IP_RETOPTS = sockets.IP_RETOPTS; { bool }
  135. // IP_PKTINFO = sockets.IP_PKTINFO; { bool }
  136. // IP_PKTOPTIONS = sockets.IP_PKTOPTIONS;
  137. // IP_PMTUDISC = sockets.IP_PMTUDISC; { obsolete name? }
  138. // IP_MTU_DISCOVER = sockets.IP_MTU_DISCOVER; { int; see below }
  139. // IP_RECVERR = sockets.IP_RECVERR; { bool }
  140. // IP_RECVTTL = sockets.IP_RECVTTL; { bool }
  141. // IP_RECVTOS = sockets.IP_RECVTOS; { bool }
  142. IP_MULTICAST_IF = sockets.IP_MULTICAST_IF; { in_addr; set/get IP multicast i/f }
  143. IP_MULTICAST_TTL = sockets.IP_MULTICAST_TTL; { u_char; set/get IP multicast ttl }
  144. IP_MULTICAST_LOOP = sockets.IP_MULTICAST_LOOP; { i_char; set/get IP multicast loopback }
  145. IP_ADD_MEMBERSHIP = sockets.IP_ADD_MEMBERSHIP; { ip_mreq; add an IP group membership }
  146. IP_DROP_MEMBERSHIP = sockets.IP_DROP_MEMBERSHIP; { ip_mreq; drop an IP group membership }
  147. SOL_SOCKET = sockets.SOL_SOCKET;
  148. SO_DEBUG = sockets.SO_DEBUG;
  149. SO_REUSEADDR = sockets.SO_REUSEADDR;
  150. SO_TYPE = sockets.SO_TYPE;
  151. SO_ERROR = sockets.SO_ERROR;
  152. SO_DONTROUTE = sockets.SO_DONTROUTE;
  153. SO_BROADCAST = sockets.SO_BROADCAST;
  154. SO_SNDBUF = sockets.SO_SNDBUF;
  155. SO_RCVBUF = sockets.SO_RCVBUF;
  156. SO_KEEPALIVE = sockets.SO_KEEPALIVE;
  157. SO_OOBINLINE = sockets.SO_OOBINLINE;
  158. // SO_NO_CHECK = sockets.SO_NO_CHECK;
  159. // SO_PRIORITY = sockets.SO_PRIORITY;
  160. SO_LINGER = sockets.SO_LINGER;
  161. // SO_BSDCOMPAT = sockets.SO_BSDCOMPAT;
  162. // SO_REUSEPORT = sockets.SO_REUSEPORT;
  163. // SO_PASSCRED = sockets.SO_PASSCRED;
  164. // SO_PEERCRED = sockets.SO_PEERCRED;
  165. SO_RCVLOWAT = sockets.SO_RCVLOWAT;
  166. SO_SNDLOWAT = sockets.SO_SNDLOWAT;
  167. SO_RCVTIMEO = sockets.SO_RCVTIMEO;
  168. SO_SNDTIMEO = sockets.SO_SNDTIMEO;
  169. { Security levels - as per NRL IPv6 - don't actually do anything }
  170. // SO_SECURITY_AUTHENTICATION = sockets.SO_SECURITY_AUTHENTICATION;
  171. // SO_SECURITY_ENCRYPTION_TRANSPORT = sockets.SO_SECURITY_ENCRYPTION_TRANSPORT;
  172. // SO_SECURITY_ENCRYPTION_NETWORK = sockets.SO_SECURITY_ENCRYPTION_NETWORK;
  173. // SO_BINDTODEVICE = sockets.SO_BINDTODEVICE;
  174. { Socket filtering }
  175. // SO_ATTACH_FILTER = sockets.SO_ATTACH_FILTER;
  176. // SO_DETACH_FILTER = sockets.SO_DETACH_FILTER;
  177. {$IFDEF DARWIN}
  178. SO_NOSIGPIPE = $1022;
  179. {$ENDIF}
  180. SOMAXCONN = 1024;
  181. IPV6_UNICAST_HOPS = sockets.IPV6_UNICAST_HOPS;
  182. IPV6_MULTICAST_IF = sockets.IPV6_MULTICAST_IF;
  183. IPV6_MULTICAST_HOPS = sockets.IPV6_MULTICAST_HOPS;
  184. IPV6_MULTICAST_LOOP = sockets.IPV6_MULTICAST_LOOP;
  185. IPV6_JOIN_GROUP = sockets.IPV6_JOIN_GROUP;
  186. IPV6_LEAVE_GROUP = sockets.IPV6_LEAVE_GROUP;
  187. const
  188. SOCK_STREAM = 1; { stream socket }
  189. SOCK_DGRAM = 2; { datagram socket }
  190. SOCK_RAW = 3; { raw-protocol interface }
  191. SOCK_RDM = 4; { reliably-delivered message }
  192. SOCK_SEQPACKET = 5; { sequenced packet stream }
  193. { TCP options. }
  194. TCP_NODELAY = $0001;
  195. { Address families. }
  196. AF_UNSPEC = 0; { unspecified }
  197. AF_INET = 2; { internetwork: UDP, TCP, etc. }
  198. AF_INET6 = 10; { Internetwork Version 6 }
  199. AF_MAX = 24;
  200. { Protocol families, same as address families for now. }
  201. PF_UNSPEC = AF_UNSPEC;
  202. PF_INET = AF_INET;
  203. PF_INET6 = AF_INET6;
  204. PF_MAX = AF_MAX;
  205. type
  206. { Structure used for manipulating linger option. }
  207. PLinger = ^TLinger;
  208. TLinger = packed record
  209. l_onoff: integer;
  210. l_linger: integer;
  211. end;
  212. const
  213. MSG_OOB = sockets.MSG_OOB; // Process out-of-band data.
  214. MSG_PEEK = sockets.MSG_PEEK; // Peek at incoming messages.
  215. {$ifdef DARWIN}
  216. MSG_NOSIGNAL = 0; // Signal is disabled by SO_NOSIGPIPE socket option instead
  217. //was $20000 as undocumented option for Mac OS X
  218. {$else}
  219. MSG_NOSIGNAL = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
  220. {$endif}
  221. const
  222. WSAEINTR = ESysEINTR;
  223. WSAEBADF = ESysEBADF;
  224. WSAEACCES = ESysEACCES;
  225. WSAEFAULT = ESysEFAULT;
  226. WSAEINVAL = ESysEINVAL;
  227. WSAEMFILE = ESysEMFILE;
  228. WSAEWOULDBLOCK = ESysEWOULDBLOCK;
  229. WSAEINPROGRESS = ESysEINPROGRESS;
  230. WSAEALREADY = ESysEALREADY;
  231. WSAENOTSOCK = ESysENOTSOCK;
  232. WSAEDESTADDRREQ = ESysEDESTADDRREQ;
  233. WSAEMSGSIZE = ESysEMSGSIZE;
  234. WSAEPROTOTYPE = ESysEPROTOTYPE;
  235. WSAENOPROTOOPT = ESysENOPROTOOPT;
  236. WSAEPROTONOSUPPORT = ESysEPROTONOSUPPORT;
  237. WSAESOCKTNOSUPPORT = ESysESOCKTNOSUPPORT;
  238. WSAEOPNOTSUPP = ESysEOPNOTSUPP;
  239. WSAEPFNOSUPPORT = ESysEPFNOSUPPORT;
  240. WSAEAFNOSUPPORT = ESysEAFNOSUPPORT;
  241. WSAEADDRINUSE = ESysEADDRINUSE;
  242. WSAEADDRNOTAVAIL = ESysEADDRNOTAVAIL;
  243. WSAENETDOWN = ESysENETDOWN;
  244. WSAENETUNREACH = ESysENETUNREACH;
  245. WSAENETRESET = ESysENETRESET;
  246. WSAECONNABORTED = ESysECONNABORTED;
  247. WSAECONNRESET = ESysECONNRESET;
  248. WSAENOBUFS = ESysENOBUFS;
  249. WSAEISCONN = ESysEISCONN;
  250. WSAENOTCONN = ESysENOTCONN;
  251. WSAESHUTDOWN = ESysESHUTDOWN;
  252. WSAETOOMANYREFS = ESysETOOMANYREFS;
  253. WSAETIMEDOUT = ESysETIMEDOUT;
  254. WSAECONNREFUSED = ESysECONNREFUSED;
  255. WSAELOOP = ESysELOOP;
  256. WSAENAMETOOLONG = ESysENAMETOOLONG;
  257. WSAEHOSTDOWN = ESysEHOSTDOWN;
  258. WSAEHOSTUNREACH = ESysEHOSTUNREACH;
  259. WSAENOTEMPTY = ESysENOTEMPTY;
  260. WSAEPROCLIM = -1;
  261. WSAEUSERS = ESysEUSERS;
  262. WSAEDQUOT = ESysEDQUOT;
  263. WSAESTALE = ESysESTALE;
  264. WSAEREMOTE = ESysEREMOTE;
  265. WSASYSNOTREADY = -2;
  266. WSAVERNOTSUPPORTED = -3;
  267. WSANOTINITIALISED = -4;
  268. WSAEDISCON = -5;
  269. WSAHOST_NOT_FOUND = 1;
  270. WSATRY_AGAIN = 2;
  271. WSANO_RECOVERY = 3;
  272. WSANO_DATA = -6;
  273. WSABASEERR = 10000;
  274. const
  275. WSADESCRIPTION_LEN = 256;
  276. WSASYS_STATUS_LEN = 128;
  277. type
  278. PWSAData = ^TWSAData;
  279. TWSAData = packed record
  280. wVersion: Word;
  281. wHighVersion: Word;
  282. szDescription: array[0..WSADESCRIPTION_LEN] of Char;
  283. szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
  284. iMaxSockets: Word;
  285. iMaxUdpDg: Word;
  286. lpVendorInfo: PChar;
  287. end;
  288. function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
  289. function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
  290. function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
  291. function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
  292. function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
  293. function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
  294. procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
  295. procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
  296. var
  297. in6addr_any, in6addr_loopback : TInAddr6;
  298. procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
  299. function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
  300. procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
  301. procedure FD_ZERO(var FDSet: TFDSet);
  302. {=============================================================================}
  303. var
  304. SynSockCS: SyncObjs.TCriticalSection;
  305. SockEnhancedApi: Boolean;
  306. SockWship6Api: Boolean;
  307. type
  308. TVarSin = packed record
  309. {$ifdef SOCK_HAS_SINLEN}
  310. sin_len : cuchar;
  311. {$endif}
  312. case integer of
  313. 0: (AddressFamily: sa_family_t);
  314. 1: (
  315. case sin_family: sa_family_t of
  316. AF_INET: (sin_port: word;
  317. sin_addr: TInAddr;
  318. sin_zero: array[0..7] of byte);
  319. AF_INET6: (sin6_port: word;
  320. sin6_flowinfo: FixedUInt;
  321. sin6_addr: TInAddr6;
  322. sin6_scope_id: FixedUInt);
  323. );
  324. end;
  325. function SizeOfVarSin(sin: TVarSin): integer;
  326. function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
  327. function WSACleanup: Integer;
  328. function WSAGetLastError: Integer;
  329. function GetHostName: string;
  330. function Shutdown(s: TSocket; how: Integer): Integer;
  331. function SetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
  332. optlen: Integer): Integer;
  333. function GetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
  334. var optlen: Integer): Integer;
  335. function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  336. function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  337. function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
  338. function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
  339. function ntohs(netshort: word): word;
  340. function ntohl(netlong: FixedUInt): FixedUInt;
  341. function Listen(s: TSocket; backlog: Integer): Integer;
  342. function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
  343. function htons(hostshort: word): word;
  344. function htonl(hostlong: FixedUInt): FixedUInt;
  345. function GetSockName(s: TSocket; var name: TVarSin): Integer;
  346. function GetPeerName(s: TSocket; var name: TVarSin): Integer;
  347. function Connect(s: TSocket; const name: TVarSin): Integer;
  348. function CloseSocket(s: TSocket): Integer;
  349. function Bind(s: TSocket; const addr: TVarSin): Integer;
  350. function Accept(s: TSocket; var addr: TVarSin): TSocket;
  351. function Socket(af, Struc, Protocol: Integer): TSocket;
  352. function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
  353. timeout: PTimeVal): Longint;
  354. function IsNewApi(Family: integer): Boolean;
  355. function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
  356. function GetSinIP(Sin: TVarSin): string;
  357. function GetSinPort(Sin: TVarSin): Integer;
  358. procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
  359. function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
  360. function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
  361. {==============================================================================}
  362. implementation
  363. function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
  364. begin
  365. Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
  366. (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
  367. end;
  368. function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
  369. begin
  370. Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
  371. (a^.u6_addr32[2] = 0) and
  372. (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
  373. (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
  374. end;
  375. function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
  376. begin
  377. Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
  378. end;
  379. function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
  380. begin
  381. Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
  382. end;
  383. function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
  384. begin
  385. Result := (a^.u6_addr8[0] = $FF);
  386. end;
  387. function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
  388. begin
  389. Result := (CompareMem( a, b, sizeof(TInAddr6)));
  390. end;
  391. procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
  392. begin
  393. FillChar(a^, sizeof(TInAddr6), 0);
  394. end;
  395. procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
  396. begin
  397. FillChar(a^, sizeof(TInAddr6), 0);
  398. a^.u6_addr8[15] := 1;
  399. end;
  400. {=============================================================================}
  401. function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
  402. begin
  403. with WSData do
  404. begin
  405. wVersion := wVersionRequired;
  406. wHighVersion := $202;
  407. szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
  408. szSystemStatus := 'Running on Unix/Linux by FreePascal';
  409. iMaxSockets := 32768;
  410. iMaxUdpDg := 8192;
  411. end;
  412. Result := 0;
  413. end;
  414. function WSACleanup: Integer;
  415. begin
  416. Result := 0;
  417. end;
  418. function WSAGetLastError: Integer;
  419. begin
  420. Result := fpGetErrno;
  421. end;
  422. function FD_ISSET(Socket: TSocket; var fdset: TFDSet): Boolean;
  423. begin
  424. Result := fpFD_ISSET(socket, fdset) <> 0;
  425. end;
  426. procedure FD_SET(Socket: TSocket; var fdset: TFDSet);
  427. begin
  428. fpFD_SET(Socket, fdset);
  429. end;
  430. procedure FD_CLR(Socket: TSocket; var fdset: TFDSet);
  431. begin
  432. fpFD_CLR(Socket, fdset);
  433. end;
  434. procedure FD_ZERO(var fdset: TFDSet);
  435. begin
  436. fpFD_ZERO(fdset);
  437. end;
  438. {=============================================================================}
  439. function SizeOfVarSin(sin: TVarSin): integer;
  440. begin
  441. case sin.sin_family of
  442. AF_INET:
  443. Result := SizeOf(TSockAddrIn);
  444. AF_INET6:
  445. Result := SizeOf(TSockAddrIn6);
  446. else
  447. Result := 0;
  448. end;
  449. end;
  450. {=============================================================================}
  451. function Bind(s: TSocket; const addr: TVarSin): Integer;
  452. begin
  453. if fpBind(s, @addr, SizeOfVarSin(addr)) = 0 then
  454. Result := 0
  455. else
  456. Result := SOCKET_ERROR;
  457. end;
  458. function Connect(s: TSocket; const name: TVarSin): Integer;
  459. begin
  460. if fpConnect(s, @name, SizeOfVarSin(name)) = 0 then
  461. Result := 0
  462. else
  463. Result := SOCKET_ERROR;
  464. end;
  465. function GetSockName(s: TSocket; var name: TVarSin): Integer;
  466. var
  467. len: integer;
  468. begin
  469. len := SizeOf(name);
  470. FillChar(name, len, 0);
  471. Result := fpGetSockName(s, @name, @Len);
  472. end;
  473. function GetPeerName(s: TSocket; var name: TVarSin): Integer;
  474. var
  475. len: integer;
  476. begin
  477. len := SizeOf(name);
  478. FillChar(name, len, 0);
  479. Result := fpGetPeerName(s, @name, @Len);
  480. end;
  481. function GetHostName: string;
  482. begin
  483. Result := unix.GetHostName;
  484. end;
  485. function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  486. begin
  487. Result := fpSend(s, pointer(Buf), len, flags);
  488. end;
  489. function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
  490. begin
  491. Result := fpRecv(s, pointer(Buf), len, flags);
  492. end;
  493. function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
  494. begin
  495. Result := fpSendTo(s, pointer(Buf), len, flags, @addrto, SizeOfVarSin(addrto));
  496. end;
  497. function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
  498. var
  499. x: integer;
  500. begin
  501. x := SizeOf(from);
  502. Result := fpRecvFrom(s, pointer(Buf), len, flags, @from, @x);
  503. end;
  504. function Accept(s: TSocket; var addr: TVarSin): TSocket;
  505. var
  506. x: integer;
  507. begin
  508. x := SizeOf(addr);
  509. Result := fpAccept(s, @addr, @x);
  510. end;
  511. function Shutdown(s: TSocket; how: Integer): Integer;
  512. begin
  513. Result := fpShutdown(s, how);
  514. end;
  515. function SetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
  516. optlen: Integer): Integer;
  517. begin
  518. Result := fpsetsockopt(s, level, optname, pointer(optval), optlen);
  519. end;
  520. function GetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
  521. var optlen: Integer): Integer;
  522. begin
  523. Result := fpgetsockopt(s, level, optname, pointer(optval), @optlen);
  524. end;
  525. function ntohs(netshort: word): word;
  526. begin
  527. Result := sockets.ntohs(NetShort);
  528. end;
  529. function ntohl(netlong: FixedUInt): FixedUInt;
  530. begin
  531. Result := sockets.ntohl(NetLong);
  532. end;
  533. function Listen(s: TSocket; backlog: Integer): Integer;
  534. begin
  535. if fpListen(s, backlog) = 0 then
  536. Result := 0
  537. else
  538. Result := SOCKET_ERROR;
  539. end;
  540. function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
  541. begin
  542. Result := fpIoctl(s, cmd, @arg);
  543. end;
  544. function htons(hostshort: word): word;
  545. begin
  546. Result := sockets.htons(Hostshort);
  547. end;
  548. function htonl(hostlong: FixedUInt): FixedUInt;
  549. begin
  550. Result := sockets.htonl(HostLong);
  551. end;
  552. function CloseSocket(s: TSocket): Integer;
  553. begin
  554. Result := sockets.CloseSocket(s);
  555. end;
  556. function Socket(af, Struc, Protocol: Integer): TSocket;
  557. {$IFDEF DARWIN}
  558. var
  559. on_off: integer;
  560. {$ENDIF}
  561. begin
  562. Result := fpSocket(af, struc, protocol);
  563. // ##### Patch for Mac OS to avoid "Project XXX raised exception class 'External: SIGPIPE'" error.
  564. {$IFDEF DARWIN}
  565. if Result <> INVALID_SOCKET then
  566. begin
  567. on_off := 1;
  568. synsock.SetSockOpt(Result, integer(SOL_SOCKET), integer(SO_NOSIGPIPE), @on_off, SizeOf(integer));
  569. end;
  570. {$ENDIF}
  571. end;
  572. function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
  573. timeout: PTimeVal): Longint;
  574. begin
  575. Result := fpSelect(nfds, readfds, writefds, exceptfds, timeout);
  576. end;
  577. {=============================================================================}
  578. function IsNewApi(Family: integer): Boolean;
  579. begin
  580. Result := SockEnhancedApi;
  581. if not Result then
  582. Result := (Family = AF_INET6) and SockWship6Api;
  583. end;
  584. function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
  585. var
  586. TwoPass: boolean;
  587. f1, f2: integer;
  588. function GetAddr(f:integer): integer;
  589. var
  590. a4: array [1..1] of in_addr;
  591. a6: array [1..1] of Tin6_addr;
  592. he: THostEntry;
  593. begin
  594. Result := WSAEPROTONOSUPPORT;
  595. case f of
  596. AF_INET:
  597. begin
  598. if IP = cAnyHost then
  599. begin
  600. Sin.sin_family := AF_INET;
  601. Result := 0;
  602. end
  603. else
  604. begin
  605. if lowercase(IP) = cLocalHostStr then
  606. a4[1].s_addr := htonl(INADDR_LOOPBACK)
  607. else
  608. begin
  609. a4[1].s_addr := 0;
  610. Result := WSAHOST_NOT_FOUND;
  611. a4[1] := StrTonetAddr(IP);
  612. if a4[1].s_addr = INADDR_ANY then
  613. if GetHostByName(ip, he) then
  614. a4[1]:=HostToNet(he.Addr)
  615. else
  616. Resolvename(ip, a4);
  617. end;
  618. if a4[1].s_addr <> INADDR_ANY then
  619. begin
  620. Sin.sin_family := AF_INET;
  621. sin.sin_addr := a4[1];
  622. Result := 0;
  623. end;
  624. end;
  625. end;
  626. AF_INET6:
  627. begin
  628. if IP = c6AnyHost then
  629. begin
  630. Sin.sin_family := AF_INET6;
  631. Result := 0;
  632. end
  633. else
  634. begin
  635. if lowercase(IP) = cLocalHostStr then
  636. SET_LOOPBACK_ADDR6(@a6[1])
  637. else
  638. begin
  639. Result := WSAHOST_NOT_FOUND;
  640. SET_IN6_IF_ADDR_ANY(@a6[1]);
  641. a6[1] := StrTonetAddr6(IP);
  642. if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  643. Resolvename6(ip, a6);
  644. end;
  645. if not IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  646. begin
  647. Sin.sin_family := AF_INET6;
  648. sin.sin6_addr := a6[1];
  649. Result := 0;
  650. end;
  651. end;
  652. end;
  653. end;
  654. end;
  655. begin
  656. Result := 0;
  657. FillChar(Sin, Sizeof(Sin), 0);
  658. Sin.sin_port := synsock.htons(Resolveport(port, family, SockProtocol, SockType));
  659. TwoPass := False;
  660. if Family = AF_UNSPEC then
  661. begin
  662. if PreferIP4 then
  663. begin
  664. f1 := AF_INET;
  665. f2 := AF_INET6;
  666. TwoPass := True;
  667. end
  668. else
  669. begin
  670. f2 := AF_INET;
  671. f1 := AF_INET6;
  672. TwoPass := True;
  673. end;
  674. end
  675. else
  676. f1 := Family;
  677. Result := GetAddr(f1);
  678. if Result <> 0 then
  679. if TwoPass then
  680. Result := GetAddr(f2);
  681. end;
  682. function GetSinIP(Sin: TVarSin): string;
  683. begin
  684. Result := '';
  685. case sin.AddressFamily of
  686. AF_INET:
  687. begin
  688. result := NetAddrToStr(sin.sin_addr);
  689. end;
  690. AF_INET6:
  691. begin
  692. result := NetAddrToStr6(sin.sin6_addr);
  693. end;
  694. end;
  695. end;
  696. function GetSinPort(Sin: TVarSin): Integer;
  697. begin
  698. if (Sin.sin_family = AF_INET6) then
  699. Result := synsock.ntohs(Sin.sin6_port)
  700. else
  701. Result := synsock.ntohs(Sin.sin_port);
  702. end;
  703. procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
  704. var
  705. x, n: integer;
  706. a4: array [1..255] of in_addr;
  707. a6: array [1..255] of Tin6_addr;
  708. he: THostEntry;
  709. begin
  710. IPList.Clear;
  711. if (family = AF_INET) or (family = AF_UNSPEC) then
  712. begin
  713. if lowercase(name) = cLocalHostStr then
  714. IpList.Add(cLocalHost)
  715. else
  716. begin
  717. a4[1] := StrTonetAddr(name);
  718. if a4[1].s_addr = INADDR_ANY then
  719. if GetHostByName(name, he) then
  720. begin
  721. a4[1]:=HostToNet(he.Addr);
  722. x := 1;
  723. end
  724. else
  725. x := Resolvename(name, a4)
  726. else
  727. x := 1;
  728. for n := 1 to x do
  729. IpList.Add(netaddrToStr(a4[n]));
  730. end;
  731. end;
  732. if (family = AF_INET6) or (family = AF_UNSPEC) then
  733. begin
  734. if lowercase(name) = cLocalHostStr then
  735. IpList.Add(c6LocalHost)
  736. else
  737. begin
  738. a6[1] := StrTonetAddr6(name);
  739. if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
  740. x := Resolvename6(name, a6)
  741. else
  742. x := 1;
  743. for n := 1 to x do
  744. IpList.Add(netaddrToStr6(a6[n]));
  745. end;
  746. end;
  747. if IPList.Count = 0 then
  748. IPList.Add(cAnyHost);
  749. end;
  750. function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
  751. var
  752. ProtoEnt: TProtocolEntry;
  753. ServEnt: TServiceEntry;
  754. begin
  755. Result := StrToIntDef(Port, 0);
  756. if Result = 0 then
  757. begin
  758. ProtoEnt.Name := '';
  759. if GetProtocolByNumber(SockProtocol, ProtoEnt) then
  760. begin
  761. ServEnt.port := 0;
  762. if GetServiceByName(Port, ProtoEnt.Name, ServEnt) then
  763. Result := synsock.ntohs(ServEnt.port);
  764. end;
  765. end;
  766. end;
  767. function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
  768. var
  769. n: integer;
  770. a4: array [1..1] of in_addr;
  771. a6: array [1..1] of Tin6_addr;
  772. a: array [1..1] of string;
  773. begin
  774. Result := IP;
  775. a4[1] := StrToNetAddr(IP);
  776. if a4[1].s_addr <> INADDR_ANY then
  777. begin
  778. //why ResolveAddress need address in HOST order? :-O
  779. n := ResolveAddress(nettohost(a4[1]), a);
  780. if n > 0 then
  781. Result := a[1];
  782. end
  783. else
  784. begin
  785. a6[1] := StrToNetAddr6(IP);
  786. n := ResolveAddress6(a6[1], a);
  787. if n > 0 then
  788. Result := a[1];
  789. end;
  790. end;
  791. {=============================================================================}
  792. function InitSocketInterface(stack: string): Boolean;
  793. begin
  794. SockEnhancedApi := False;
  795. SockWship6Api := False;
  796. // Libc.Signal(Libc.SIGPIPE, TSignalHandler(Libc.SIG_IGN));
  797. Result := True;
  798. end;
  799. function DestroySocketInterface: Boolean;
  800. begin
  801. Result := True;
  802. end;
  803. initialization
  804. begin
  805. SynSockCS := SyncObjs.TCriticalSection.Create;
  806. SET_IN6_IF_ADDR_ANY (@in6addr_any);
  807. SET_LOOPBACK_ADDR6 (@in6addr_loopback);
  808. end;
  809. finalization
  810. begin
  811. SynSockCS.Free;
  812. end;
  813. {$ENDIF}