source: trunk/Packages/synapse/ssfpc.pas

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