1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . S O C K E T S --
9 -- Copyright (C) 2001-2009, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada.Streams; use Ada.Streams;
35 with Ada.Exceptions; use Ada.Exceptions;
36 with Ada.Finalization;
37 with Ada.Unchecked_Conversion;
39 with Interfaces.C.Strings;
41 with GNAT.Sockets.Thin_Common; use GNAT.Sockets.Thin_Common;
42 with GNAT.Sockets.Thin; use GNAT.Sockets.Thin;
43 with GNAT.Sockets.Thin.Task_Safe_NetDB; use GNAT.Sockets.Thin.Task_Safe_NetDB;
45 with GNAT.Sockets.Linker_Options;
46 pragma Warnings (Off, GNAT.Sockets.Linker_Options);
47 -- Need to include pragma Linker_Options which is platform dependent
49 with System; use System;
51 package body GNAT.Sockets is
53 package C renames Interfaces.C;
57 ENOERROR : constant := 0;
59 Empty_Socket_Set : Socket_Set_Type;
60 -- Variable set in Initialize, and then used internally to provide an
61 -- initial value for Socket_Set_Type objects.
63 Netdb_Buffer_Size : constant := SOSC.Need_Netdb_Buffer * 1024;
64 -- The network database functions gethostbyname, gethostbyaddr,
65 -- getservbyname and getservbyport can either be guaranteed task safe by
66 -- the operating system, or else return data through a user-provided buffer
67 -- to ensure concurrent uses do not interfere.
69 -- Correspondence tables
71 Levels : constant array (Level_Type) of C.int :=
72 (Socket_Level => SOSC.SOL_SOCKET,
73 IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP,
74 IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP,
75 IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP);
77 Modes : constant array (Mode_Type) of C.int :=
78 (Socket_Stream => SOSC.SOCK_STREAM,
79 Socket_Datagram => SOSC.SOCK_DGRAM);
81 Shutmodes : constant array (Shutmode_Type) of C.int :=
82 (Shut_Read => SOSC.SHUT_RD,
83 Shut_Write => SOSC.SHUT_WR,
84 Shut_Read_Write => SOSC.SHUT_RDWR);
86 Requests : constant array (Request_Name) of C.int :=
87 (Non_Blocking_IO => SOSC.FIONBIO,
88 N_Bytes_To_Read => SOSC.FIONREAD);
90 Options : constant array (Option_Name) of C.int :=
91 (Keep_Alive => SOSC.SO_KEEPALIVE,
92 Reuse_Address => SOSC.SO_REUSEADDR,
93 Broadcast => SOSC.SO_BROADCAST,
94 Send_Buffer => SOSC.SO_SNDBUF,
95 Receive_Buffer => SOSC.SO_RCVBUF,
96 Linger => SOSC.SO_LINGER,
97 Error => SOSC.SO_ERROR,
98 No_Delay => SOSC.TCP_NODELAY,
99 Add_Membership => SOSC.IP_ADD_MEMBERSHIP,
100 Drop_Membership => SOSC.IP_DROP_MEMBERSHIP,
101 Multicast_If => SOSC.IP_MULTICAST_IF,
102 Multicast_TTL => SOSC.IP_MULTICAST_TTL,
103 Multicast_Loop => SOSC.IP_MULTICAST_LOOP,
104 Receive_Packet_Info => SOSC.IP_PKTINFO,
105 Send_Timeout => SOSC.SO_SNDTIMEO,
106 Receive_Timeout => SOSC.SO_RCVTIMEO);
107 -- ??? Note: for OpenSolaris, Receive_Packet_Info should be IP_RECVPKTINFO,
108 -- but for Linux compatibility this constant is the same as IP_PKTINFO.
110 Flags : constant array (0 .. 3) of C.int :=
111 (0 => SOSC.MSG_OOB, -- Process_Out_Of_Band_Data
112 1 => SOSC.MSG_PEEK, -- Peek_At_Incoming_Data
113 2 => SOSC.MSG_WAITALL, -- Wait_For_A_Full_Reception
114 3 => SOSC.MSG_EOR); -- Send_End_Of_Record
116 Socket_Error_Id : constant Exception_Id := Socket_Error'Identity;
117 Host_Error_Id : constant Exception_Id := Host_Error'Identity;
119 Hex_To_Char : constant String (1 .. 16) := "0123456789ABCDEF";
120 -- Use to print in hexadecimal format
122 -----------------------
123 -- Local subprograms --
124 -----------------------
126 function Resolve_Error
127 (Error_Value : Integer;
128 From_Errno : Boolean := True) return Error_Type;
129 -- Associate an enumeration value (error_type) to en error value (errno).
130 -- From_Errno prevents from mixing h_errno with errno.
132 function To_Name (N : String) return Name_Type;
133 function To_String (HN : Name_Type) return String;
134 -- Conversion functions
136 function To_Int (F : Request_Flag_Type) return C.int;
137 -- Return the int value corresponding to the specified flags combination
139 function Set_Forced_Flags (F : C.int) return C.int;
140 -- Return F with the bits from SOSC.MSG_Forced_Flags forced set
142 function Short_To_Network
143 (S : C.unsigned_short) return C.unsigned_short;
144 pragma Inline (Short_To_Network);
145 -- Convert a port number into a network port number
147 function Network_To_Short
148 (S : C.unsigned_short) return C.unsigned_short
149 renames Short_To_Network;
150 -- Symmetric operation
153 (Val : Inet_Addr_VN_Type;
154 Hex : Boolean := False) return String;
155 -- Output an array of inet address components in hex or decimal mode
157 function Is_IP_Address (Name : String) return Boolean;
158 -- Return true when Name is an IP address in standard dot notation
160 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr;
161 procedure To_Inet_Addr
163 Result : out Inet_Addr_Type);
164 -- Conversion functions
166 function To_Host_Entry (E : Hostent) return Host_Entry_Type;
167 -- Conversion function
169 function To_Service_Entry (E : Servent) return Service_Entry_Type;
170 -- Conversion function
172 function To_Timeval (Val : Timeval_Duration) return Timeval;
173 -- Separate Val in seconds and microseconds
175 function To_Duration (Val : Timeval) return Timeval_Duration;
176 -- Reconstruct a Duration value from a Timeval record (seconds and
179 procedure Raise_Socket_Error (Error : Integer);
180 -- Raise Socket_Error with an exception message describing the error code
183 procedure Raise_Host_Error (H_Error : Integer);
184 -- Raise Host_Error exception with message describing error code (note
185 -- hstrerror seems to be obsolete) from h_errno.
187 procedure Narrow (Item : in out Socket_Set_Type);
188 -- Update Last as it may be greater than the real last socket
190 -- Types needed for Datagram_Socket_Stream_Type
192 type Datagram_Socket_Stream_Type is new Root_Stream_Type with record
193 Socket : Socket_Type;
195 From : Sock_Addr_Type;
198 type Datagram_Socket_Stream_Access is
199 access all Datagram_Socket_Stream_Type;
202 (Stream : in out Datagram_Socket_Stream_Type;
203 Item : out Ada.Streams.Stream_Element_Array;
204 Last : out Ada.Streams.Stream_Element_Offset);
207 (Stream : in out Datagram_Socket_Stream_Type;
208 Item : Ada.Streams.Stream_Element_Array);
210 -- Types needed for Stream_Socket_Stream_Type
212 type Stream_Socket_Stream_Type is new Root_Stream_Type with record
213 Socket : Socket_Type;
216 type Stream_Socket_Stream_Access is
217 access all Stream_Socket_Stream_Type;
220 (Stream : in out Stream_Socket_Stream_Type;
221 Item : out Ada.Streams.Stream_Element_Array;
222 Last : out Ada.Streams.Stream_Element_Offset);
225 (Stream : in out Stream_Socket_Stream_Type;
226 Item : Ada.Streams.Stream_Element_Array);
228 procedure Stream_Write
229 (Socket : Socket_Type;
230 Item : Ada.Streams.Stream_Element_Array;
231 To : access Sock_Addr_Type);
232 -- Common implementation for the Write operation of Datagram_Socket_Stream_
233 -- Type and Stream_Socket_Stream_Type.
235 procedure Wait_On_Socket
236 (Socket : Socket_Type;
238 Timeout : Selector_Duration;
239 Selector : access Selector_Type := null;
240 Status : out Selector_Status);
241 -- Common code for variants of socket operations supporting a timeout:
242 -- block in Check_Selector on Socket for at most the indicated timeout.
243 -- If For_Read is True, Socket is added to the read set for this call, else
244 -- it is added to the write set. If no selector is provided, a local one is
245 -- created for this call and destroyed prior to returning.
247 type Sockets_Library_Controller is new Ada.Finalization.Limited_Controlled
249 -- This type is used to generate automatic calls to Initialize and Finalize
250 -- during the elaboration and finalization of this package. A single object
251 -- of this type must exist at library level.
253 function Err_Code_Image (E : Integer) return String;
254 -- Return the value of E surrounded with brackets
257 (First : Stream_Element_Offset;
258 Count : C.int) return Stream_Element_Offset;
259 -- Compute the Last OUT parameter for the various Receive_Socket
260 -- subprograms: returns First + Count - 1, except for the case
261 -- where First = Stream_Element_Offset'First and Res = 0, in which
262 -- case Stream_Element_Offset'Last is returned instead.
264 procedure Initialize (X : in out Sockets_Library_Controller);
265 procedure Finalize (X : in out Sockets_Library_Controller);
271 function "+" (L, R : Request_Flag_Type) return Request_Flag_Type is
280 procedure Abort_Selector (Selector : Selector_Type) is
284 -- Send one byte to unblock select system call
286 Res := Signalling_Fds.Write (C.int (Selector.W_Sig_Socket));
288 if Res = Failure then
289 Raise_Socket_Error (Socket_Errno);
297 procedure Accept_Socket
298 (Server : Socket_Type;
299 Socket : out Socket_Type;
300 Address : out Sock_Addr_Type)
303 Sin : aliased Sockaddr_In;
304 Len : aliased C.int := Sin'Size / 8;
307 Res := C_Accept (C.int (Server), Sin'Address, Len'Access);
309 if Res = Failure then
310 Raise_Socket_Error (Socket_Errno);
313 Socket := Socket_Type (Res);
315 To_Inet_Addr (Sin.Sin_Addr, Address.Addr);
316 Address.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
323 procedure Accept_Socket
324 (Server : Socket_Type;
325 Socket : out Socket_Type;
326 Address : out Sock_Addr_Type;
327 Timeout : Selector_Duration;
328 Selector : access Selector_Type := null;
329 Status : out Selector_Status)
332 -- Wait for socket to become available for reading
338 Selector => Selector,
341 -- Accept connection if available
343 if Status = Completed then
344 Accept_Socket (Server, Socket, Address);
355 (E : Host_Entry_Type;
356 N : Positive := 1) return Inet_Addr_Type
359 return E.Addresses (N);
362 ----------------------
363 -- Addresses_Length --
364 ----------------------
366 function Addresses_Length (E : Host_Entry_Type) return Natural is
368 return E.Addresses_Length;
369 end Addresses_Length;
376 (E : Host_Entry_Type;
377 N : Positive := 1) return String
380 return To_String (E.Aliases (N));
388 (S : Service_Entry_Type;
389 N : Positive := 1) return String
392 return To_String (S.Aliases (N));
399 function Aliases_Length (E : Host_Entry_Type) return Natural is
401 return E.Aliases_Length;
408 function Aliases_Length (S : Service_Entry_Type) return Natural is
410 return S.Aliases_Length;
417 procedure Bind_Socket
418 (Socket : Socket_Type;
419 Address : Sock_Addr_Type)
422 Sin : aliased Sockaddr_In;
423 Len : constant C.int := Sin'Size / 8;
424 -- This assumes that Address.Family = Family_Inet???
427 if Address.Family = Family_Inet6 then
428 raise Socket_Error with "IPv6 not supported";
431 Set_Family (Sin.Sin_Family, Address.Family);
432 Set_Address (Sin'Unchecked_Access, To_In_Addr (Address.Addr));
434 (Sin'Unchecked_Access,
435 Short_To_Network (C.unsigned_short (Address.Port)));
437 Res := C_Bind (C.int (Socket), Sin'Address, Len);
439 if Res = Failure then
440 Raise_Socket_Error (Socket_Errno);
448 procedure Check_Selector
449 (Selector : in out Selector_Type;
450 R_Socket_Set : in out Socket_Set_Type;
451 W_Socket_Set : in out Socket_Set_Type;
452 Status : out Selector_Status;
453 Timeout : Selector_Duration := Forever)
455 E_Socket_Set : Socket_Set_Type := Empty_Socket_Set;
458 (Selector, R_Socket_Set, W_Socket_Set, E_Socket_Set, Status, Timeout);
465 procedure Check_Selector
466 (Selector : in out Selector_Type;
467 R_Socket_Set : in out Socket_Set_Type;
468 W_Socket_Set : in out Socket_Set_Type;
469 E_Socket_Set : in out Socket_Set_Type;
470 Status : out Selector_Status;
471 Timeout : Selector_Duration := Forever)
475 RSig : Socket_Type renames Selector.R_Sig_Socket;
476 TVal : aliased Timeval;
477 TPtr : Timeval_Access;
482 -- No timeout or Forever is indicated by a null timeval pointer
484 if Timeout = Forever then
487 TVal := To_Timeval (Timeout);
488 TPtr := TVal'Unchecked_Access;
491 -- Add read signalling socket
493 Set (R_Socket_Set, RSig);
495 Last := C.int'Max (C.int'Max (C.int (R_Socket_Set.Last),
496 C.int (W_Socket_Set.Last)),
497 C.int (E_Socket_Set.Last));
502 R_Socket_Set.Set'Access,
503 W_Socket_Set.Set'Access,
504 E_Socket_Set.Set'Access,
507 if Res = Failure then
508 Raise_Socket_Error (Socket_Errno);
511 -- If Select was resumed because of read signalling socket, read this
512 -- data and remove socket from set.
514 if Is_Set (R_Socket_Set, RSig) then
515 Clear (R_Socket_Set, RSig);
517 Res := Signalling_Fds.Read (C.int (RSig));
519 if Res = Failure then
520 Raise_Socket_Error (Socket_Errno);
529 -- Update socket sets in regard to their new contents
531 Narrow (R_Socket_Set);
532 Narrow (W_Socket_Set);
533 Narrow (E_Socket_Set);
541 (Item : in out Socket_Set_Type;
542 Socket : Socket_Type)
544 Last : aliased C.int := C.int (Item.Last);
546 if Item.Last /= No_Socket then
547 Remove_Socket_From_Set (Item.Set'Access, C.int (Socket));
548 Last_Socket_In_Set (Item.Set'Access, Last'Unchecked_Access);
549 Item.Last := Socket_Type (Last);
557 procedure Close_Selector (Selector : in out Selector_Type) is
559 -- Close the signalling file descriptors used internally for the
560 -- implementation of Abort_Selector.
562 Signalling_Fds.Close (C.int (Selector.R_Sig_Socket));
563 Signalling_Fds.Close (C.int (Selector.W_Sig_Socket));
565 -- Reset R_Sig_Socket and W_Sig_Socket to No_Socket to ensure that any
566 -- (erroneous) subsequent attempt to use this selector properly fails.
568 Selector.R_Sig_Socket := No_Socket;
569 Selector.W_Sig_Socket := No_Socket;
576 procedure Close_Socket (Socket : Socket_Type) is
580 Res := C_Close (C.int (Socket));
582 if Res = Failure then
583 Raise_Socket_Error (Socket_Errno);
591 procedure Connect_Socket
592 (Socket : Socket_Type;
593 Server : Sock_Addr_Type)
596 Sin : aliased Sockaddr_In;
597 Len : constant C.int := Sin'Size / 8;
600 if Server.Family = Family_Inet6 then
601 raise Socket_Error with "IPv6 not supported";
604 Set_Family (Sin.Sin_Family, Server.Family);
605 Set_Address (Sin'Unchecked_Access, To_In_Addr (Server.Addr));
607 (Sin'Unchecked_Access,
608 Short_To_Network (C.unsigned_short (Server.Port)));
610 Res := C_Connect (C.int (Socket), Sin'Address, Len);
612 if Res = Failure then
613 Raise_Socket_Error (Socket_Errno);
621 procedure Connect_Socket
622 (Socket : Socket_Type;
623 Server : Sock_Addr_Type;
624 Timeout : Selector_Duration;
625 Selector : access Selector_Type := null;
626 Status : out Selector_Status)
629 -- Used to set Socket to non-blocking I/O
632 -- Set the socket to non-blocking I/O
634 Req := (Name => Non_Blocking_IO, Enabled => True);
635 Control_Socket (Socket, Request => Req);
637 -- Start operation (non-blocking), will raise Socket_Error with
641 Connect_Socket (Socket, Server);
643 when E : Socket_Error =>
644 if Resolve_Exception (E) = Operation_Now_In_Progress then
651 -- Wait for socket to become available for writing
657 Selector => Selector,
660 -- Reset the socket to blocking I/O
662 Req := (Name => Non_Blocking_IO, Enabled => False);
663 Control_Socket (Socket, Request => Req);
670 procedure Control_Socket
671 (Socket : Socket_Type;
672 Request : in out Request_Type)
679 when Non_Blocking_IO =>
680 Arg := C.int (Boolean'Pos (Request.Enabled));
682 when N_Bytes_To_Read =>
687 (C.int (Socket), Requests (Request.Name), Arg'Unchecked_Access);
689 if Res = Failure then
690 Raise_Socket_Error (Socket_Errno);
694 when Non_Blocking_IO =>
697 when N_Bytes_To_Read =>
698 Request.Size := Natural (Arg);
707 (Source : Socket_Set_Type;
708 Target : in out Socket_Set_Type)
714 ---------------------
715 -- Create_Selector --
716 ---------------------
718 procedure Create_Selector (Selector : out Selector_Type) is
719 Two_Fds : aliased Fd_Pair;
723 -- We open two signalling file descriptors. One of them is used to send
724 -- data to the other, which is included in a C_Select socket set. The
725 -- communication is used to force a call to C_Select to complete, and
726 -- the waiting task to resume its execution.
728 Res := Signalling_Fds.Create (Two_Fds'Access);
730 if Res = Failure then
731 Raise_Socket_Error (Socket_Errno);
734 Selector.R_Sig_Socket := Socket_Type (Two_Fds (Read_End));
735 Selector.W_Sig_Socket := Socket_Type (Two_Fds (Write_End));
742 procedure Create_Socket
743 (Socket : out Socket_Type;
744 Family : Family_Type := Family_Inet;
745 Mode : Mode_Type := Socket_Stream)
750 Res := C_Socket (Families (Family), Modes (Mode), 0);
752 if Res = Failure then
753 Raise_Socket_Error (Socket_Errno);
756 Socket := Socket_Type (Res);
763 procedure Empty (Item : in out Socket_Set_Type) is
765 Reset_Socket_Set (Item.Set'Access);
766 Item.Last := No_Socket;
773 function Err_Code_Image (E : Integer) return String is
774 Msg : String := E'Img & "] ";
776 Msg (Msg'First) := '[';
784 procedure Finalize (X : in out Sockets_Library_Controller) is
785 pragma Unreferenced (X);
788 -- Finalization operation for the GNAT.Sockets package
797 procedure Finalize is
799 -- This is a dummy placeholder for an obsolete API.
800 -- The real finalization actions are in Initialize primitive operation
801 -- of Sockets_Library_Controller.
811 (Item : in out Socket_Set_Type;
812 Socket : out Socket_Type)
815 L : aliased C.int := C.int (Item.Last);
818 if Item.Last /= No_Socket then
820 (Item.Set'Access, Last => L'Access, Socket => S'Access);
821 Item.Last := Socket_Type (L);
822 Socket := Socket_Type (S);
833 (Stream : not null Stream_Access) return Sock_Addr_Type
836 if Stream.all in Datagram_Socket_Stream_Type then
837 return Datagram_Socket_Stream_Type (Stream.all).From;
839 return Get_Peer_Name (Stream_Socket_Stream_Type (Stream.all).Socket);
843 -------------------------
844 -- Get_Host_By_Address --
845 -------------------------
847 function Get_Host_By_Address
848 (Address : Inet_Addr_Type;
849 Family : Family_Type := Family_Inet) return Host_Entry_Type
851 pragma Unreferenced (Family);
853 HA : aliased In_Addr := To_In_Addr (Address);
854 Buflen : constant C.int := Netdb_Buffer_Size;
855 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
856 Res : aliased Hostent;
860 if Safe_Gethostbyaddr (HA'Address, HA'Size / 8, SOSC.AF_INET,
861 Res'Access, Buf'Address, Buflen, Err'Access) /= 0
863 Raise_Host_Error (Integer (Err));
866 return To_Host_Entry (Res);
867 end Get_Host_By_Address;
869 ----------------------
870 -- Get_Host_By_Name --
871 ----------------------
873 function Get_Host_By_Name (Name : String) return Host_Entry_Type is
875 -- Detect IP address name and redirect to Inet_Addr
877 if Is_IP_Address (Name) then
878 return Get_Host_By_Address (Inet_Addr (Name));
882 HN : constant C.char_array := C.To_C (Name);
883 Buflen : constant C.int := Netdb_Buffer_Size;
884 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
885 Res : aliased Hostent;
889 if Safe_Gethostbyname
890 (HN, Res'Access, Buf'Address, Buflen, Err'Access) /= 0
892 Raise_Host_Error (Integer (Err));
895 return To_Host_Entry (Res);
897 end Get_Host_By_Name;
903 function Get_Peer_Name (Socket : Socket_Type) return Sock_Addr_Type is
904 Sin : aliased Sockaddr_In;
905 Len : aliased C.int := Sin'Size / 8;
906 Res : Sock_Addr_Type (Family_Inet);
909 if C_Getpeername (C.int (Socket), Sin'Address, Len'Access) = Failure then
910 Raise_Socket_Error (Socket_Errno);
913 To_Inet_Addr (Sin.Sin_Addr, Res.Addr);
914 Res.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
919 -------------------------
920 -- Get_Service_By_Name --
921 -------------------------
923 function Get_Service_By_Name
925 Protocol : String) return Service_Entry_Type
927 SN : constant C.char_array := C.To_C (Name);
928 SP : constant C.char_array := C.To_C (Protocol);
929 Buflen : constant C.int := Netdb_Buffer_Size;
930 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
931 Res : aliased Servent;
934 if Safe_Getservbyname (SN, SP, Res'Access, Buf'Address, Buflen) /= 0 then
935 raise Service_Error with "Service not found";
938 -- Translate from the C format to the API format
940 return To_Service_Entry (Res);
941 end Get_Service_By_Name;
943 -------------------------
944 -- Get_Service_By_Port --
945 -------------------------
947 function Get_Service_By_Port
949 Protocol : String) return Service_Entry_Type
951 SP : constant C.char_array := C.To_C (Protocol);
952 Buflen : constant C.int := Netdb_Buffer_Size;
953 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
954 Res : aliased Servent;
957 if Safe_Getservbyport
958 (C.int (Short_To_Network (C.unsigned_short (Port))), SP,
959 Res'Access, Buf'Address, Buflen) /= 0
961 raise Service_Error with "Service not found";
964 -- Translate from the C format to the API format
966 return To_Service_Entry (Res);
967 end Get_Service_By_Port;
969 ---------------------
970 -- Get_Socket_Name --
971 ---------------------
973 function Get_Socket_Name
974 (Socket : Socket_Type) return Sock_Addr_Type
976 Sin : aliased Sockaddr_In;
977 Len : aliased C.int := Sin'Size / 8;
979 Addr : Sock_Addr_Type := No_Sock_Addr;
982 Res := C_Getsockname (C.int (Socket), Sin'Address, Len'Access);
984 if Res /= Failure then
985 To_Inet_Addr (Sin.Sin_Addr, Addr.Addr);
986 Addr.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
992 -----------------------
993 -- Get_Socket_Option --
994 -----------------------
996 function Get_Socket_Option
997 (Socket : Socket_Type;
998 Level : Level_Type := Socket_Level;
999 Name : Option_Name) return Option_Type
1001 use type C.unsigned_char;
1003 V8 : aliased Two_Ints;
1005 V1 : aliased C.unsigned_char;
1006 VT : aliased Timeval;
1007 Len : aliased C.int;
1008 Add : System.Address;
1010 Opt : Option_Type (Name);
1014 when Multicast_Loop |
1016 Receive_Packet_Info =>
1051 if Res = Failure then
1052 Raise_Socket_Error (Socket_Errno);
1060 Opt.Enabled := (V4 /= 0);
1063 Opt.Enabled := (V8 (V8'First) /= 0);
1064 Opt.Seconds := Natural (V8 (V8'Last));
1068 Opt.Size := Natural (V4);
1071 Opt.Error := Resolve_Error (Integer (V4));
1073 when Add_Membership |
1075 To_Inet_Addr (To_In_Addr (V8 (V8'First)), Opt.Multicast_Address);
1076 To_Inet_Addr (To_In_Addr (V8 (V8'Last)), Opt.Local_Interface);
1078 when Multicast_If =>
1079 To_Inet_Addr (To_In_Addr (V4), Opt.Outgoing_If);
1081 when Multicast_TTL =>
1082 Opt.Time_To_Live := Integer (V1);
1084 when Multicast_Loop |
1085 Receive_Packet_Info =>
1086 Opt.Enabled := (V1 /= 0);
1090 Opt.Timeout := To_Duration (VT);
1094 end Get_Socket_Option;
1100 function Host_Name return String is
1101 Name : aliased C.char_array (1 .. 64);
1105 Res := C_Gethostname (Name'Address, Name'Length);
1107 if Res = Failure then
1108 Raise_Socket_Error (Socket_Errno);
1111 return C.To_Ada (Name);
1119 (Val : Inet_Addr_VN_Type;
1120 Hex : Boolean := False) return String
1122 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
1123 -- has at most a length of 3 plus one '.' character.
1125 Buffer : String (1 .. 4 * Val'Length);
1126 Length : Natural := 1;
1127 Separator : Character;
1129 procedure Img10 (V : Inet_Addr_Comp_Type);
1130 -- Append to Buffer image of V in decimal format
1132 procedure Img16 (V : Inet_Addr_Comp_Type);
1133 -- Append to Buffer image of V in hexadecimal format
1139 procedure Img10 (V : Inet_Addr_Comp_Type) is
1140 Img : constant String := V'Img;
1141 Len : constant Natural := Img'Length - 1;
1143 Buffer (Length .. Length + Len - 1) := Img (2 .. Img'Last);
1144 Length := Length + Len;
1151 procedure Img16 (V : Inet_Addr_Comp_Type) is
1153 Buffer (Length) := Hex_To_Char (Natural (V / 16) + 1);
1154 Buffer (Length + 1) := Hex_To_Char (Natural (V mod 16) + 1);
1155 Length := Length + 2;
1158 -- Start of processing for Image
1161 Separator := (if Hex then ':' else '.');
1163 for J in Val'Range loop
1170 if J /= Val'Last then
1171 Buffer (Length) := Separator;
1172 Length := Length + 1;
1176 return Buffer (1 .. Length - 1);
1183 function Image (Value : Inet_Addr_Type) return String is
1185 if Value.Family = Family_Inet then
1186 return Image (Inet_Addr_VN_Type (Value.Sin_V4), Hex => False);
1188 return Image (Inet_Addr_VN_Type (Value.Sin_V6), Hex => True);
1196 function Image (Value : Sock_Addr_Type) return String is
1197 Port : constant String := Value.Port'Img;
1199 return Image (Value.Addr) & ':' & Port (2 .. Port'Last);
1206 function Image (Socket : Socket_Type) return String is
1215 function Image (Item : Socket_Set_Type) return String is
1216 Socket_Set : Socket_Set_Type := Item;
1220 Last_Img : constant String := Socket_Set.Last'Img;
1222 (1 .. (Integer (Socket_Set.Last) + 1) * Last_Img'Length);
1223 Index : Positive := 1;
1224 Socket : Socket_Type;
1227 while not Is_Empty (Socket_Set) loop
1228 Get (Socket_Set, Socket);
1231 Socket_Img : constant String := Socket'Img;
1233 Buffer (Index .. Index + Socket_Img'Length - 1) := Socket_Img;
1234 Index := Index + Socket_Img'Length;
1238 return "[" & Last_Img & "]" & Buffer (1 .. Index - 1);
1246 function Inet_Addr (Image : String) return Inet_Addr_Type is
1248 use Interfaces.C.Strings;
1250 Img : aliased char_array := To_C (Image);
1251 Cp : constant chars_ptr := To_Chars_Ptr (Img'Unchecked_Access);
1252 Addr : aliased C.int;
1254 Result : Inet_Addr_Type;
1257 -- Special case for an empty Image as on some platforms (e.g. Windows)
1258 -- calling Inet_Addr("") will not return an error.
1261 Raise_Socket_Error (SOSC.EINVAL);
1264 Res := Inet_Pton (SOSC.AF_INET, Cp, Addr'Address);
1267 Raise_Socket_Error (Socket_Errno);
1270 Raise_Socket_Error (SOSC.EINVAL);
1273 To_Inet_Addr (To_In_Addr (Addr), Result);
1281 procedure Initialize (X : in out Sockets_Library_Controller) is
1282 pragma Unreferenced (X);
1285 -- Initialization operation for the GNAT.Sockets package
1287 Empty_Socket_Set.Last := No_Socket;
1288 Reset_Socket_Set (Empty_Socket_Set.Set'Access);
1296 procedure Initialize (Process_Blocking_IO : Boolean) is
1297 Expected : constant Boolean := not SOSC.Thread_Blocking_IO;
1300 if Process_Blocking_IO /= Expected then
1301 raise Socket_Error with
1302 "incorrect Process_Blocking_IO setting, expected " & Expected'Img;
1305 -- This is a dummy placeholder for an obsolete API
1307 -- Real initialization actions are in Initialize primitive operation
1308 -- of Sockets_Library_Controller.
1317 procedure Initialize is
1319 -- This is a dummy placeholder for an obsolete API
1321 -- Real initialization actions are in Initialize primitive operation
1322 -- of Sockets_Library_Controller.
1331 function Is_Empty (Item : Socket_Set_Type) return Boolean is
1333 return Item.Last = No_Socket;
1340 function Is_IP_Address (Name : String) return Boolean is
1342 for J in Name'Range loop
1344 and then Name (J) not in '0' .. '9'
1358 (Item : Socket_Set_Type;
1359 Socket : Socket_Type) return Boolean
1362 return Item.Last /= No_Socket
1363 and then Socket <= Item.Last
1364 and then Is_Socket_In_Set (Item.Set'Access, C.int (Socket)) /= 0;
1372 (First : Stream_Element_Offset;
1373 Count : C.int) return Stream_Element_Offset
1376 if First = Stream_Element_Offset'First and then Count = 0 then
1377 return Stream_Element_Offset'Last;
1379 return First + Stream_Element_Offset (Count - 1);
1387 procedure Listen_Socket
1388 (Socket : Socket_Type;
1389 Length : Natural := 15)
1391 Res : constant C.int := C_Listen (C.int (Socket), C.int (Length));
1393 if Res = Failure then
1394 Raise_Socket_Error (Socket_Errno);
1402 procedure Narrow (Item : in out Socket_Set_Type) is
1403 Last : aliased C.int := C.int (Item.Last);
1405 if Item.Last /= No_Socket then
1406 Last_Socket_In_Set (Item.Set'Access, Last'Unchecked_Access);
1407 Item.Last := Socket_Type (Last);
1415 function Official_Name (E : Host_Entry_Type) return String is
1417 return To_String (E.Official);
1424 function Official_Name (S : Service_Entry_Type) return String is
1426 return To_String (S.Official);
1429 --------------------
1430 -- Wait_On_Socket --
1431 --------------------
1433 procedure Wait_On_Socket
1434 (Socket : Socket_Type;
1436 Timeout : Selector_Duration;
1437 Selector : access Selector_Type := null;
1438 Status : out Selector_Status)
1440 type Local_Selector_Access is access Selector_Type;
1441 for Local_Selector_Access'Storage_Size use Selector_Type'Size;
1443 S : Selector_Access;
1444 -- Selector to use for waiting
1446 R_Fd_Set : Socket_Set_Type;
1447 W_Fd_Set : Socket_Set_Type;
1448 -- Socket sets, empty at elaboration
1451 -- Create selector if not provided by the user
1453 if Selector = null then
1455 Local_S : constant Local_Selector_Access := new Selector_Type;
1457 S := Local_S.all'Unchecked_Access;
1458 Create_Selector (S.all);
1462 S := Selector.all'Access;
1466 Set (R_Fd_Set, Socket);
1468 Set (W_Fd_Set, Socket);
1471 Check_Selector (S.all, R_Fd_Set, W_Fd_Set, Status, Timeout);
1473 -- Cleanup actions (required in all cases to avoid memory leaks)
1481 if Selector = null then
1482 Close_Selector (S.all);
1490 function Port_Number (S : Service_Entry_Type) return Port_Type is
1499 function Protocol_Name (S : Service_Entry_Type) return String is
1501 return To_String (S.Protocol);
1504 ----------------------
1505 -- Raise_Host_Error --
1506 ----------------------
1508 procedure Raise_Host_Error (H_Error : Integer) is
1510 raise Host_Error with
1511 Err_Code_Image (H_Error)
1512 & C.Strings.Value (Host_Error_Messages.Host_Error_Message (H_Error));
1513 end Raise_Host_Error;
1515 ------------------------
1516 -- Raise_Socket_Error --
1517 ------------------------
1519 procedure Raise_Socket_Error (Error : Integer) is
1520 use type C.Strings.chars_ptr;
1522 raise Socket_Error with
1523 Err_Code_Image (Error)
1524 & C.Strings.Value (Socket_Error_Message (Error));
1525 end Raise_Socket_Error;
1532 (Stream : in out Datagram_Socket_Stream_Type;
1533 Item : out Ada.Streams.Stream_Element_Array;
1534 Last : out Ada.Streams.Stream_Element_Offset)
1536 First : Ada.Streams.Stream_Element_Offset := Item'First;
1537 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1538 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1544 Item (First .. Max),
1550 -- Exit when all or zero data received. Zero means that the socket
1553 exit when Index < First or else Index = Max;
1564 (Stream : in out Stream_Socket_Stream_Type;
1565 Item : out Ada.Streams.Stream_Element_Array;
1566 Last : out Ada.Streams.Stream_Element_Offset)
1568 pragma Warnings (Off, Stream);
1570 First : Ada.Streams.Stream_Element_Offset := Item'First;
1571 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1572 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1576 Receive_Socket (Stream.Socket, Item (First .. Max), Index);
1579 -- Exit when all or zero data received. Zero means that the socket
1582 exit when Index < First or else Index = Max;
1588 --------------------
1589 -- Receive_Socket --
1590 --------------------
1592 procedure Receive_Socket
1593 (Socket : Socket_Type;
1594 Item : out Ada.Streams.Stream_Element_Array;
1595 Last : out Ada.Streams.Stream_Element_Offset;
1596 Flags : Request_Flag_Type := No_Request_Flag)
1602 C_Recv (C.int (Socket), Item'Address, Item'Length, To_Int (Flags));
1604 if Res = Failure then
1605 Raise_Socket_Error (Socket_Errno);
1608 Last := Last_Index (First => Item'First, Count => Res);
1611 --------------------
1612 -- Receive_Socket --
1613 --------------------
1615 procedure Receive_Socket
1616 (Socket : Socket_Type;
1617 Item : out Ada.Streams.Stream_Element_Array;
1618 Last : out Ada.Streams.Stream_Element_Offset;
1619 From : out Sock_Addr_Type;
1620 Flags : Request_Flag_Type := No_Request_Flag)
1623 Sin : aliased Sockaddr_In;
1624 Len : aliased C.int := Sin'Size / 8;
1636 if Res = Failure then
1637 Raise_Socket_Error (Socket_Errno);
1640 Last := Last_Index (First => Item'First, Count => Res);
1642 To_Inet_Addr (Sin.Sin_Addr, From.Addr);
1643 From.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
1646 --------------------
1647 -- Receive_Vector --
1648 --------------------
1650 procedure Receive_Vector
1651 (Socket : Socket_Type;
1652 Vector : Vector_Type;
1653 Count : out Ada.Streams.Stream_Element_Count;
1654 Flags : Request_Flag_Type := No_Request_Flag)
1659 (Msg_Name => System.Null_Address,
1661 Msg_Iov => Vector'Address,
1662 Msg_Iovlen => SOSC.Msg_Iovlen_T (Vector'Length),
1663 Msg_Control => System.Null_Address,
1664 Msg_Controllen => 0,
1674 if Res = ssize_t (Failure) then
1675 Raise_Socket_Error (Socket_Errno);
1678 Count := Ada.Streams.Stream_Element_Count (Res);
1685 function Resolve_Error
1686 (Error_Value : Integer;
1687 From_Errno : Boolean := True) return Error_Type
1689 use GNAT.Sockets.SOSC;
1692 if not From_Errno then
1694 when SOSC.HOST_NOT_FOUND => return Unknown_Host;
1695 when SOSC.TRY_AGAIN => return Host_Name_Lookup_Failure;
1696 when SOSC.NO_RECOVERY => return Non_Recoverable_Error;
1697 when SOSC.NO_DATA => return Unknown_Server_Error;
1698 when others => return Cannot_Resolve_Error;
1702 -- Special case: EAGAIN may be the same value as EWOULDBLOCK, so we
1703 -- can't include it in the case statement below.
1705 pragma Warnings (Off);
1706 -- Condition "EAGAIN /= EWOULDBLOCK" is known at compile time
1708 if EAGAIN /= EWOULDBLOCK and then Error_Value = EAGAIN then
1709 return Resource_Temporarily_Unavailable;
1712 pragma Warnings (On);
1715 when ENOERROR => return Success;
1716 when EACCES => return Permission_Denied;
1717 when EADDRINUSE => return Address_Already_In_Use;
1718 when EADDRNOTAVAIL => return Cannot_Assign_Requested_Address;
1719 when EAFNOSUPPORT => return
1720 Address_Family_Not_Supported_By_Protocol;
1721 when EALREADY => return Operation_Already_In_Progress;
1722 when EBADF => return Bad_File_Descriptor;
1723 when ECONNABORTED => return Software_Caused_Connection_Abort;
1724 when ECONNREFUSED => return Connection_Refused;
1725 when ECONNRESET => return Connection_Reset_By_Peer;
1726 when EDESTADDRREQ => return Destination_Address_Required;
1727 when EFAULT => return Bad_Address;
1728 when EHOSTDOWN => return Host_Is_Down;
1729 when EHOSTUNREACH => return No_Route_To_Host;
1730 when EINPROGRESS => return Operation_Now_In_Progress;
1731 when EINTR => return Interrupted_System_Call;
1732 when EINVAL => return Invalid_Argument;
1733 when EIO => return Input_Output_Error;
1734 when EISCONN => return Transport_Endpoint_Already_Connected;
1735 when ELOOP => return Too_Many_Symbolic_Links;
1736 when EMFILE => return Too_Many_Open_Files;
1737 when EMSGSIZE => return Message_Too_Long;
1738 when ENAMETOOLONG => return File_Name_Too_Long;
1739 when ENETDOWN => return Network_Is_Down;
1740 when ENETRESET => return
1741 Network_Dropped_Connection_Because_Of_Reset;
1742 when ENETUNREACH => return Network_Is_Unreachable;
1743 when ENOBUFS => return No_Buffer_Space_Available;
1744 when ENOPROTOOPT => return Protocol_Not_Available;
1745 when ENOTCONN => return Transport_Endpoint_Not_Connected;
1746 when ENOTSOCK => return Socket_Operation_On_Non_Socket;
1747 when EOPNOTSUPP => return Operation_Not_Supported;
1748 when EPFNOSUPPORT => return Protocol_Family_Not_Supported;
1749 when EPIPE => return Broken_Pipe;
1750 when EPROTONOSUPPORT => return Protocol_Not_Supported;
1751 when EPROTOTYPE => return Protocol_Wrong_Type_For_Socket;
1752 when ESHUTDOWN => return
1753 Cannot_Send_After_Transport_Endpoint_Shutdown;
1754 when ESOCKTNOSUPPORT => return Socket_Type_Not_Supported;
1755 when ETIMEDOUT => return Connection_Timed_Out;
1756 when ETOOMANYREFS => return Too_Many_References;
1757 when EWOULDBLOCK => return Resource_Temporarily_Unavailable;
1759 when others => return Cannot_Resolve_Error;
1763 -----------------------
1764 -- Resolve_Exception --
1765 -----------------------
1767 function Resolve_Exception
1768 (Occurrence : Exception_Occurrence) return Error_Type
1770 Id : constant Exception_Id := Exception_Identity (Occurrence);
1771 Msg : constant String := Exception_Message (Occurrence);
1778 while First <= Msg'Last
1779 and then Msg (First) not in '0' .. '9'
1784 if First > Msg'Last then
1785 return Cannot_Resolve_Error;
1789 while Last < Msg'Last
1790 and then Msg (Last + 1) in '0' .. '9'
1795 Val := Integer'Value (Msg (First .. Last));
1797 if Id = Socket_Error_Id then
1798 return Resolve_Error (Val);
1799 elsif Id = Host_Error_Id then
1800 return Resolve_Error (Val, False);
1802 return Cannot_Resolve_Error;
1804 end Resolve_Exception;
1810 procedure Send_Socket
1811 (Socket : Socket_Type;
1812 Item : Ada.Streams.Stream_Element_Array;
1813 Last : out Ada.Streams.Stream_Element_Offset;
1814 Flags : Request_Flag_Type := No_Request_Flag)
1817 Send_Socket (Socket, Item, Last, To => null, Flags => Flags);
1824 procedure Send_Socket
1825 (Socket : Socket_Type;
1826 Item : Ada.Streams.Stream_Element_Array;
1827 Last : out Ada.Streams.Stream_Element_Offset;
1828 To : Sock_Addr_Type;
1829 Flags : Request_Flag_Type := No_Request_Flag)
1833 (Socket, Item, Last, To => To'Unrestricted_Access, Flags => Flags);
1840 procedure Send_Socket
1841 (Socket : Socket_Type;
1842 Item : Ada.Streams.Stream_Element_Array;
1843 Last : out Ada.Streams.Stream_Element_Offset;
1844 To : access Sock_Addr_Type;
1845 Flags : Request_Flag_Type := No_Request_Flag)
1849 Sin : aliased Sockaddr_In;
1850 C_To : System.Address;
1855 Set_Family (Sin.Sin_Family, To.Family);
1856 Set_Address (Sin'Unchecked_Access, To_In_Addr (To.Addr));
1858 (Sin'Unchecked_Access,
1859 Short_To_Network (C.unsigned_short (To.Port)));
1860 C_To := Sin'Address;
1861 Len := Sin'Size / 8;
1864 C_To := System.Null_Address;
1872 Set_Forced_Flags (To_Int (Flags)),
1876 if Res = Failure then
1877 Raise_Socket_Error (Socket_Errno);
1880 Last := Last_Index (First => Item'First, Count => Res);
1887 procedure Send_Vector
1888 (Socket : Socket_Type;
1889 Vector : Vector_Type;
1890 Count : out Ada.Streams.Stream_Element_Count;
1891 Flags : Request_Flag_Type := No_Request_Flag)
1897 Iov_Count : SOSC.Msg_Iovlen_T;
1898 This_Iov_Count : SOSC.Msg_Iovlen_T;
1904 while Iov_Count < Vector'Length loop
1906 pragma Warnings (Off);
1907 -- Following test may be compile time known on some targets
1910 (if Vector'Length - Iov_Count > SOSC.IOV_MAX
1912 else Vector'Length - Iov_Count);
1914 pragma Warnings (On);
1917 (Msg_Name => System.Null_Address,
1920 (Vector'First + Integer (Iov_Count))'Address,
1921 Msg_Iovlen => This_Iov_Count,
1922 Msg_Control => System.Null_Address,
1923 Msg_Controllen => 0,
1930 Set_Forced_Flags (To_Int (Flags)));
1932 if Res = ssize_t (Failure) then
1933 Raise_Socket_Error (Socket_Errno);
1936 Count := Count + Ada.Streams.Stream_Element_Count (Res);
1937 Iov_Count := Iov_Count + This_Iov_Count;
1945 procedure Set (Item : in out Socket_Set_Type; Socket : Socket_Type) is
1947 if Item.Last = No_Socket then
1949 -- Uninitialized socket set, make sure it is properly zeroed out
1951 Reset_Socket_Set (Item.Set'Access);
1952 Item.Last := Socket;
1954 elsif Item.Last < Socket then
1955 Item.Last := Socket;
1958 Insert_Socket_In_Set (Item.Set'Access, C.int (Socket));
1961 ----------------------
1962 -- Set_Forced_Flags --
1963 ----------------------
1965 function Set_Forced_Flags (F : C.int) return C.int is
1966 use type C.unsigned;
1967 function To_unsigned is
1968 new Ada.Unchecked_Conversion (C.int, C.unsigned);
1970 new Ada.Unchecked_Conversion (C.unsigned, C.int);
1972 return To_int (To_unsigned (F) or SOSC.MSG_Forced_Flags);
1973 end Set_Forced_Flags;
1975 -----------------------
1976 -- Set_Socket_Option --
1977 -----------------------
1979 procedure Set_Socket_Option
1980 (Socket : Socket_Type;
1981 Level : Level_Type := Socket_Level;
1982 Option : Option_Type)
1984 V8 : aliased Two_Ints;
1986 V1 : aliased C.unsigned_char;
1987 VT : aliased Timeval;
1989 Add : System.Address := Null_Address;
1998 V4 := C.int (Boolean'Pos (Option.Enabled));
2003 V8 (V8'First) := C.int (Boolean'Pos (Option.Enabled));
2004 V8 (V8'Last) := C.int (Option.Seconds);
2010 V4 := C.int (Option.Size);
2015 V4 := C.int (Boolean'Pos (True));
2019 when Add_Membership |
2021 V8 (V8'First) := To_Int (To_In_Addr (Option.Multicast_Address));
2022 V8 (V8'Last) := To_Int (To_In_Addr (Option.Local_Interface));
2026 when Multicast_If =>
2027 V4 := To_Int (To_In_Addr (Option.Outgoing_If));
2031 when Multicast_TTL =>
2032 V1 := C.unsigned_char (Option.Time_To_Live);
2036 when Multicast_Loop |
2037 Receive_Packet_Info =>
2038 V1 := C.unsigned_char (Boolean'Pos (Option.Enabled));
2044 VT := To_Timeval (Option.Timeout);
2053 Options (Option.Name),
2056 if Res = Failure then
2057 Raise_Socket_Error (Socket_Errno);
2059 end Set_Socket_Option;
2061 ----------------------
2062 -- Short_To_Network --
2063 ----------------------
2065 function Short_To_Network (S : C.unsigned_short) return C.unsigned_short is
2066 use type C.unsigned_short;
2069 -- Big-endian case. No conversion needed. On these platforms,
2070 -- htons() defaults to a null procedure.
2072 pragma Warnings (Off);
2073 -- Since the test can generate "always True/False" warning
2075 if Default_Bit_Order = High_Order_First then
2078 pragma Warnings (On);
2080 -- Little-endian case. We must swap the high and low bytes of this
2081 -- short to make the port number network compliant.
2084 return (S / 256) + (S mod 256) * 256;
2086 end Short_To_Network;
2088 ---------------------
2089 -- Shutdown_Socket --
2090 ---------------------
2092 procedure Shutdown_Socket
2093 (Socket : Socket_Type;
2094 How : Shutmode_Type := Shut_Read_Write)
2099 Res := C_Shutdown (C.int (Socket), Shutmodes (How));
2101 if Res = Failure then
2102 Raise_Socket_Error (Socket_Errno);
2104 end Shutdown_Socket;
2111 (Socket : Socket_Type;
2112 Send_To : Sock_Addr_Type) return Stream_Access
2114 S : Datagram_Socket_Stream_Access;
2117 S := new Datagram_Socket_Stream_Type;
2120 S.From := Get_Socket_Name (Socket);
2121 return Stream_Access (S);
2128 function Stream (Socket : Socket_Type) return Stream_Access is
2129 S : Stream_Socket_Stream_Access;
2131 S := new Stream_Socket_Stream_Type;
2133 return Stream_Access (S);
2140 procedure Stream_Write
2141 (Socket : Socket_Type;
2142 Item : Ada.Streams.Stream_Element_Array;
2143 To : access Sock_Addr_Type)
2145 First : Ada.Streams.Stream_Element_Offset;
2146 Index : Ada.Streams.Stream_Element_Offset;
2147 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2150 First := Item'First;
2152 while First <= Max loop
2153 Send_Socket (Socket, Item (First .. Max), Index, To);
2155 -- Exit when all or zero data sent. Zero means that the socket has
2156 -- been closed by peer.
2158 exit when Index < First or else Index = Max;
2163 -- For an empty array, we have First > Max, and hence Index >= Max (no
2164 -- error, the loop above is never executed). After a succesful send,
2165 -- Index = Max. The only remaining case, Index < Max, is therefore
2166 -- always an actual send failure.
2169 Raise_Socket_Error (Socket_Errno);
2177 function To_C (Socket : Socket_Type) return Integer is
2179 return Integer (Socket);
2186 function To_Duration (Val : Timeval) return Timeval_Duration is
2188 return Natural (Val.Tv_Sec) * 1.0 + Natural (Val.Tv_Usec) * 1.0E-6;
2195 function To_Host_Entry (E : Hostent) return Host_Entry_Type is
2198 Official : constant String :=
2199 C.Strings.Value (E.H_Name);
2201 Aliases : constant Chars_Ptr_Array :=
2202 Chars_Ptr_Pointers.Value (E.H_Aliases);
2203 -- H_Aliases points to a list of name aliases. The list is terminated by
2206 Addresses : constant In_Addr_Access_Array :=
2207 In_Addr_Access_Pointers.Value (E.H_Addr_List);
2208 -- H_Addr_List points to a list of binary addresses (in network byte
2209 -- order). The list is terminated by a NULL pointer.
2211 -- H_Length is not used because it is currently only set to 4.
2212 -- H_Addrtype is always AF_INET
2214 Result : Host_Entry_Type
2215 (Aliases_Length => Aliases'Length - 1,
2216 Addresses_Length => Addresses'Length - 1);
2217 -- The last element is a null pointer
2223 Result.Official := To_Name (Official);
2225 Source := Aliases'First;
2226 Target := Result.Aliases'First;
2227 while Target <= Result.Aliases_Length loop
2228 Result.Aliases (Target) :=
2229 To_Name (C.Strings.Value (Aliases (Source)));
2230 Source := Source + 1;
2231 Target := Target + 1;
2234 Source := Addresses'First;
2235 Target := Result.Addresses'First;
2236 while Target <= Result.Addresses_Length loop
2237 To_Inet_Addr (Addresses (Source).all, Result.Addresses (Target));
2238 Source := Source + 1;
2239 Target := Target + 1;
2249 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr is
2251 if Addr.Family = Family_Inet then
2252 return (S_B1 => C.unsigned_char (Addr.Sin_V4 (1)),
2253 S_B2 => C.unsigned_char (Addr.Sin_V4 (2)),
2254 S_B3 => C.unsigned_char (Addr.Sin_V4 (3)),
2255 S_B4 => C.unsigned_char (Addr.Sin_V4 (4)));
2258 raise Socket_Error with "IPv6 not supported";
2265 procedure To_Inet_Addr
2267 Result : out Inet_Addr_Type) is
2269 Result.Sin_V4 (1) := Inet_Addr_Comp_Type (Addr.S_B1);
2270 Result.Sin_V4 (2) := Inet_Addr_Comp_Type (Addr.S_B2);
2271 Result.Sin_V4 (3) := Inet_Addr_Comp_Type (Addr.S_B3);
2272 Result.Sin_V4 (4) := Inet_Addr_Comp_Type (Addr.S_B4);
2279 function To_Int (F : Request_Flag_Type) return C.int
2281 Current : Request_Flag_Type := F;
2282 Result : C.int := 0;
2285 for J in Flags'Range loop
2286 exit when Current = 0;
2288 if Current mod 2 /= 0 then
2289 if Flags (J) = -1 then
2290 Raise_Socket_Error (SOSC.EOPNOTSUPP);
2293 Result := Result + Flags (J);
2296 Current := Current / 2;
2306 function To_Name (N : String) return Name_Type is
2308 return Name_Type'(N'Length, N);
2311 ----------------------
2312 -- To_Service_Entry --
2313 ----------------------
2315 function To_Service_Entry (E : Servent) return Service_Entry_Type is
2318 Official : constant String := C.Strings.Value (E.S_Name);
2320 Aliases : constant Chars_Ptr_Array :=
2321 Chars_Ptr_Pointers.Value (E.S_Aliases);
2322 -- S_Aliases points to a list of name aliases. The list is
2323 -- terminated by a NULL pointer.
2325 Protocol : constant String := C.Strings.Value (E.S_Proto);
2327 Result : Service_Entry_Type (Aliases_Length => Aliases'Length - 1);
2328 -- The last element is a null pointer
2334 Result.Official := To_Name (Official);
2336 Source := Aliases'First;
2337 Target := Result.Aliases'First;
2338 while Target <= Result.Aliases_Length loop
2339 Result.Aliases (Target) :=
2340 To_Name (C.Strings.Value (Aliases (Source)));
2341 Source := Source + 1;
2342 Target := Target + 1;
2346 Port_Type (Network_To_Short (C.unsigned_short (E.S_Port)));
2348 Result.Protocol := To_Name (Protocol);
2350 end To_Service_Entry;
2356 function To_String (HN : Name_Type) return String is
2358 return HN.Name (1 .. HN.Length);
2365 function To_Timeval (Val : Timeval_Duration) return Timeval is
2370 -- If zero, set result as zero (otherwise it gets rounded down to -1)
2376 -- Normal case where we do round down
2379 S := time_t (Val - 0.5);
2380 uS := suseconds_t (1_000_000 * (Val - Selector_Duration (S)));
2391 (Stream : in out Datagram_Socket_Stream_Type;
2392 Item : Ada.Streams.Stream_Element_Array)
2395 Stream_Write (Stream.Socket, Item, To => Stream.To'Unrestricted_Access);
2403 (Stream : in out Stream_Socket_Stream_Type;
2404 Item : Ada.Streams.Stream_Element_Array)
2407 Stream_Write (Stream.Socket, Item, To => null);
2410 Sockets_Library_Controller_Object : Sockets_Library_Controller;
2411 pragma Unreferenced (Sockets_Library_Controller_Object);
2412 -- The elaboration and finalization of this object perform the required
2413 -- initialization and cleanup actions for the sockets library.