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;
50 with System.Communication; use System.Communication;
51 with System.CRTL; use System.CRTL;
53 package body GNAT.Sockets is
55 package C renames Interfaces.C;
59 ENOERROR : constant := 0;
61 Netdb_Buffer_Size : constant := SOSC.Need_Netdb_Buffer * 1024;
62 -- The network database functions gethostbyname, gethostbyaddr,
63 -- getservbyname and getservbyport can either be guaranteed task safe by
64 -- the operating system, or else return data through a user-provided buffer
65 -- to ensure concurrent uses do not interfere.
67 -- Correspondence tables
69 Levels : constant array (Level_Type) of C.int :=
70 (Socket_Level => SOSC.SOL_SOCKET,
71 IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP,
72 IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP,
73 IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP);
75 Modes : constant array (Mode_Type) of C.int :=
76 (Socket_Stream => SOSC.SOCK_STREAM,
77 Socket_Datagram => SOSC.SOCK_DGRAM);
79 Shutmodes : constant array (Shutmode_Type) of C.int :=
80 (Shut_Read => SOSC.SHUT_RD,
81 Shut_Write => SOSC.SHUT_WR,
82 Shut_Read_Write => SOSC.SHUT_RDWR);
84 Requests : constant array (Request_Name) of C.int :=
85 (Non_Blocking_IO => SOSC.FIONBIO,
86 N_Bytes_To_Read => SOSC.FIONREAD);
88 Options : constant array (Option_Name) of C.int :=
89 (Keep_Alive => SOSC.SO_KEEPALIVE,
90 Reuse_Address => SOSC.SO_REUSEADDR,
91 Broadcast => SOSC.SO_BROADCAST,
92 Send_Buffer => SOSC.SO_SNDBUF,
93 Receive_Buffer => SOSC.SO_RCVBUF,
94 Linger => SOSC.SO_LINGER,
95 Error => SOSC.SO_ERROR,
96 No_Delay => SOSC.TCP_NODELAY,
97 Add_Membership => SOSC.IP_ADD_MEMBERSHIP,
98 Drop_Membership => SOSC.IP_DROP_MEMBERSHIP,
99 Multicast_If => SOSC.IP_MULTICAST_IF,
100 Multicast_TTL => SOSC.IP_MULTICAST_TTL,
101 Multicast_Loop => SOSC.IP_MULTICAST_LOOP,
102 Receive_Packet_Info => SOSC.IP_PKTINFO,
103 Send_Timeout => SOSC.SO_SNDTIMEO,
104 Receive_Timeout => SOSC.SO_RCVTIMEO);
105 -- ??? Note: for OpenSolaris, Receive_Packet_Info should be IP_RECVPKTINFO,
106 -- but for Linux compatibility this constant is the same as IP_PKTINFO.
108 Flags : constant array (0 .. 3) of C.int :=
109 (0 => SOSC.MSG_OOB, -- Process_Out_Of_Band_Data
110 1 => SOSC.MSG_PEEK, -- Peek_At_Incoming_Data
111 2 => SOSC.MSG_WAITALL, -- Wait_For_A_Full_Reception
112 3 => SOSC.MSG_EOR); -- Send_End_Of_Record
114 Socket_Error_Id : constant Exception_Id := Socket_Error'Identity;
115 Host_Error_Id : constant Exception_Id := Host_Error'Identity;
117 Hex_To_Char : constant String (1 .. 16) := "0123456789ABCDEF";
118 -- Use to print in hexadecimal format
120 -----------------------
121 -- Local subprograms --
122 -----------------------
124 function Resolve_Error
125 (Error_Value : Integer;
126 From_Errno : Boolean := True) return Error_Type;
127 -- Associate an enumeration value (error_type) to en error value (errno).
128 -- From_Errno prevents from mixing h_errno with errno.
130 function To_Name (N : String) return Name_Type;
131 function To_String (HN : Name_Type) return String;
132 -- Conversion functions
134 function To_Int (F : Request_Flag_Type) return C.int;
135 -- Return the int value corresponding to the specified flags combination
137 function Set_Forced_Flags (F : C.int) return C.int;
138 -- Return F with the bits from SOSC.MSG_Forced_Flags forced set
140 function Short_To_Network
141 (S : C.unsigned_short) return C.unsigned_short;
142 pragma Inline (Short_To_Network);
143 -- Convert a port number into a network port number
145 function Network_To_Short
146 (S : C.unsigned_short) return C.unsigned_short
147 renames Short_To_Network;
148 -- Symmetric operation
151 (Val : Inet_Addr_VN_Type;
152 Hex : Boolean := False) return String;
153 -- Output an array of inet address components in hex or decimal mode
155 function Is_IP_Address (Name : String) return Boolean;
156 -- Return true when Name is an IP address in standard dot notation
158 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr;
159 procedure To_Inet_Addr
161 Result : out Inet_Addr_Type);
162 -- Conversion functions
164 function To_Host_Entry (E : Hostent) return Host_Entry_Type;
165 -- Conversion function
167 function To_Service_Entry (E : Servent_Access) return Service_Entry_Type;
168 -- Conversion function
170 function To_Timeval (Val : Timeval_Duration) return Timeval;
171 -- Separate Val in seconds and microseconds
173 function To_Duration (Val : Timeval) return Timeval_Duration;
174 -- Reconstruct a Duration value from a Timeval record (seconds and
177 procedure Raise_Socket_Error (Error : Integer);
178 -- Raise Socket_Error with an exception message describing the error code
181 procedure Raise_Host_Error (H_Error : Integer);
182 -- Raise Host_Error exception with message describing error code (note
183 -- hstrerror seems to be obsolete) from h_errno.
185 procedure Narrow (Item : in out Socket_Set_Type);
186 -- Update Last as it may be greater than the real last socket
188 -- Types needed for Datagram_Socket_Stream_Type
190 type Datagram_Socket_Stream_Type is new Root_Stream_Type with record
191 Socket : Socket_Type;
193 From : Sock_Addr_Type;
196 type Datagram_Socket_Stream_Access is
197 access all Datagram_Socket_Stream_Type;
200 (Stream : in out Datagram_Socket_Stream_Type;
201 Item : out Ada.Streams.Stream_Element_Array;
202 Last : out Ada.Streams.Stream_Element_Offset);
205 (Stream : in out Datagram_Socket_Stream_Type;
206 Item : Ada.Streams.Stream_Element_Array);
208 -- Types needed for Stream_Socket_Stream_Type
210 type Stream_Socket_Stream_Type is new Root_Stream_Type with record
211 Socket : Socket_Type;
214 type Stream_Socket_Stream_Access is
215 access all Stream_Socket_Stream_Type;
218 (Stream : in out Stream_Socket_Stream_Type;
219 Item : out Ada.Streams.Stream_Element_Array;
220 Last : out Ada.Streams.Stream_Element_Offset);
223 (Stream : in out Stream_Socket_Stream_Type;
224 Item : Ada.Streams.Stream_Element_Array);
226 procedure Stream_Write
227 (Socket : Socket_Type;
228 Item : Ada.Streams.Stream_Element_Array;
229 To : access Sock_Addr_Type);
230 -- Common implementation for the Write operation of Datagram_Socket_Stream_
231 -- Type and Stream_Socket_Stream_Type.
233 procedure Wait_On_Socket
234 (Socket : Socket_Type;
236 Timeout : Selector_Duration;
237 Selector : access Selector_Type := null;
238 Status : out Selector_Status);
239 -- Common code for variants of socket operations supporting a timeout:
240 -- block in Check_Selector on Socket for at most the indicated timeout.
241 -- If For_Read is True, Socket is added to the read set for this call, else
242 -- it is added to the write set. If no selector is provided, a local one is
243 -- created for this call and destroyed prior to returning.
245 type Sockets_Library_Controller is new Ada.Finalization.Limited_Controlled
247 -- This type is used to generate automatic calls to Initialize and Finalize
248 -- during the elaboration and finalization of this package. A single object
249 -- of this type must exist at library level.
251 function Err_Code_Image (E : Integer) return String;
252 -- Return the value of E surrounded with brackets
254 procedure Initialize (X : in out Sockets_Library_Controller);
255 procedure Finalize (X : in out Sockets_Library_Controller);
257 procedure Normalize_Empty_Socket_Set (S : in out Socket_Set_Type);
258 -- If S is the empty set (detected by Last = No_Socket), make sure its
259 -- fd_set component is actually cleared. Note that the case where it is
260 -- not can occur for an uninitialized Socket_Set_Type object.
262 function Is_Open (S : Selector_Type) return Boolean;
263 -- Return True for an "open" Selector_Type object, i.e. one for which
264 -- Create_Selector has been called and Close_Selector has not been called.
270 function "+" (L, R : Request_Flag_Type) return Request_Flag_Type is
279 procedure Abort_Selector (Selector : Selector_Type) is
283 if not Is_Open (Selector) then
284 raise Program_Error with "closed selector";
287 -- Send one byte to unblock select system call
289 Res := Signalling_Fds.Write (C.int (Selector.W_Sig_Socket));
291 if Res = Failure then
292 Raise_Socket_Error (Socket_Errno);
300 procedure Accept_Socket
301 (Server : Socket_Type;
302 Socket : out Socket_Type;
303 Address : out Sock_Addr_Type)
306 Sin : aliased Sockaddr_In;
307 Len : aliased C.int := Sin'Size / 8;
310 Res := C_Accept (C.int (Server), Sin'Address, Len'Access);
312 if Res = Failure then
313 Raise_Socket_Error (Socket_Errno);
316 Socket := Socket_Type (Res);
318 To_Inet_Addr (Sin.Sin_Addr, Address.Addr);
319 Address.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
326 procedure Accept_Socket
327 (Server : Socket_Type;
328 Socket : out Socket_Type;
329 Address : out Sock_Addr_Type;
330 Timeout : Selector_Duration;
331 Selector : access Selector_Type := null;
332 Status : out Selector_Status)
335 if Selector /= null and then not Is_Open (Selector.all) then
336 raise Program_Error with "closed selector";
339 -- Wait for socket to become available for reading
345 Selector => Selector,
348 -- Accept connection if available
350 if Status = Completed then
351 Accept_Socket (Server, Socket, Address);
362 (E : Host_Entry_Type;
363 N : Positive := 1) return Inet_Addr_Type
366 return E.Addresses (N);
369 ----------------------
370 -- Addresses_Length --
371 ----------------------
373 function Addresses_Length (E : Host_Entry_Type) return Natural is
375 return E.Addresses_Length;
376 end Addresses_Length;
383 (E : Host_Entry_Type;
384 N : Positive := 1) return String
387 return To_String (E.Aliases (N));
395 (S : Service_Entry_Type;
396 N : Positive := 1) return String
399 return To_String (S.Aliases (N));
406 function Aliases_Length (E : Host_Entry_Type) return Natural is
408 return E.Aliases_Length;
415 function Aliases_Length (S : Service_Entry_Type) return Natural is
417 return S.Aliases_Length;
424 procedure Bind_Socket
425 (Socket : Socket_Type;
426 Address : Sock_Addr_Type)
429 Sin : aliased Sockaddr_In;
430 Len : constant C.int := Sin'Size / 8;
431 -- This assumes that Address.Family = Family_Inet???
434 if Address.Family = Family_Inet6 then
435 raise Socket_Error with "IPv6 not supported";
438 Set_Family (Sin.Sin_Family, Address.Family);
439 Set_Address (Sin'Unchecked_Access, To_In_Addr (Address.Addr));
441 (Sin'Unchecked_Access,
442 Short_To_Network (C.unsigned_short (Address.Port)));
444 Res := C_Bind (C.int (Socket), Sin'Address, Len);
446 if Res = Failure then
447 Raise_Socket_Error (Socket_Errno);
455 procedure Check_Selector
456 (Selector : in out Selector_Type;
457 R_Socket_Set : in out Socket_Set_Type;
458 W_Socket_Set : in out Socket_Set_Type;
459 Status : out Selector_Status;
460 Timeout : Selector_Duration := Forever)
462 E_Socket_Set : Socket_Set_Type;
465 (Selector, R_Socket_Set, W_Socket_Set, E_Socket_Set, Status, Timeout);
472 procedure Check_Selector
473 (Selector : in out Selector_Type;
474 R_Socket_Set : in out Socket_Set_Type;
475 W_Socket_Set : in out Socket_Set_Type;
476 E_Socket_Set : in out Socket_Set_Type;
477 Status : out Selector_Status;
478 Timeout : Selector_Duration := Forever)
482 RSig : constant Socket_Type := Selector.R_Sig_Socket;
483 TVal : aliased Timeval;
484 TPtr : Timeval_Access;
487 if not Is_Open (Selector) then
488 raise Program_Error with "closed selector";
493 -- No timeout or Forever is indicated by a null timeval pointer
495 if Timeout = Forever then
498 TVal := To_Timeval (Timeout);
499 TPtr := TVal'Unchecked_Access;
502 -- Add read signalling socket
504 Set (R_Socket_Set, RSig);
506 Last := C.int'Max (C.int'Max (C.int (R_Socket_Set.Last),
507 C.int (W_Socket_Set.Last)),
508 C.int (E_Socket_Set.Last));
510 -- Zero out fd_set for empty Socket_Set_Type objects
512 Normalize_Empty_Socket_Set (R_Socket_Set);
513 Normalize_Empty_Socket_Set (W_Socket_Set);
514 Normalize_Empty_Socket_Set (E_Socket_Set);
519 R_Socket_Set.Set'Access,
520 W_Socket_Set.Set'Access,
521 E_Socket_Set.Set'Access,
524 if Res = Failure then
525 Raise_Socket_Error (Socket_Errno);
528 -- If Select was resumed because of read signalling socket, read this
529 -- data and remove socket from set.
531 if Is_Set (R_Socket_Set, RSig) then
532 Clear (R_Socket_Set, RSig);
534 Res := Signalling_Fds.Read (C.int (RSig));
536 if Res = Failure then
537 Raise_Socket_Error (Socket_Errno);
546 -- Update socket sets in regard to their new contents
548 Narrow (R_Socket_Set);
549 Narrow (W_Socket_Set);
550 Narrow (E_Socket_Set);
558 (Item : in out Socket_Set_Type;
559 Socket : Socket_Type)
561 Last : aliased C.int := C.int (Item.Last);
563 if Item.Last /= No_Socket then
564 Remove_Socket_From_Set (Item.Set'Access, C.int (Socket));
565 Last_Socket_In_Set (Item.Set'Access, Last'Unchecked_Access);
566 Item.Last := Socket_Type (Last);
574 procedure Close_Selector (Selector : in out Selector_Type) is
576 if not Is_Open (Selector) then
578 -- Selector already in closed state: nothing to do
583 -- Close the signalling file descriptors used internally for the
584 -- implementation of Abort_Selector.
586 Signalling_Fds.Close (C.int (Selector.R_Sig_Socket));
587 Signalling_Fds.Close (C.int (Selector.W_Sig_Socket));
589 -- Reset R_Sig_Socket and W_Sig_Socket to No_Socket to ensure that any
590 -- (erroneous) subsequent attempt to use this selector properly fails.
592 Selector.R_Sig_Socket := No_Socket;
593 Selector.W_Sig_Socket := No_Socket;
600 procedure Close_Socket (Socket : Socket_Type) is
604 Res := C_Close (C.int (Socket));
606 if Res = Failure then
607 Raise_Socket_Error (Socket_Errno);
615 procedure Connect_Socket
616 (Socket : Socket_Type;
617 Server : Sock_Addr_Type)
620 Sin : aliased Sockaddr_In;
621 Len : constant C.int := Sin'Size / 8;
624 if Server.Family = Family_Inet6 then
625 raise Socket_Error with "IPv6 not supported";
628 Set_Family (Sin.Sin_Family, Server.Family);
629 Set_Address (Sin'Unchecked_Access, To_In_Addr (Server.Addr));
631 (Sin'Unchecked_Access,
632 Short_To_Network (C.unsigned_short (Server.Port)));
634 Res := C_Connect (C.int (Socket), Sin'Address, Len);
636 if Res = Failure then
637 Raise_Socket_Error (Socket_Errno);
645 procedure Connect_Socket
646 (Socket : Socket_Type;
647 Server : Sock_Addr_Type;
648 Timeout : Selector_Duration;
649 Selector : access Selector_Type := null;
650 Status : out Selector_Status)
653 -- Used to set Socket to non-blocking I/O
656 if Selector /= null and then not Is_Open (Selector.all) then
657 raise Program_Error with "closed selector";
660 -- Set the socket to non-blocking I/O
662 Req := (Name => Non_Blocking_IO, Enabled => True);
663 Control_Socket (Socket, Request => Req);
665 -- Start operation (non-blocking), will raise Socket_Error with
669 Connect_Socket (Socket, Server);
671 when E : Socket_Error =>
672 if Resolve_Exception (E) = Operation_Now_In_Progress then
679 -- Wait for socket to become available for writing
685 Selector => Selector,
688 -- Reset the socket to blocking I/O
690 Req := (Name => Non_Blocking_IO, Enabled => False);
691 Control_Socket (Socket, Request => Req);
698 procedure Control_Socket
699 (Socket : Socket_Type;
700 Request : in out Request_Type)
707 when Non_Blocking_IO =>
708 Arg := C.int (Boolean'Pos (Request.Enabled));
710 when N_Bytes_To_Read =>
715 (C.int (Socket), Requests (Request.Name), Arg'Unchecked_Access);
717 if Res = Failure then
718 Raise_Socket_Error (Socket_Errno);
722 when Non_Blocking_IO =>
725 when N_Bytes_To_Read =>
726 Request.Size := Natural (Arg);
735 (Source : Socket_Set_Type;
736 Target : out Socket_Set_Type)
742 ---------------------
743 -- Create_Selector --
744 ---------------------
746 procedure Create_Selector (Selector : out Selector_Type) is
747 Two_Fds : aliased Fd_Pair;
751 if Is_Open (Selector) then
752 -- Raise exception to prevent socket descriptor leak
754 raise Program_Error with "selector already open";
757 -- We open two signalling file descriptors. One of them is used to send
758 -- data to the other, which is included in a C_Select socket set. The
759 -- communication is used to force a call to C_Select to complete, and
760 -- the waiting task to resume its execution.
762 Res := Signalling_Fds.Create (Two_Fds'Access);
764 if Res = Failure then
765 Raise_Socket_Error (Socket_Errno);
768 Selector.R_Sig_Socket := Socket_Type (Two_Fds (Read_End));
769 Selector.W_Sig_Socket := Socket_Type (Two_Fds (Write_End));
776 procedure Create_Socket
777 (Socket : out Socket_Type;
778 Family : Family_Type := Family_Inet;
779 Mode : Mode_Type := Socket_Stream)
784 Res := C_Socket (Families (Family), Modes (Mode), 0);
786 if Res = Failure then
787 Raise_Socket_Error (Socket_Errno);
790 Socket := Socket_Type (Res);
797 procedure Empty (Item : out Socket_Set_Type) is
799 Reset_Socket_Set (Item.Set'Access);
800 Item.Last := No_Socket;
807 function Err_Code_Image (E : Integer) return String is
808 Msg : String := E'Img & "] ";
810 Msg (Msg'First) := '[';
818 procedure Finalize (X : in out Sockets_Library_Controller) is
819 pragma Unreferenced (X);
822 -- Finalization operation for the GNAT.Sockets package
831 procedure Finalize is
833 -- This is a dummy placeholder for an obsolete API.
834 -- The real finalization actions are in Initialize primitive operation
835 -- of Sockets_Library_Controller.
845 (Item : in out Socket_Set_Type;
846 Socket : out Socket_Type)
849 L : aliased C.int := C.int (Item.Last);
852 if Item.Last /= No_Socket then
854 (Item.Set'Access, Last => L'Access, Socket => S'Access);
855 Item.Last := Socket_Type (L);
856 Socket := Socket_Type (S);
867 (Stream : not null Stream_Access) return Sock_Addr_Type
870 if Stream.all in Datagram_Socket_Stream_Type then
871 return Datagram_Socket_Stream_Type (Stream.all).From;
873 return Get_Peer_Name (Stream_Socket_Stream_Type (Stream.all).Socket);
877 -------------------------
878 -- Get_Host_By_Address --
879 -------------------------
881 function Get_Host_By_Address
882 (Address : Inet_Addr_Type;
883 Family : Family_Type := Family_Inet) return Host_Entry_Type
885 pragma Unreferenced (Family);
887 HA : aliased In_Addr := To_In_Addr (Address);
888 Buflen : constant C.int := Netdb_Buffer_Size;
889 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
890 Res : aliased Hostent;
894 if Safe_Gethostbyaddr (HA'Address, HA'Size / 8, SOSC.AF_INET,
895 Res'Access, Buf'Address, Buflen, Err'Access) /= 0
897 Raise_Host_Error (Integer (Err));
900 return To_Host_Entry (Res);
901 end Get_Host_By_Address;
903 ----------------------
904 -- Get_Host_By_Name --
905 ----------------------
907 function Get_Host_By_Name (Name : String) return Host_Entry_Type is
909 -- Detect IP address name and redirect to Inet_Addr
911 if Is_IP_Address (Name) then
912 return Get_Host_By_Address (Inet_Addr (Name));
916 HN : constant C.char_array := C.To_C (Name);
917 Buflen : constant C.int := Netdb_Buffer_Size;
918 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
919 Res : aliased Hostent;
923 if Safe_Gethostbyname
924 (HN, Res'Access, Buf'Address, Buflen, Err'Access) /= 0
926 Raise_Host_Error (Integer (Err));
929 return To_Host_Entry (Res);
931 end Get_Host_By_Name;
937 function Get_Peer_Name (Socket : Socket_Type) return Sock_Addr_Type is
938 Sin : aliased Sockaddr_In;
939 Len : aliased C.int := Sin'Size / 8;
940 Res : Sock_Addr_Type (Family_Inet);
943 if C_Getpeername (C.int (Socket), Sin'Address, Len'Access) = Failure then
944 Raise_Socket_Error (Socket_Errno);
947 To_Inet_Addr (Sin.Sin_Addr, Res.Addr);
948 Res.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
953 -------------------------
954 -- Get_Service_By_Name --
955 -------------------------
957 function Get_Service_By_Name
959 Protocol : String) return Service_Entry_Type
961 SN : constant C.char_array := C.To_C (Name);
962 SP : constant C.char_array := C.To_C (Protocol);
963 Buflen : constant C.int := Netdb_Buffer_Size;
964 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
965 Res : aliased Servent;
968 if Safe_Getservbyname (SN, SP, Res'Access, Buf'Address, Buflen) /= 0 then
969 raise Service_Error with "Service not found";
972 -- Translate from the C format to the API format
974 return To_Service_Entry (Res'Unchecked_Access);
975 end Get_Service_By_Name;
977 -------------------------
978 -- Get_Service_By_Port --
979 -------------------------
981 function Get_Service_By_Port
983 Protocol : String) return Service_Entry_Type
985 SP : constant C.char_array := C.To_C (Protocol);
986 Buflen : constant C.int := Netdb_Buffer_Size;
987 Buf : aliased C.char_array (1 .. Netdb_Buffer_Size);
988 Res : aliased Servent;
991 if Safe_Getservbyport
992 (C.int (Short_To_Network (C.unsigned_short (Port))), SP,
993 Res'Access, Buf'Address, Buflen) /= 0
995 raise Service_Error with "Service not found";
998 -- Translate from the C format to the API format
1000 return To_Service_Entry (Res'Unchecked_Access);
1001 end Get_Service_By_Port;
1003 ---------------------
1004 -- Get_Socket_Name --
1005 ---------------------
1007 function Get_Socket_Name
1008 (Socket : Socket_Type) return Sock_Addr_Type
1010 Sin : aliased Sockaddr_In;
1011 Len : aliased C.int := Sin'Size / 8;
1013 Addr : Sock_Addr_Type := No_Sock_Addr;
1016 Res := C_Getsockname (C.int (Socket), Sin'Address, Len'Access);
1018 if Res /= Failure then
1019 To_Inet_Addr (Sin.Sin_Addr, Addr.Addr);
1020 Addr.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
1024 end Get_Socket_Name;
1026 -----------------------
1027 -- Get_Socket_Option --
1028 -----------------------
1030 function Get_Socket_Option
1031 (Socket : Socket_Type;
1032 Level : Level_Type := Socket_Level;
1033 Name : Option_Name) return Option_Type
1035 use type C.unsigned_char;
1037 V8 : aliased Two_Ints;
1039 V1 : aliased C.unsigned_char;
1040 VT : aliased Timeval;
1041 Len : aliased C.int;
1042 Add : System.Address;
1044 Opt : Option_Type (Name);
1048 when Multicast_Loop |
1050 Receive_Packet_Info =>
1085 if Res = Failure then
1086 Raise_Socket_Error (Socket_Errno);
1094 Opt.Enabled := (V4 /= 0);
1097 Opt.Enabled := (V8 (V8'First) /= 0);
1098 Opt.Seconds := Natural (V8 (V8'Last));
1102 Opt.Size := Natural (V4);
1105 Opt.Error := Resolve_Error (Integer (V4));
1107 when Add_Membership |
1109 To_Inet_Addr (To_In_Addr (V8 (V8'First)), Opt.Multicast_Address);
1110 To_Inet_Addr (To_In_Addr (V8 (V8'Last)), Opt.Local_Interface);
1112 when Multicast_If =>
1113 To_Inet_Addr (To_In_Addr (V4), Opt.Outgoing_If);
1115 when Multicast_TTL =>
1116 Opt.Time_To_Live := Integer (V1);
1118 when Multicast_Loop |
1119 Receive_Packet_Info =>
1120 Opt.Enabled := (V1 /= 0);
1124 Opt.Timeout := To_Duration (VT);
1128 end Get_Socket_Option;
1134 function Host_Name return String is
1135 Name : aliased C.char_array (1 .. 64);
1139 Res := C_Gethostname (Name'Address, Name'Length);
1141 if Res = Failure then
1142 Raise_Socket_Error (Socket_Errno);
1145 return C.To_Ada (Name);
1153 (Val : Inet_Addr_VN_Type;
1154 Hex : Boolean := False) return String
1156 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
1157 -- has at most a length of 3 plus one '.' character.
1159 Buffer : String (1 .. 4 * Val'Length);
1160 Length : Natural := 1;
1161 Separator : Character;
1163 procedure Img10 (V : Inet_Addr_Comp_Type);
1164 -- Append to Buffer image of V in decimal format
1166 procedure Img16 (V : Inet_Addr_Comp_Type);
1167 -- Append to Buffer image of V in hexadecimal format
1173 procedure Img10 (V : Inet_Addr_Comp_Type) is
1174 Img : constant String := V'Img;
1175 Len : constant Natural := Img'Length - 1;
1177 Buffer (Length .. Length + Len - 1) := Img (2 .. Img'Last);
1178 Length := Length + Len;
1185 procedure Img16 (V : Inet_Addr_Comp_Type) is
1187 Buffer (Length) := Hex_To_Char (Natural (V / 16) + 1);
1188 Buffer (Length + 1) := Hex_To_Char (Natural (V mod 16) + 1);
1189 Length := Length + 2;
1192 -- Start of processing for Image
1195 Separator := (if Hex then ':' else '.');
1197 for J in Val'Range loop
1204 if J /= Val'Last then
1205 Buffer (Length) := Separator;
1206 Length := Length + 1;
1210 return Buffer (1 .. Length - 1);
1217 function Image (Value : Inet_Addr_Type) return String is
1219 if Value.Family = Family_Inet then
1220 return Image (Inet_Addr_VN_Type (Value.Sin_V4), Hex => False);
1222 return Image (Inet_Addr_VN_Type (Value.Sin_V6), Hex => True);
1230 function Image (Value : Sock_Addr_Type) return String is
1231 Port : constant String := Value.Port'Img;
1233 return Image (Value.Addr) & ':' & Port (2 .. Port'Last);
1240 function Image (Socket : Socket_Type) return String is
1249 function Image (Item : Socket_Set_Type) return String is
1250 Socket_Set : Socket_Set_Type := Item;
1254 Last_Img : constant String := Socket_Set.Last'Img;
1256 (1 .. (Integer (Socket_Set.Last) + 1) * Last_Img'Length);
1257 Index : Positive := 1;
1258 Socket : Socket_Type;
1261 while not Is_Empty (Socket_Set) loop
1262 Get (Socket_Set, Socket);
1265 Socket_Img : constant String := Socket'Img;
1267 Buffer (Index .. Index + Socket_Img'Length - 1) := Socket_Img;
1268 Index := Index + Socket_Img'Length;
1272 return "[" & Last_Img & "]" & Buffer (1 .. Index - 1);
1280 function Inet_Addr (Image : String) return Inet_Addr_Type is
1282 use Interfaces.C.Strings;
1284 Img : aliased char_array := To_C (Image);
1285 Cp : constant chars_ptr := To_Chars_Ptr (Img'Unchecked_Access);
1286 Addr : aliased C.int;
1288 Result : Inet_Addr_Type;
1291 -- Special case for an empty Image as on some platforms (e.g. Windows)
1292 -- calling Inet_Addr("") will not return an error.
1295 Raise_Socket_Error (SOSC.EINVAL);
1298 Res := Inet_Pton (SOSC.AF_INET, Cp, Addr'Address);
1301 Raise_Socket_Error (Socket_Errno);
1304 Raise_Socket_Error (SOSC.EINVAL);
1307 To_Inet_Addr (To_In_Addr (Addr), Result);
1315 procedure Initialize (X : in out Sockets_Library_Controller) is
1316 pragma Unreferenced (X);
1326 procedure Initialize (Process_Blocking_IO : Boolean) is
1327 Expected : constant Boolean := not SOSC.Thread_Blocking_IO;
1330 if Process_Blocking_IO /= Expected then
1331 raise Socket_Error with
1332 "incorrect Process_Blocking_IO setting, expected " & Expected'Img;
1335 -- This is a dummy placeholder for an obsolete API
1337 -- Real initialization actions are in Initialize primitive operation
1338 -- of Sockets_Library_Controller.
1347 procedure Initialize is
1349 -- This is a dummy placeholder for an obsolete API
1351 -- Real initialization actions are in Initialize primitive operation
1352 -- of Sockets_Library_Controller.
1361 function Is_Empty (Item : Socket_Set_Type) return Boolean is
1363 return Item.Last = No_Socket;
1370 function Is_IP_Address (Name : String) return Boolean is
1372 for J in Name'Range loop
1374 and then Name (J) not in '0' .. '9'
1387 function Is_Open (S : Selector_Type) return Boolean is
1389 -- Either both controlling socket descriptors are valid (case of an
1390 -- open selector) or neither (case of a closed selector).
1392 pragma Assert ((S.R_Sig_Socket /= No_Socket)
1394 (S.W_Sig_Socket /= No_Socket));
1396 return S.R_Sig_Socket /= No_Socket;
1404 (Item : Socket_Set_Type;
1405 Socket : Socket_Type) return Boolean
1408 return Item.Last /= No_Socket
1409 and then Socket <= Item.Last
1410 and then Is_Socket_In_Set (Item.Set'Access, C.int (Socket)) /= 0;
1417 procedure Listen_Socket
1418 (Socket : Socket_Type;
1419 Length : Natural := 15)
1421 Res : constant C.int := C_Listen (C.int (Socket), C.int (Length));
1423 if Res = Failure then
1424 Raise_Socket_Error (Socket_Errno);
1432 procedure Narrow (Item : in out Socket_Set_Type) is
1433 Last : aliased C.int := C.int (Item.Last);
1435 if Item.Last /= No_Socket then
1436 Last_Socket_In_Set (Item.Set'Access, Last'Unchecked_Access);
1437 Item.Last := Socket_Type (Last);
1441 --------------------------------
1442 -- Normalize_Empty_Socket_Set --
1443 --------------------------------
1445 procedure Normalize_Empty_Socket_Set (S : in out Socket_Set_Type) is
1447 if S.Last = No_Socket then
1448 Reset_Socket_Set (S.Set'Access);
1450 end Normalize_Empty_Socket_Set;
1456 function Official_Name (E : Host_Entry_Type) return String is
1458 return To_String (E.Official);
1465 function Official_Name (S : Service_Entry_Type) return String is
1467 return To_String (S.Official);
1470 --------------------
1471 -- Wait_On_Socket --
1472 --------------------
1474 procedure Wait_On_Socket
1475 (Socket : Socket_Type;
1477 Timeout : Selector_Duration;
1478 Selector : access Selector_Type := null;
1479 Status : out Selector_Status)
1481 type Local_Selector_Access is access Selector_Type;
1482 for Local_Selector_Access'Storage_Size use Selector_Type'Size;
1484 S : Selector_Access;
1485 -- Selector to use for waiting
1487 R_Fd_Set : Socket_Set_Type;
1488 W_Fd_Set : Socket_Set_Type;
1491 -- Create selector if not provided by the user
1493 if Selector = null then
1495 Local_S : constant Local_Selector_Access := new Selector_Type;
1497 S := Local_S.all'Unchecked_Access;
1498 Create_Selector (S.all);
1502 S := Selector.all'Access;
1506 Set (R_Fd_Set, Socket);
1508 Set (W_Fd_Set, Socket);
1511 Check_Selector (S.all, R_Fd_Set, W_Fd_Set, Status, Timeout);
1513 if Selector = null then
1514 Close_Selector (S.all);
1522 function Port_Number (S : Service_Entry_Type) return Port_Type is
1531 function Protocol_Name (S : Service_Entry_Type) return String is
1533 return To_String (S.Protocol);
1536 ----------------------
1537 -- Raise_Host_Error --
1538 ----------------------
1540 procedure Raise_Host_Error (H_Error : Integer) is
1542 raise Host_Error with
1543 Err_Code_Image (H_Error)
1544 & C.Strings.Value (Host_Error_Messages.Host_Error_Message (H_Error));
1545 end Raise_Host_Error;
1547 ------------------------
1548 -- Raise_Socket_Error --
1549 ------------------------
1551 procedure Raise_Socket_Error (Error : Integer) is
1552 use type C.Strings.chars_ptr;
1554 raise Socket_Error with
1555 Err_Code_Image (Error)
1556 & C.Strings.Value (Socket_Error_Message (Error));
1557 end Raise_Socket_Error;
1564 (Stream : in out Datagram_Socket_Stream_Type;
1565 Item : out Ada.Streams.Stream_Element_Array;
1566 Last : out Ada.Streams.Stream_Element_Offset)
1568 First : Ada.Streams.Stream_Element_Offset := Item'First;
1569 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1570 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1576 Item (First .. Max),
1582 -- Exit when all or zero data received. Zero means that the socket
1585 exit when Index < First or else Index = Max;
1596 (Stream : in out Stream_Socket_Stream_Type;
1597 Item : out Ada.Streams.Stream_Element_Array;
1598 Last : out Ada.Streams.Stream_Element_Offset)
1600 pragma Warnings (Off, Stream);
1602 First : Ada.Streams.Stream_Element_Offset := Item'First;
1603 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1604 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1608 Receive_Socket (Stream.Socket, Item (First .. Max), Index);
1611 -- Exit when all or zero data received. Zero means that the socket
1614 exit when Index < First or else Index = Max;
1620 --------------------
1621 -- Receive_Socket --
1622 --------------------
1624 procedure Receive_Socket
1625 (Socket : Socket_Type;
1626 Item : out Ada.Streams.Stream_Element_Array;
1627 Last : out Ada.Streams.Stream_Element_Offset;
1628 Flags : Request_Flag_Type := No_Request_Flag)
1634 C_Recv (C.int (Socket), Item'Address, Item'Length, To_Int (Flags));
1636 if Res = Failure then
1637 Raise_Socket_Error (Socket_Errno);
1640 Last := Last_Index (First => Item'First, Count => size_t (Res));
1643 --------------------
1644 -- Receive_Socket --
1645 --------------------
1647 procedure Receive_Socket
1648 (Socket : Socket_Type;
1649 Item : out Ada.Streams.Stream_Element_Array;
1650 Last : out Ada.Streams.Stream_Element_Offset;
1651 From : out Sock_Addr_Type;
1652 Flags : Request_Flag_Type := No_Request_Flag)
1655 Sin : aliased Sockaddr_In;
1656 Len : aliased C.int := Sin'Size / 8;
1668 if Res = Failure then
1669 Raise_Socket_Error (Socket_Errno);
1672 Last := Last_Index (First => Item'First, Count => size_t (Res));
1674 To_Inet_Addr (Sin.Sin_Addr, From.Addr);
1675 From.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
1678 --------------------
1679 -- Receive_Vector --
1680 --------------------
1682 procedure Receive_Vector
1683 (Socket : Socket_Type;
1684 Vector : Vector_Type;
1685 Count : out Ada.Streams.Stream_Element_Count;
1686 Flags : Request_Flag_Type := No_Request_Flag)
1691 (Msg_Name => System.Null_Address,
1693 Msg_Iov => Vector'Address,
1695 -- recvmsg(2) returns EMSGSIZE on Linux (and probably on other
1696 -- platforms) when the supplied vector is longer than IOV_MAX,
1697 -- so use minimum of the two lengths.
1699 Msg_Iovlen => SOSC.Msg_Iovlen_T'Min
1700 (Vector'Length, SOSC.IOV_MAX),
1702 Msg_Control => System.Null_Address,
1703 Msg_Controllen => 0,
1713 if Res = ssize_t (Failure) then
1714 Raise_Socket_Error (Socket_Errno);
1717 Count := Ada.Streams.Stream_Element_Count (Res);
1724 function Resolve_Error
1725 (Error_Value : Integer;
1726 From_Errno : Boolean := True) return Error_Type
1728 use GNAT.Sockets.SOSC;
1731 if not From_Errno then
1733 when SOSC.HOST_NOT_FOUND => return Unknown_Host;
1734 when SOSC.TRY_AGAIN => return Host_Name_Lookup_Failure;
1735 when SOSC.NO_RECOVERY => return Non_Recoverable_Error;
1736 when SOSC.NO_DATA => return Unknown_Server_Error;
1737 when others => return Cannot_Resolve_Error;
1741 -- Special case: EAGAIN may be the same value as EWOULDBLOCK, so we
1742 -- can't include it in the case statement below.
1744 pragma Warnings (Off);
1745 -- Condition "EAGAIN /= EWOULDBLOCK" is known at compile time
1747 if EAGAIN /= EWOULDBLOCK and then Error_Value = EAGAIN then
1748 return Resource_Temporarily_Unavailable;
1751 pragma Warnings (On);
1753 -- This is not a case statement because if a particular error
1754 -- number constant is not defined, s-oscons-tmplt.c defines
1755 -- it to -1. If multiple constants are not defined, they
1756 -- would each be -1 and result in a "duplicate value in case" error.
1757 if Error_Value = ENOERROR then
1759 elsif Error_Value = EACCES then
1760 return Permission_Denied;
1761 elsif Error_Value = EADDRINUSE then
1762 return Address_Already_In_Use;
1763 elsif Error_Value = EADDRNOTAVAIL then
1764 return Cannot_Assign_Requested_Address;
1765 elsif Error_Value = EAFNOSUPPORT then
1766 return Address_Family_Not_Supported_By_Protocol;
1767 elsif Error_Value = EALREADY then
1768 return Operation_Already_In_Progress;
1769 elsif Error_Value = EBADF then
1770 return Bad_File_Descriptor;
1771 elsif Error_Value = ECONNABORTED then
1772 return Software_Caused_Connection_Abort;
1773 elsif Error_Value = ECONNREFUSED then
1774 return Connection_Refused;
1775 elsif Error_Value = ECONNRESET then
1776 return Connection_Reset_By_Peer;
1777 elsif Error_Value = EDESTADDRREQ then
1778 return Destination_Address_Required;
1779 elsif Error_Value = EFAULT then
1781 elsif Error_Value = EHOSTDOWN then
1782 return Host_Is_Down;
1783 elsif Error_Value = EHOSTUNREACH then
1784 return No_Route_To_Host;
1785 elsif Error_Value = EINPROGRESS then
1786 return Operation_Now_In_Progress;
1787 elsif Error_Value = EINTR then
1788 return Interrupted_System_Call;
1789 elsif Error_Value = EINVAL then
1790 return Invalid_Argument;
1791 elsif Error_Value = EIO then
1792 return Input_Output_Error;
1793 elsif Error_Value = EISCONN then
1794 return Transport_Endpoint_Already_Connected;
1795 elsif Error_Value = ELOOP then
1796 return Too_Many_Symbolic_Links;
1797 elsif Error_Value = EMFILE then
1798 return Too_Many_Open_Files;
1799 elsif Error_Value = EMSGSIZE then
1800 return Message_Too_Long;
1801 elsif Error_Value = ENAMETOOLONG then
1802 return File_Name_Too_Long;
1803 elsif Error_Value = ENETDOWN then
1804 return Network_Is_Down;
1805 elsif Error_Value = ENETRESET then
1806 return Network_Dropped_Connection_Because_Of_Reset;
1807 elsif Error_Value = ENETUNREACH then
1808 return Network_Is_Unreachable;
1809 elsif Error_Value = ENOBUFS then
1810 return No_Buffer_Space_Available;
1811 elsif Error_Value = ENOPROTOOPT then
1812 return Protocol_Not_Available;
1813 elsif Error_Value = ENOTCONN then
1814 return Transport_Endpoint_Not_Connected;
1815 elsif Error_Value = ENOTSOCK then
1816 return Socket_Operation_On_Non_Socket;
1817 elsif Error_Value = EOPNOTSUPP then
1818 return Operation_Not_Supported;
1819 elsif Error_Value = EPFNOSUPPORT then
1820 return Protocol_Family_Not_Supported;
1821 elsif Error_Value = EPIPE then
1823 elsif Error_Value = EPROTONOSUPPORT then
1824 return Protocol_Not_Supported;
1825 elsif Error_Value = EPROTOTYPE then
1826 return Protocol_Wrong_Type_For_Socket;
1827 elsif Error_Value = ESHUTDOWN then
1828 return Cannot_Send_After_Transport_Endpoint_Shutdown;
1829 elsif Error_Value = ESOCKTNOSUPPORT then
1830 return Socket_Type_Not_Supported;
1831 elsif Error_Value = ETIMEDOUT then
1832 return Connection_Timed_Out;
1833 elsif Error_Value = ETOOMANYREFS then
1834 return Too_Many_References;
1835 elsif Error_Value = EWOULDBLOCK then
1836 return Resource_Temporarily_Unavailable;
1838 return Cannot_Resolve_Error;
1842 -----------------------
1843 -- Resolve_Exception --
1844 -----------------------
1846 function Resolve_Exception
1847 (Occurrence : Exception_Occurrence) return Error_Type
1849 Id : constant Exception_Id := Exception_Identity (Occurrence);
1850 Msg : constant String := Exception_Message (Occurrence);
1857 while First <= Msg'Last
1858 and then Msg (First) not in '0' .. '9'
1863 if First > Msg'Last then
1864 return Cannot_Resolve_Error;
1868 while Last < Msg'Last
1869 and then Msg (Last + 1) in '0' .. '9'
1874 Val := Integer'Value (Msg (First .. Last));
1876 if Id = Socket_Error_Id then
1877 return Resolve_Error (Val);
1879 elsif Id = Host_Error_Id then
1880 return Resolve_Error (Val, False);
1883 return Cannot_Resolve_Error;
1885 end Resolve_Exception;
1891 procedure Send_Socket
1892 (Socket : Socket_Type;
1893 Item : Ada.Streams.Stream_Element_Array;
1894 Last : out Ada.Streams.Stream_Element_Offset;
1895 Flags : Request_Flag_Type := No_Request_Flag)
1898 Send_Socket (Socket, Item, Last, To => null, Flags => Flags);
1905 procedure Send_Socket
1906 (Socket : Socket_Type;
1907 Item : Ada.Streams.Stream_Element_Array;
1908 Last : out Ada.Streams.Stream_Element_Offset;
1909 To : Sock_Addr_Type;
1910 Flags : Request_Flag_Type := No_Request_Flag)
1914 (Socket, Item, Last, To => To'Unrestricted_Access, Flags => Flags);
1921 procedure Send_Socket
1922 (Socket : Socket_Type;
1923 Item : Ada.Streams.Stream_Element_Array;
1924 Last : out Ada.Streams.Stream_Element_Offset;
1925 To : access Sock_Addr_Type;
1926 Flags : Request_Flag_Type := No_Request_Flag)
1930 Sin : aliased Sockaddr_In;
1931 C_To : System.Address;
1936 Set_Family (Sin.Sin_Family, To.Family);
1937 Set_Address (Sin'Unchecked_Access, To_In_Addr (To.Addr));
1939 (Sin'Unchecked_Access,
1940 Short_To_Network (C.unsigned_short (To.Port)));
1941 C_To := Sin'Address;
1942 Len := Sin'Size / 8;
1945 C_To := System.Null_Address;
1953 Set_Forced_Flags (To_Int (Flags)),
1957 if Res = Failure then
1958 Raise_Socket_Error (Socket_Errno);
1961 Last := Last_Index (First => Item'First, Count => size_t (Res));
1968 procedure Send_Vector
1969 (Socket : Socket_Type;
1970 Vector : Vector_Type;
1971 Count : out Ada.Streams.Stream_Element_Count;
1972 Flags : Request_Flag_Type := No_Request_Flag)
1978 Iov_Count : SOSC.Msg_Iovlen_T;
1979 This_Iov_Count : SOSC.Msg_Iovlen_T;
1985 while Iov_Count < Vector'Length loop
1987 pragma Warnings (Off);
1988 -- Following test may be compile time known on some targets
1991 (if Vector'Length - Iov_Count > SOSC.IOV_MAX
1993 else Vector'Length - Iov_Count);
1995 pragma Warnings (On);
1998 (Msg_Name => System.Null_Address,
2001 (Vector'First + Integer (Iov_Count))'Address,
2002 Msg_Iovlen => This_Iov_Count,
2003 Msg_Control => System.Null_Address,
2004 Msg_Controllen => 0,
2011 Set_Forced_Flags (To_Int (Flags)));
2013 if Res = ssize_t (Failure) then
2014 Raise_Socket_Error (Socket_Errno);
2017 Count := Count + Ada.Streams.Stream_Element_Count (Res);
2018 Iov_Count := Iov_Count + This_Iov_Count;
2026 procedure Set (Item : in out Socket_Set_Type; Socket : Socket_Type) is
2028 if Item.Last = No_Socket then
2030 -- Uninitialized socket set, make sure it is properly zeroed out
2032 Reset_Socket_Set (Item.Set'Access);
2033 Item.Last := Socket;
2035 elsif Item.Last < Socket then
2036 Item.Last := Socket;
2039 Insert_Socket_In_Set (Item.Set'Access, C.int (Socket));
2042 ----------------------
2043 -- Set_Forced_Flags --
2044 ----------------------
2046 function Set_Forced_Flags (F : C.int) return C.int is
2047 use type C.unsigned;
2048 function To_unsigned is
2049 new Ada.Unchecked_Conversion (C.int, C.unsigned);
2051 new Ada.Unchecked_Conversion (C.unsigned, C.int);
2053 return To_int (To_unsigned (F) or SOSC.MSG_Forced_Flags);
2054 end Set_Forced_Flags;
2056 -----------------------
2057 -- Set_Socket_Option --
2058 -----------------------
2060 procedure Set_Socket_Option
2061 (Socket : Socket_Type;
2062 Level : Level_Type := Socket_Level;
2063 Option : Option_Type)
2065 V8 : aliased Two_Ints;
2067 V1 : aliased C.unsigned_char;
2068 VT : aliased Timeval;
2070 Add : System.Address := Null_Address;
2079 V4 := C.int (Boolean'Pos (Option.Enabled));
2084 V8 (V8'First) := C.int (Boolean'Pos (Option.Enabled));
2085 V8 (V8'Last) := C.int (Option.Seconds);
2091 V4 := C.int (Option.Size);
2096 V4 := C.int (Boolean'Pos (True));
2100 when Add_Membership |
2102 V8 (V8'First) := To_Int (To_In_Addr (Option.Multicast_Address));
2103 V8 (V8'Last) := To_Int (To_In_Addr (Option.Local_Interface));
2107 when Multicast_If =>
2108 V4 := To_Int (To_In_Addr (Option.Outgoing_If));
2112 when Multicast_TTL =>
2113 V1 := C.unsigned_char (Option.Time_To_Live);
2117 when Multicast_Loop |
2118 Receive_Packet_Info =>
2119 V1 := C.unsigned_char (Boolean'Pos (Option.Enabled));
2125 VT := To_Timeval (Option.Timeout);
2134 Options (Option.Name),
2137 if Res = Failure then
2138 Raise_Socket_Error (Socket_Errno);
2140 end Set_Socket_Option;
2142 ----------------------
2143 -- Short_To_Network --
2144 ----------------------
2146 function Short_To_Network (S : C.unsigned_short) return C.unsigned_short is
2147 use type C.unsigned_short;
2150 -- Big-endian case. No conversion needed. On these platforms,
2151 -- htons() defaults to a null procedure.
2153 pragma Warnings (Off);
2154 -- Since the test can generate "always True/False" warning
2156 if Default_Bit_Order = High_Order_First then
2159 pragma Warnings (On);
2161 -- Little-endian case. We must swap the high and low bytes of this
2162 -- short to make the port number network compliant.
2165 return (S / 256) + (S mod 256) * 256;
2167 end Short_To_Network;
2169 ---------------------
2170 -- Shutdown_Socket --
2171 ---------------------
2173 procedure Shutdown_Socket
2174 (Socket : Socket_Type;
2175 How : Shutmode_Type := Shut_Read_Write)
2180 Res := C_Shutdown (C.int (Socket), Shutmodes (How));
2182 if Res = Failure then
2183 Raise_Socket_Error (Socket_Errno);
2185 end Shutdown_Socket;
2192 (Socket : Socket_Type;
2193 Send_To : Sock_Addr_Type) return Stream_Access
2195 S : Datagram_Socket_Stream_Access;
2198 S := new Datagram_Socket_Stream_Type;
2201 S.From := Get_Socket_Name (Socket);
2202 return Stream_Access (S);
2209 function Stream (Socket : Socket_Type) return Stream_Access is
2210 S : Stream_Socket_Stream_Access;
2212 S := new Stream_Socket_Stream_Type;
2214 return Stream_Access (S);
2221 procedure Stream_Write
2222 (Socket : Socket_Type;
2223 Item : Ada.Streams.Stream_Element_Array;
2224 To : access Sock_Addr_Type)
2226 First : Ada.Streams.Stream_Element_Offset;
2227 Index : Ada.Streams.Stream_Element_Offset;
2228 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2231 First := Item'First;
2233 while First <= Max loop
2234 Send_Socket (Socket, Item (First .. Max), Index, To);
2236 -- Exit when all or zero data sent. Zero means that the socket has
2237 -- been closed by peer.
2239 exit when Index < First or else Index = Max;
2244 -- For an empty array, we have First > Max, and hence Index >= Max (no
2245 -- error, the loop above is never executed). After a succesful send,
2246 -- Index = Max. The only remaining case, Index < Max, is therefore
2247 -- always an actual send failure.
2250 Raise_Socket_Error (Socket_Errno);
2258 function To_C (Socket : Socket_Type) return Integer is
2260 return Integer (Socket);
2267 function To_Duration (Val : Timeval) return Timeval_Duration is
2269 return Natural (Val.Tv_Sec) * 1.0 + Natural (Val.Tv_Usec) * 1.0E-6;
2276 function To_Host_Entry (E : Hostent) return Host_Entry_Type is
2279 Official : constant String :=
2280 C.Strings.Value (E.H_Name);
2282 Aliases : constant Chars_Ptr_Array :=
2283 Chars_Ptr_Pointers.Value (E.H_Aliases);
2284 -- H_Aliases points to a list of name aliases. The list is terminated by
2287 Addresses : constant In_Addr_Access_Array :=
2288 In_Addr_Access_Pointers.Value (E.H_Addr_List);
2289 -- H_Addr_List points to a list of binary addresses (in network byte
2290 -- order). The list is terminated by a NULL pointer.
2292 -- H_Length is not used because it is currently only set to 4.
2293 -- H_Addrtype is always AF_INET
2295 Result : Host_Entry_Type
2296 (Aliases_Length => Aliases'Length - 1,
2297 Addresses_Length => Addresses'Length - 1);
2298 -- The last element is a null pointer
2304 Result.Official := To_Name (Official);
2306 Source := Aliases'First;
2307 Target := Result.Aliases'First;
2308 while Target <= Result.Aliases_Length loop
2309 Result.Aliases (Target) :=
2310 To_Name (C.Strings.Value (Aliases (Source)));
2311 Source := Source + 1;
2312 Target := Target + 1;
2315 Source := Addresses'First;
2316 Target := Result.Addresses'First;
2317 while Target <= Result.Addresses_Length loop
2318 To_Inet_Addr (Addresses (Source).all, Result.Addresses (Target));
2319 Source := Source + 1;
2320 Target := Target + 1;
2330 function To_In_Addr (Addr : Inet_Addr_Type) return In_Addr is
2332 if Addr.Family = Family_Inet then
2333 return (S_B1 => C.unsigned_char (Addr.Sin_V4 (1)),
2334 S_B2 => C.unsigned_char (Addr.Sin_V4 (2)),
2335 S_B3 => C.unsigned_char (Addr.Sin_V4 (3)),
2336 S_B4 => C.unsigned_char (Addr.Sin_V4 (4)));
2339 raise Socket_Error with "IPv6 not supported";
2346 procedure To_Inet_Addr
2348 Result : out Inet_Addr_Type) is
2350 Result.Sin_V4 (1) := Inet_Addr_Comp_Type (Addr.S_B1);
2351 Result.Sin_V4 (2) := Inet_Addr_Comp_Type (Addr.S_B2);
2352 Result.Sin_V4 (3) := Inet_Addr_Comp_Type (Addr.S_B3);
2353 Result.Sin_V4 (4) := Inet_Addr_Comp_Type (Addr.S_B4);
2360 function To_Int (F : Request_Flag_Type) return C.int
2362 Current : Request_Flag_Type := F;
2363 Result : C.int := 0;
2366 for J in Flags'Range loop
2367 exit when Current = 0;
2369 if Current mod 2 /= 0 then
2370 if Flags (J) = -1 then
2371 Raise_Socket_Error (SOSC.EOPNOTSUPP);
2374 Result := Result + Flags (J);
2377 Current := Current / 2;
2387 function To_Name (N : String) return Name_Type is
2389 return Name_Type'(N'Length, N);
2392 ----------------------
2393 -- To_Service_Entry --
2394 ----------------------
2396 function To_Service_Entry (E : Servent_Access) return Service_Entry_Type is
2399 Official : constant String := C.Strings.Value (Servent_S_Name (E));
2401 Aliases : constant Chars_Ptr_Array :=
2402 Chars_Ptr_Pointers.Value (Servent_S_Aliases (E));
2403 -- S_Aliases points to a list of name aliases. The list is
2404 -- terminated by a NULL pointer.
2406 Protocol : constant String := C.Strings.Value (Servent_S_Proto (E));
2408 Result : Service_Entry_Type (Aliases_Length => Aliases'Length - 1);
2409 -- The last element is a null pointer
2415 Result.Official := To_Name (Official);
2417 Source := Aliases'First;
2418 Target := Result.Aliases'First;
2419 while Target <= Result.Aliases_Length loop
2420 Result.Aliases (Target) :=
2421 To_Name (C.Strings.Value (Aliases (Source)));
2422 Source := Source + 1;
2423 Target := Target + 1;
2427 Port_Type (Network_To_Short (C.unsigned_short (Servent_S_Port (E))));
2429 Result.Protocol := To_Name (Protocol);
2431 end To_Service_Entry;
2437 function To_String (HN : Name_Type) return String is
2439 return HN.Name (1 .. HN.Length);
2446 function To_Timeval (Val : Timeval_Duration) return Timeval is
2451 -- If zero, set result as zero (otherwise it gets rounded down to -1)
2457 -- Normal case where we do round down
2460 S := time_t (Val - 0.5);
2461 uS := suseconds_t (1_000_000 * (Val - Selector_Duration (S)));
2472 (Stream : in out Datagram_Socket_Stream_Type;
2473 Item : Ada.Streams.Stream_Element_Array)
2476 Stream_Write (Stream.Socket, Item, To => Stream.To'Unrestricted_Access);
2484 (Stream : in out Stream_Socket_Stream_Type;
2485 Item : Ada.Streams.Stream_Element_Array)
2488 Stream_Write (Stream.Socket, Item, To => null);
2491 Sockets_Library_Controller_Object : Sockets_Library_Controller;
2492 pragma Unreferenced (Sockets_Library_Controller_Object);
2493 -- The elaboration and finalization of this object perform the required
2494 -- initialization and cleanup actions for the sockets library.