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