1 {==============================================================================|
2 | Project : Ararat Synapse                                       | 001.001.002 |
3 |==============================================================================|
4 | Content: Socket Independent Platform Layer - FreePascal definition include   |
5 |==============================================================================|
6 | Copyright (c)2006-2010, 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-2010.                |
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 
45 {:@exclude}
46 
47 {$IFDEF FPC}
48 {For FreePascal 2.x.x}
49 
50 //{$DEFINE FORCEOLDAPI}
51 {Note about define FORCEOLDAPI:
52 If you activate this compiler directive, then is allways used old socket API
53 for name resolution. If you leave this directive inactive, then the new API
54 is used, when running system allows it.
55 
56 For IPv6 support you must have new API!
57 }
58 
59 {$IFDEF FPC}
60   {$MODE DELPHI}
61 {$ENDIF}
62 {$H+}
63 
64 {$ifdef FreeBSD}
65 {$DEFINE SOCK_HAS_SINLEN}               // BSD definition of scoketaddr
66 {$endif}
67 {$ifdef darwin}
68 {$DEFINE SOCK_HAS_SINLEN}               // BSD definition of scoketaddr
69 {$endif}
70 
71 interface
72 
73 uses
74   SyncObjs, SysUtils, Classes,
75   synafpc, BaseUnix, Unix, termio, sockets, netdb;
76 
InitSocketInterfacenull77 function InitSocketInterface(stack: string): Boolean;
DestroySocketInterfacenull78 function DestroySocketInterface: Boolean;
79 
80 const
81   DLLStackName = '';
82   WinsockLevel = $0202;
83 
84   cLocalHost = '127.0.0.1';
85   cAnyHost = '0.0.0.0';
86   c6AnyHost = '::0';
87   c6Localhost = '::1';
88   cLocalHostStr = 'localhost';
89 
90 type
91   TSocket = longint;
92   TAddrFamily = integer;
93 
94   TMemory = pointer;
95 
96 
97 type
98   TFDSet = Baseunix.TFDSet;
99   PFDSet = ^TFDSet;
100   Ptimeval = Baseunix.ptimeval;
101   Ttimeval = Baseunix.ttimeval;
102 
103 const
104   FIONREAD        = termio.FIONREAD;
105   FIONBIO         = termio.FIONBIO;
106   FIOASYNC        = termio.FIOASYNC;
107 
108 const
109   IPPROTO_IP     =   0;		{ Dummy					}
110   IPPROTO_ICMP   =   1;		{ Internet Control Message Protocol }
111   IPPROTO_IGMP   =   2;		{ Internet Group Management Protocol}
112   IPPROTO_TCP    =   6;		{ TCP           			}
113   IPPROTO_UDP    =   17;	{ User Datagram Protocol		}
114   IPPROTO_IPV6   =   41;
115   IPPROTO_ICMPV6 =   58;
116   IPPROTO_RM     =  113;
117 
118   IPPROTO_RAW    =   255;
119   IPPROTO_MAX    =   256;
120 
121 type
122   PInAddr = ^TInAddr;
123   TInAddr = sockets.in_addr;
124 
125   PSockAddrIn = ^TSockAddrIn;
126   TSockAddrIn = sockets.TInetSockAddr;
127 
128 
129   TIP_mreq =  record
130     imr_multiaddr: TInAddr;     // IP multicast address of group
131     imr_interface: TInAddr;     // local IP address of interface
132   end;
133 
134 
135   PInAddr6 = ^TInAddr6;
136   TInAddr6 = sockets.Tin6_addr;
137 
138   PSockAddrIn6 = ^TSockAddrIn6;
139   TSockAddrIn6 = sockets.TInetSockAddr6;
140 
141 
142   TIPv6_mreq = record
143     ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
144     ipv6mr_interface: integer;   // Interface index.
145   end;
146 
147 const
148   INADDR_ANY       = $00000000;
149   INADDR_LOOPBACK  = $7F000001;
150   INADDR_BROADCAST = $FFFFFFFF;
151   INADDR_NONE      = $FFFFFFFF;
152   ADDR_ANY		 = INADDR_ANY;
153   INVALID_SOCKET		= TSocket(NOT(0));
154   SOCKET_ERROR			= -1;
155 
156 Const
157   IP_TOS             = sockets.IP_TOS;             { int; IP type of service and precedence.  }
158   IP_TTL             = sockets.IP_TTL;             { int; IP time to live.  }
159   IP_HDRINCL         = sockets.IP_HDRINCL;         { int; Header is included with data.  }
160   IP_OPTIONS         = sockets.IP_OPTIONS;         { ip_opts; IP per-packet options.  }
161 //  IP_ROUTER_ALERT    = sockets.IP_ROUTER_ALERT;    { bool }
162   IP_RECVOPTS        = sockets.IP_RECVOPTS;        { bool }
163   IP_RETOPTS         = sockets.IP_RETOPTS;         { bool }
164 //  IP_PKTINFO         = sockets.IP_PKTINFO;         { bool }
165 //  IP_PKTOPTIONS      = sockets.IP_PKTOPTIONS;
166 //  IP_PMTUDISC        = sockets.IP_PMTUDISC;        { obsolete name? }
167 //  IP_MTU_DISCOVER    = sockets.IP_MTU_DISCOVER;    { int; see below }
168 //  IP_RECVERR         = sockets.IP_RECVERR;         { bool }
169 //  IP_RECVTTL         = sockets.IP_RECVTTL;         { bool }
170 //  IP_RECVTOS         = sockets.IP_RECVTOS;         { bool }
171   IP_MULTICAST_IF    = sockets.IP_MULTICAST_IF;    { in_addr; set/get IP multicast i/f }
172   IP_MULTICAST_TTL   = sockets.IP_MULTICAST_TTL;   { u_char; set/get IP multicast ttl }
173   IP_MULTICAST_LOOP  = sockets.IP_MULTICAST_LOOP;  { i_char; set/get IP multicast loopback }
174   IP_ADD_MEMBERSHIP  = sockets.IP_ADD_MEMBERSHIP;  { ip_mreq; add an IP group membership }
175   IP_DROP_MEMBERSHIP = sockets.IP_DROP_MEMBERSHIP; { ip_mreq; drop an IP group membership }
176 
177   SOL_SOCKET    = sockets.SOL_SOCKET;
178 
179   SO_DEBUG      = sockets.SO_DEBUG;
180   SO_REUSEADDR  = sockets.SO_REUSEADDR;
181   SO_TYPE       = sockets.SO_TYPE;
182   SO_ERROR      = sockets.SO_ERROR;
183   SO_DONTROUTE  = sockets.SO_DONTROUTE;
184   SO_BROADCAST  = sockets.SO_BROADCAST;
185   SO_SNDBUF     = sockets.SO_SNDBUF;
186   SO_RCVBUF     = sockets.SO_RCVBUF;
187   SO_KEEPALIVE  = sockets.SO_KEEPALIVE;
188   SO_OOBINLINE  = sockets.SO_OOBINLINE;
189 //  SO_NO_CHECK   = sockets.SO_NO_CHECK;
190 //  SO_PRIORITY   = sockets.SO_PRIORITY;
191   SO_LINGER     = sockets.SO_LINGER;
192 //  SO_BSDCOMPAT  = sockets.SO_BSDCOMPAT;
193 //  SO_REUSEPORT  = sockets.SO_REUSEPORT;
194 //  SO_PASSCRED   = sockets.SO_PASSCRED;
195 //  SO_PEERCRED   = sockets.SO_PEERCRED;
196   SO_RCVLOWAT   = sockets.SO_RCVLOWAT;
197   SO_SNDLOWAT   = sockets.SO_SNDLOWAT;
198   SO_RCVTIMEO   = sockets.SO_RCVTIMEO;
199   SO_SNDTIMEO   = sockets.SO_SNDTIMEO;
200 { Security levels - as per NRL IPv6 - don't actually do anything }
201 //  SO_SECURITY_AUTHENTICATION       = sockets.SO_SECURITY_AUTHENTICATION;
202 //  SO_SECURITY_ENCRYPTION_TRANSPORT = sockets.SO_SECURITY_ENCRYPTION_TRANSPORT;
203 //  SO_SECURITY_ENCRYPTION_NETWORK   = sockets.SO_SECURITY_ENCRYPTION_NETWORK;
204 //  SO_BINDTODEVICE                  = sockets.SO_BINDTODEVICE;
205 { Socket filtering }
206 //  SO_ATTACH_FILTER = sockets.SO_ATTACH_FILTER;
207 //  SO_DETACH_FILTER = sockets.SO_DETACH_FILTER;
208 
209   SOMAXCONN       = 1024;
210 
211   IPV6_UNICAST_HOPS     = sockets.IPV6_UNICAST_HOPS;
212   IPV6_MULTICAST_IF     = sockets.IPV6_MULTICAST_IF;
213   IPV6_MULTICAST_HOPS   = sockets.IPV6_MULTICAST_HOPS;
214   IPV6_MULTICAST_LOOP   = sockets.IPV6_MULTICAST_LOOP;
215   IPV6_JOIN_GROUP       = sockets.IPV6_JOIN_GROUP;
216   IPV6_LEAVE_GROUP      = sockets.IPV6_LEAVE_GROUP;
217 
218 const
219   SOCK_STREAM     = 1;               { stream socket }
220   SOCK_DGRAM      = 2;               { datagram socket }
221   SOCK_RAW        = 3;               { raw-protocol interface }
222   SOCK_RDM        = 4;               { reliably-delivered message }
223   SOCK_SEQPACKET  = 5;               { sequenced packet stream }
224 
225 { TCP options. }
226   TCP_NODELAY     = $0001;
227 
228 { Address families. }
229 
230   AF_UNSPEC       = 0;               { unspecified }
231   AF_INET         = 2;               { internetwork: UDP, TCP, etc. }
232   AF_INET6        = 10;              { Internetwork Version 6 }
233   AF_MAX          = 24;
234 
235 { Protocol families, same as address families for now. }
236   PF_UNSPEC       = AF_UNSPEC;
237   PF_INET         = AF_INET;
238   PF_INET6        = AF_INET6;
239   PF_MAX          = AF_MAX;
240 
241 type
242 { Structure used for manipulating linger option. }
243   PLinger = ^TLinger;
244   TLinger = packed record
245     l_onoff: integer;
246     l_linger: integer;
247   end;
248 
249 const
250 
251   MSG_OOB       = sockets.MSG_OOB;      // Process out-of-band data.
252   MSG_PEEK      = sockets.MSG_PEEK;     // Peek at incoming messages.
253   MSG_NOSIGNAL  = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
254 
255 const
256   WSAEINTR = ESysEINTR;
257   WSAEBADF = ESysEBADF;
258   WSAEACCES = ESysEACCES;
259   WSAEFAULT = ESysEFAULT;
260   WSAEINVAL = ESysEINVAL;
261   WSAEMFILE = ESysEMFILE;
262   WSAEWOULDBLOCK = ESysEWOULDBLOCK;
263   WSAEINPROGRESS = ESysEINPROGRESS;
264   WSAEALREADY = ESysEALREADY;
265   WSAENOTSOCK = ESysENOTSOCK;
266   WSAEDESTADDRREQ = ESysEDESTADDRREQ;
267   WSAEMSGSIZE = ESysEMSGSIZE;
268   WSAEPROTOTYPE = ESysEPROTOTYPE;
269   WSAENOPROTOOPT = ESysENOPROTOOPT;
270   WSAEPROTONOSUPPORT = ESysEPROTONOSUPPORT;
271   WSAESOCKTNOSUPPORT = ESysESOCKTNOSUPPORT;
272   WSAEOPNOTSUPP = ESysEOPNOTSUPP;
273   WSAEPFNOSUPPORT = ESysEPFNOSUPPORT;
274   WSAEAFNOSUPPORT = ESysEAFNOSUPPORT;
275   WSAEADDRINUSE = ESysEADDRINUSE;
276   WSAEADDRNOTAVAIL = ESysEADDRNOTAVAIL;
277   WSAENETDOWN = ESysENETDOWN;
278   WSAENETUNREACH = ESysENETUNREACH;
279   WSAENETRESET = ESysENETRESET;
280   WSAECONNABORTED = ESysECONNABORTED;
281   WSAECONNRESET = ESysECONNRESET;
282   WSAENOBUFS = ESysENOBUFS;
283   WSAEISCONN = ESysEISCONN;
284   WSAENOTCONN = ESysENOTCONN;
285   WSAESHUTDOWN = ESysESHUTDOWN;
286   WSAETOOMANYREFS = ESysETOOMANYREFS;
287   WSAETIMEDOUT = ESysETIMEDOUT;
288   WSAECONNREFUSED = ESysECONNREFUSED;
289   WSAELOOP = ESysELOOP;
290   WSAENAMETOOLONG = ESysENAMETOOLONG;
291   WSAEHOSTDOWN = ESysEHOSTDOWN;
292   WSAEHOSTUNREACH = ESysEHOSTUNREACH;
293   WSAENOTEMPTY = ESysENOTEMPTY;
294   WSAEPROCLIM = -1;
295   WSAEUSERS = ESysEUSERS;
296   WSAEDQUOT = ESysEDQUOT;
297   WSAESTALE = ESysESTALE;
298   WSAEREMOTE = ESysEREMOTE;
299   WSASYSNOTREADY = -2;
300   WSAVERNOTSUPPORTED = -3;
301   WSANOTINITIALISED = -4;
302   WSAEDISCON = -5;
303   WSAHOST_NOT_FOUND = 1;
304   WSATRY_AGAIN = 2;
305   WSANO_RECOVERY = 3;
306   WSANO_DATA = -6;
307 
308 const
309   WSADESCRIPTION_LEN     =   256;
310   WSASYS_STATUS_LEN      =   128;
311 type
312   PWSAData = ^TWSAData;
313   TWSAData = packed record
314     wVersion: Word;
315     wHighVersion: Word;
316     szDescription: array[0..WSADESCRIPTION_LEN] of Char;
317     szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
318     iMaxSockets: Word;
319     iMaxUdpDg: Word;
320     lpVendorInfo: PChar;
321   end;
322 
IN6_IS_ADDR_UNSPECIFIEDnull323   function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
IN6_IS_ADDR_LOOPBACKnull324   function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
IN6_IS_ADDR_LINKLOCALnull325   function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
IN6_IS_ADDR_SITELOCALnull326   function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
IN6_IS_ADDR_MULTICASTnull327   function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
IN6_ADDR_EQUALnull328   function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
329   procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
330   procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
331 
332 var
333   in6addr_any, in6addr_loopback : TInAddr6;
334 
335 procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
FD_ISSETnull336 function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
337 procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
338 procedure FD_ZERO(var FDSet: TFDSet);
339 
340 {=============================================================================}
341 
342 var
343   SynSockCS: SyncObjs.TCriticalSection;
344   SockEnhancedApi: Boolean;
345   SockWship6Api: Boolean;
346 
347 type
348   TVarSin = packed record
349   {$ifdef SOCK_HAS_SINLEN}
350      sin_len     : cuchar;
351   {$endif}
352     case integer of
353       0: (AddressFamily: sa_family_t);
354       1: (
355         case sin_family: sa_family_t of
356           AF_INET: (sin_port: word;
357                     sin_addr: TInAddr;
358                     sin_zero: array[0..7] of Char);
359           AF_INET6: (sin6_port:     word;
360                 		sin6_flowinfo: longword;
361       	    	      sin6_addr:     TInAddr6;
362       		          sin6_scope_id: longword);
363           );
364   end;
365 
SizeOfVarSinnull366 function SizeOfVarSin(sin: TVarSin): integer;
367 
WSAStartupnull368   function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
WSACleanupnull369   function WSACleanup: Integer;
WSAGetLastErrornull370   function WSAGetLastError: Integer;
GetHostNamenull371   function GetHostName: string;
Shutdownnull372   function Shutdown(s: TSocket; how: Integer): Integer;
SetSockOptnull373   function SetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
374     optlen: Integer): Integer;
GetSockOptnull375   function GetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
376     var optlen: Integer): Integer;
Sendnull377   function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
Recvnull378   function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
SendTonull379   function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
RecvFromnull380   function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
ntohsnull381   function ntohs(netshort: word): word;
ntohlnull382   function ntohl(netlong: longword): longword;
Listennull383   function Listen(s: TSocket; backlog: Integer): Integer;
IoctlSocketnull384   function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
htonsnull385   function htons(hostshort: word): word;
htonlnull386   function htonl(hostlong: longword): longword;
GetSockNamenull387   function GetSockName(s: TSocket; var name: TVarSin): Integer;
GetPeerNamenull388   function GetPeerName(s: TSocket; var name: TVarSin): Integer;
Connectnull389   function Connect(s: TSocket; const name: TVarSin): Integer;
CloseSocketnull390   function CloseSocket(s: TSocket): Integer;
Bindnull391   function Bind(s: TSocket; const addr: TVarSin): Integer;
Acceptnull392   function Accept(s: TSocket; var addr: TVarSin): TSocket;
Socketnull393   function Socket(af, Struc, Protocol: Integer): TSocket;
Selectnull394   function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
395     timeout: PTimeVal): Longint;
396 
IsNewApinull397 function IsNewApi(Family: integer): Boolean;
SetVarSinnull398 function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
GetSinIPnull399 function GetSinIP(Sin: TVarSin): string;
GetSinPortnull400 function GetSinPort(Sin: TVarSin): Integer;
401 procedure ResolveNameToIP(Name: string;  Family, SockProtocol, SockType: integer; const IPList: TStrings);
ResolveIPToNamenull402 function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
ResolvePortnull403 function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
404 
405 
406 {==============================================================================}
407 implementation
408 
409 
IN6_IS_ADDR_UNSPECIFIEDnull410 function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
411 begin
412   Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
413              (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
414 end;
415 
IN6_IS_ADDR_LOOPBACKnull416 function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
417 begin
418   Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
419              (a^.u6_addr32[2] = 0) and
420              (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
421              (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
422 end;
423 
IN6_IS_ADDR_LINKLOCALnull424 function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
425 begin
426   Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
427 end;
428 
IN6_IS_ADDR_SITELOCALnull429 function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
430 begin
431   Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
432 end;
433 
IN6_IS_ADDR_MULTICASTnull434 function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
435 begin
436   Result := (a^.u6_addr8[0] = $FF);
437 end;
438 
IN6_ADDR_EQUALnull439 function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
440 begin
441   Result := (CompareMem( a, b, sizeof(TInAddr6)));
442 end;
443 
444 procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
445 begin
446   FillChar(a^, sizeof(TInAddr6), 0);
447 end;
448 
449 procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
450 begin
451   FillChar(a^, sizeof(TInAddr6), 0);
452   a^.u6_addr8[15] := 1;
453 end;
454 
455 {=============================================================================}
456 
WSAStartupnull457 function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
458 begin
459   with WSData do
460   begin
461     wVersion := wVersionRequired;
462     wHighVersion := $202;
463     szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
464     szSystemStatus := 'Running on Unix/Linux by FreePascal';
465     iMaxSockets := 32768;
466     iMaxUdpDg := 8192;
467   end;
468   Result := 0;
469 end;
470 
WSACleanupnull471 function WSACleanup: Integer;
472 begin
473   Result := 0;
474 end;
475 
WSAGetLastErrornull476 function WSAGetLastError: Integer;
477 begin
478   Result := fpGetErrno;
479 end;
480 
FD_ISSETnull481 function FD_ISSET(Socket: TSocket; var fdset: TFDSet): Boolean;
482 begin
483   Result := fpFD_ISSET(socket, fdset) <> 0;
484 end;
485 
486 procedure FD_SET(Socket: TSocket; var fdset: TFDSet);
487 begin
488   fpFD_SET(Socket, fdset);
489 end;
490 
491 procedure FD_CLR(Socket: TSocket; var fdset: TFDSet);
492 begin
493   fpFD_CLR(Socket, fdset);
494 end;
495 
496 procedure FD_ZERO(var fdset: TFDSet);
497 begin
498   fpFD_ZERO(fdset);
499 end;
500 
501 {=============================================================================}
502 
SizeOfVarSinnull503 function SizeOfVarSin(sin: TVarSin): integer;
504 begin
505   case sin.sin_family of
506     AF_INET:
507             Result := SizeOf(TSockAddrIn);
508     AF_INET6:
509             Result := SizeOf(TSockAddrIn6);
510   else
511     Result := 0;
512   end;
513 end;
514 
515 {=============================================================================}
516 
Bindnull517 function Bind(s: TSocket; const addr: TVarSin): Integer;
518 begin
519   if fpBind(s, @addr, SizeOfVarSin(addr)) = 0 then
520     Result := 0
521   else
522     Result := SOCKET_ERROR;
523 end;
524 
Connectnull525 function Connect(s: TSocket; const name: TVarSin): Integer;
526 begin
527   if fpConnect(s, @name, SizeOfVarSin(name)) = 0 then
528     Result := 0
529   else
530     Result := SOCKET_ERROR;
531 end;
532 
GetSockNamenull533 function GetSockName(s: TSocket; var name: TVarSin): Integer;
534 var
535   len: integer;
536 begin
537   len := SizeOf(name);
538   FillChar(name, len, 0);
539   Result := fpGetSockName(s, @name, @Len);
540 end;
541 
GetPeerNamenull542 function GetPeerName(s: TSocket; var name: TVarSin): Integer;
543 var
544   len: integer;
545 begin
546   len := SizeOf(name);
547   FillChar(name, len, 0);
548   Result := fpGetPeerName(s, @name, @Len);
549 end;
550 
GetHostNamenull551 function GetHostName: string;
552 begin
553   Result := unix.GetHostName;
554 end;
555 
Sendnull556 function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
557 begin
558   Result := fpSend(s, pointer(Buf), len, flags);
559 end;
560 
Recvnull561 function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
562 begin
563   Result := fpRecv(s, pointer(Buf), len, flags);
564 end;
565 
SendTonull566 function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
567 begin
568   Result := fpSendTo(s, pointer(Buf), len, flags, @addrto, SizeOfVarSin(addrto));
569 end;
570 
RecvFromnull571 function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
572 var
573   x: integer;
574 begin
575   x := SizeOf(from);
576   Result := fpRecvFrom(s, pointer(Buf), len, flags, @from, @x);
577 end;
578 
Acceptnull579 function Accept(s: TSocket; var addr: TVarSin): TSocket;
580 var
581   x: integer;
582 begin
583   x := SizeOf(addr);
584   Result := fpAccept(s, @addr, @x);
585 end;
586 
Shutdownnull587 function Shutdown(s: TSocket; how: Integer): Integer;
588 begin
589   Result := fpShutdown(s, how);
590 end;
591 
SetSockOptnull592 function SetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
593   optlen: Integer): Integer;
594 begin
595   Result := fpsetsockopt(s, level, optname, pointer(optval), optlen);
596 end;
597 
GetSockOptnull598 function GetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
599   var optlen: Integer): Integer;
600 begin
601   Result := fpgetsockopt(s, level, optname, pointer(optval), @optlen);
602 end;
603 
ntohsnull604 function  ntohs(netshort: word): word;
605 begin
606   Result := sockets.ntohs(NetShort);
607 end;
608 
ntohlnull609 function  ntohl(netlong: longword): longword;
610 begin
611   Result := sockets.ntohl(NetLong);
612 end;
613 
Listennull614 function  Listen(s: TSocket; backlog: Integer): Integer;
615 begin
616   if fpListen(s, backlog) = 0 then
617     Result := 0
618   else
619     Result := SOCKET_ERROR;
620 end;
621 
IoctlSocketnull622 function  IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
623 begin
624   Result := fpIoctl(s, cmd, @arg);
625 end;
626 
htonsnull627 function  htons(hostshort: word): word;
628 begin
629   Result := sockets.htons(Hostshort);
630 end;
631 
htonlnull632 function  htonl(hostlong: longword): longword;
633 begin
634   Result := sockets.htonl(HostLong);
635 end;
636 
CloseSocketnull637 function CloseSocket(s: TSocket): Integer;
638 begin
639   Result := sockets.CloseSocket(s);
640 end;
641 
Socketnull642 function Socket(af, Struc, Protocol: Integer): TSocket;
643 begin
644   Result := fpSocket(af, struc, protocol);
645 end;
646 
Selectnull647 function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
648   timeout: PTimeVal): Longint;
649 begin
650   Result := fpSelect(nfds, readfds, writefds, exceptfds, timeout);
651 end;
652 
653 {=============================================================================}
IsNewApinull654 function IsNewApi(Family: integer): Boolean;
655 begin
656   Result := SockEnhancedApi;
657   if not Result then
658     Result := (Family = AF_INET6) and SockWship6Api;
659 end;
660 
SetVarSinnull661 function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
662 var
663   TwoPass: boolean;
664   f1, f2: integer;
665 
GetAddrnull666   function GetAddr(f:integer): integer;
667   var
668     a4: array [1..1] of in_addr;
669     a6: array [1..1] of Tin6_addr;
670   begin
671     Result := WSAEPROTONOSUPPORT;
672     case f of
673       AF_INET:
674         begin
675           if IP = cAnyHost then
676           begin
677             Sin.sin_family := AF_INET;
678             Result := 0;
679           end
680           else
681           begin
682             if lowercase(IP) = cLocalHostStr then
683               a4[1].s_addr := htonl(INADDR_LOOPBACK)
684             else
685             begin
686               a4[1].s_addr := 0;
687               Result := WSAHOST_NOT_FOUND;
688               a4[1] := StrTonetAddr(IP);
689               if a4[1].s_addr = INADDR_ANY then
690                 Resolvename(ip, a4);
691             end;
692             if a4[1].s_addr <> INADDR_ANY then
693             begin
694               Sin.sin_family := AF_INET;
695               sin.sin_addr := a4[1];
696               Result := 0;
697             end;
698           end;
699         end;
700       AF_INET6:
701         begin
702           if IP = c6AnyHost then
703           begin
704             Sin.sin_family := AF_INET6;
705             Result := 0;
706           end
707           else
708           begin
709             if lowercase(IP) = cLocalHostStr then
710               SET_LOOPBACK_ADDR6(@a6[1])
711             else
712             begin
713               Result := WSAHOST_NOT_FOUND;
714               SET_IN6_IF_ADDR_ANY(@a6[1]);
715               a6[1] := StrTonetAddr6(IP);
716               if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
717                 Resolvename6(ip, a6);
718             end;
719             if not IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
720             begin
721               Sin.sin_family := AF_INET6;
722               sin.sin6_addr := a6[1];
723               Result := 0;
724             end;
725           end;
726         end;
727     end;
728   end;
729 begin
730   Result := 0;
731   FillChar(Sin, Sizeof(Sin), 0);
732   Sin.sin_port := Resolveport(port, family, SockProtocol, SockType);
733   TwoPass := False;
734   if Family = AF_UNSPEC then
735   begin
736     if PreferIP4 then
737     begin
738       f1 := AF_INET;
739       f2 := AF_INET6;
740       TwoPass := True;
741     end
742     else
743     begin
744       f2 := AF_INET;
745       f1 := AF_INET6;
746       TwoPass := True;
747     end;
748   end
749   else
750     f1 := Family;
751   Result := GetAddr(f1);
752   if Result <> 0 then
753     if TwoPass then
754       Result := GetAddr(f2);
755 end;
756 
GetSinIPnull757 function GetSinIP(Sin: TVarSin): string;
758 begin
759   Result := '';
760   case sin.AddressFamily of
761     AF_INET:
762       begin
763         result := NetAddrToStr(sin.sin_addr);
764       end;
765     AF_INET6:
766       begin
767         result := NetAddrToStr6(sin.sin6_addr);
768       end;
769   end;
770 end;
771 
GetSinPortnull772 function GetSinPort(Sin: TVarSin): Integer;
773 begin
774   if (Sin.sin_family = AF_INET6) then
775     Result := synsock.ntohs(Sin.sin6_port)
776   else
777     Result := synsock.ntohs(Sin.sin_port);
778 end;
779 
780 procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
781 var
782   x, n: integer;
783   a4: array [1..255] of in_addr;
784   a6: array [1..255] of Tin6_addr;
785 begin
786   IPList.Clear;
787   if (family = AF_INET) or (family = AF_UNSPEC) then
788   begin
789     if lowercase(name) = cLocalHostStr then
790       IpList.Add(cLocalHost)
791     else
792     begin
793       a4[1] := StrTonetAddr(name);
794       if a4[1].s_addr = INADDR_ANY then
795         x := Resolvename(name, a4)
796       else
797         x := 1;
798       for n := 1  to x do
799         IpList.Add(netaddrToStr(a4[n]));
800     end;
801   end;
802 
803   if (family = AF_INET6) or (family = AF_UNSPEC) then
804   begin
805     if lowercase(name) = cLocalHostStr then
806       IpList.Add(c6LocalHost)
807     else
808     begin
809       a6[1] := StrTonetAddr6(name);
810       if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
811         x := Resolvename6(name, a6)
812       else
813         x := 1;
814       for n := 1  to x do
815         IpList.Add(netaddrToStr6(a6[n]));
816     end;
817   end;
818 
819   if IPList.Count = 0 then
820     IPList.Add(cLocalHost);
821 end;
822 
ResolvePortnull823 function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
824 var
825   ProtoEnt: TProtocolEntry;
826   ServEnt: TServiceEntry;
827 begin
828   Result := synsock.htons(StrToIntDef(Port, 0));
829   if Result = 0 then
830   begin
831     ProtoEnt.Name := '';
832     GetProtocolByNumber(SockProtocol, ProtoEnt);
833     ServEnt.port := 0;
834     GetServiceByName(Port, ProtoEnt.Name, ServEnt);
835     Result := ServEnt.port;
836   end;
837 end;
838 
ResolveIPToNamenull839 function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
840 var
841   n: integer;
842   a4: array [1..1] of in_addr;
843   a6: array [1..1] of Tin6_addr;
844   a: array [1..1] of string;
845 begin
846   Result := IP;
847   a4[1] := StrToNetAddr(IP);
848   if a4[1].s_addr <> INADDR_ANY then
849   begin
850 //why ResolveAddress need address in HOST order? :-O
851     n := ResolveAddress(nettohost(a4[1]), a);
852     if n > 0 then
853       Result := a[1];
854   end
855   else
856   begin
857     a6[1] := StrToNetAddr6(IP);
858     n := ResolveAddress6(a6[1], a);
859     if n > 0 then
860       Result := a[1];
861   end;
862 end;
863 
864 {=============================================================================}
865 
InitSocketInterfacenull866 function InitSocketInterface(stack: string): Boolean;
867 begin
868   SockEnhancedApi := False;
869   SockWship6Api := False;
870 //  Libc.Signal(Libc.SIGPIPE, TSignalHandler(Libc.SIG_IGN));
871   Result := True;
872 end;
873 
DestroySocketInterfacenull874 function DestroySocketInterface: Boolean;
875 begin
876   Result := True;
877 end;
878 
879 initialization
880 begin
881   SynSockCS := SyncObjs.TCriticalSection.Create;
882   SET_IN6_IF_ADDR_ANY (@in6addr_any);
883   SET_LOOPBACK_ADDR6  (@in6addr_loopback);
884 end;
885 
886 finalization
887 begin
888   SynSockCS.Free;
889 end;
890 
891 {$ENDIF}
892 
893