1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . S O C K E T S --
9 -- Copyright (C) 2001-2005 Ada Core Technologies, Inc. --
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
.Unchecked_Conversion
;
38 with Interfaces
.C
.Strings
;
40 with GNAT
.Sockets
.Constants
;
41 with GNAT
.Sockets
.Thin
; use GNAT
.Sockets
.Thin
;
44 with GNAT
.Sockets
.Linker_Options
;
45 pragma Warnings
(Off
, GNAT
.Sockets
.Linker_Options
);
46 -- Need to include pragma Linker_Options which is platform dependent
48 with System
; use System
;
50 package body GNAT
.Sockets
is
52 use type C
.int
, System
.Address
;
54 Finalized
: Boolean := False;
55 Initialized
: Boolean := False;
57 ENOERROR
: constant := 0;
59 -- Correspondance tables
61 Families
: constant array (Family_Type
) of C
.int
:=
62 (Family_Inet
=> Constants
.AF_INET
,
63 Family_Inet6
=> Constants
.AF_INET6
);
65 Levels
: constant array (Level_Type
) of C
.int
:=
66 (Socket_Level
=> Constants
.SOL_SOCKET
,
67 IP_Protocol_For_IP_Level
=> Constants
.IPPROTO_IP
,
68 IP_Protocol_For_UDP_Level
=> Constants
.IPPROTO_UDP
,
69 IP_Protocol_For_TCP_Level
=> Constants
.IPPROTO_TCP
);
71 Modes
: constant array (Mode_Type
) of C
.int
:=
72 (Socket_Stream
=> Constants
.SOCK_STREAM
,
73 Socket_Datagram
=> Constants
.SOCK_DGRAM
);
75 Shutmodes
: constant array (Shutmode_Type
) of C
.int
:=
76 (Shut_Read
=> Constants
.SHUT_RD
,
77 Shut_Write
=> Constants
.SHUT_WR
,
78 Shut_Read_Write
=> Constants
.SHUT_RDWR
);
80 Requests
: constant array (Request_Name
) of C
.int
:=
81 (Non_Blocking_IO
=> Constants
.FIONBIO
,
82 N_Bytes_To_Read
=> Constants
.FIONREAD
);
84 Options
: constant array (Option_Name
) of C
.int
:=
85 (Keep_Alive
=> Constants
.SO_KEEPALIVE
,
86 Reuse_Address
=> Constants
.SO_REUSEADDR
,
87 Broadcast
=> Constants
.SO_BROADCAST
,
88 Send_Buffer
=> Constants
.SO_SNDBUF
,
89 Receive_Buffer
=> Constants
.SO_RCVBUF
,
90 Linger
=> Constants
.SO_LINGER
,
91 Error
=> Constants
.SO_ERROR
,
92 No_Delay
=> Constants
.TCP_NODELAY
,
93 Add_Membership
=> Constants
.IP_ADD_MEMBERSHIP
,
94 Drop_Membership
=> Constants
.IP_DROP_MEMBERSHIP
,
95 Multicast_TTL
=> Constants
.IP_MULTICAST_TTL
,
96 Multicast_Loop
=> Constants
.IP_MULTICAST_LOOP
);
98 Flags
: constant array (0 .. 3) of C
.int
:=
99 (0 => Constants
.MSG_OOB
, -- Process_Out_Of_Band_Data
100 1 => Constants
.MSG_PEEK
, -- Peek_At_Incoming_Data
101 2 => Constants
.MSG_WAITALL
, -- Wait_For_A_Full_Reception
102 3 => Constants
.MSG_EOR
); -- Send_End_Of_Record
104 Socket_Error_Id
: constant Exception_Id
:= Socket_Error
'Identity;
105 Host_Error_Id
: constant Exception_Id
:= Host_Error
'Identity;
107 Hex_To_Char
: constant String (1 .. 16) := "0123456789ABCDEF";
108 -- Use to print in hexadecimal format
110 function To_In_Addr
is new Ada
.Unchecked_Conversion
(C
.int
, In_Addr
);
111 function To_Int
is new Ada
.Unchecked_Conversion
(In_Addr
, C
.int
);
113 -----------------------
114 -- Local subprograms --
115 -----------------------
117 function Resolve_Error
118 (Error_Value
: Integer;
119 From_Errno
: Boolean := True) return Error_Type
;
120 -- Associate an enumeration value (error_type) to en error value
121 -- (errno). From_Errno prevents from mixing h_errno with errno.
123 function To_Name
(N
: String) return Name_Type
;
124 function To_String
(HN
: Name_Type
) return String;
125 -- Conversion functions
127 function To_Int
(F
: Request_Flag_Type
) return C
.int
;
128 -- Return the int value corresponding to the specified flags combination
130 function Set_Forced_Flags
(F
: C
.int
) return C
.int
;
131 -- Return F with the bits from Constants.MSG_Forced_Flags forced set
133 function Short_To_Network
134 (S
: C
.unsigned_short
) return C
.unsigned_short
;
135 pragma Inline
(Short_To_Network
);
136 -- Convert a port number into a network port number
138 function Network_To_Short
139 (S
: C
.unsigned_short
) return C
.unsigned_short
140 renames Short_To_Network
;
141 -- Symetric operation
144 (Val
: Inet_Addr_VN_Type
;
145 Hex
: Boolean := False) return String;
146 -- Output an array of inet address components either in
147 -- hexadecimal or in decimal mode.
149 function Is_IP_Address
(Name
: String) return Boolean;
150 -- Return true when Name is an IP address in standard dot notation.
152 function To_In_Addr
(Addr
: Inet_Addr_Type
) return Thin
.In_Addr
;
153 function To_Inet_Addr
(Addr
: In_Addr
) return Inet_Addr_Type
;
154 -- Conversion functions
156 function To_Host_Entry
(E
: Hostent
) return Host_Entry_Type
;
157 -- Conversion function
159 function To_Service_Entry
(E
: Servent
) return Service_Entry_Type
;
160 -- Conversion function
162 function To_Timeval
(Val
: Selector_Duration
) return Timeval
;
163 -- Separate Val in seconds and microseconds
165 procedure Raise_Socket_Error
(Error
: Integer);
166 -- Raise Socket_Error with an exception message describing
169 procedure Raise_Host_Error
(Error
: Integer);
170 -- Raise Host_Error exception with message describing error code
171 -- (note hstrerror seems to be obsolete).
173 procedure Narrow
(Item
: in out Socket_Set_Type
);
174 -- Update Last as it may be greater than the real last socket
176 -- Types needed for Datagram_Socket_Stream_Type
178 type Datagram_Socket_Stream_Type
is new Root_Stream_Type
with record
179 Socket
: Socket_Type
;
181 From
: Sock_Addr_Type
;
184 type Datagram_Socket_Stream_Access
is
185 access all Datagram_Socket_Stream_Type
;
188 (Stream
: in out Datagram_Socket_Stream_Type
;
189 Item
: out Ada
.Streams
.Stream_Element_Array
;
190 Last
: out Ada
.Streams
.Stream_Element_Offset
);
193 (Stream
: in out Datagram_Socket_Stream_Type
;
194 Item
: Ada
.Streams
.Stream_Element_Array
);
196 -- Types needed for Stream_Socket_Stream_Type
198 type Stream_Socket_Stream_Type
is new Root_Stream_Type
with record
199 Socket
: Socket_Type
;
202 type Stream_Socket_Stream_Access
is
203 access all Stream_Socket_Stream_Type
;
206 (Stream
: in out Stream_Socket_Stream_Type
;
207 Item
: out Ada
.Streams
.Stream_Element_Array
;
208 Last
: out Ada
.Streams
.Stream_Element_Offset
);
211 (Stream
: in out Stream_Socket_Stream_Type
;
212 Item
: Ada
.Streams
.Stream_Element_Array
);
218 function "+" (L
, R
: Request_Flag_Type
) return Request_Flag_Type
is
227 procedure Abort_Selector
(Selector
: Selector_Type
) is
228 Buf
: aliased Character := ASCII
.NUL
;
232 -- Send an empty array to unblock C select system call
234 Res
:= C_Send
(C
.int
(Selector
.W_Sig_Socket
), Buf
'Address, 1,
235 Constants
.MSG_Forced_Flags
);
236 if Res
= Failure
then
237 Raise_Socket_Error
(Socket_Errno
);
245 procedure Accept_Socket
246 (Server
: Socket_Type
;
247 Socket
: out Socket_Type
;
248 Address
: out Sock_Addr_Type
)
251 Sin
: aliased Sockaddr_In
;
252 Len
: aliased C
.int
:= Sin
'Size / 8;
255 Res
:= C_Accept
(C
.int
(Server
), Sin
'Address, Len
'Access);
257 if Res
= Failure
then
258 Raise_Socket_Error
(Socket_Errno
);
261 Socket
:= Socket_Type
(Res
);
263 Address
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
264 Address
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
272 (E
: Host_Entry_Type
;
273 N
: Positive := 1) return Inet_Addr_Type
276 return E
.Addresses
(N
);
279 ----------------------
280 -- Addresses_Length --
281 ----------------------
283 function Addresses_Length
(E
: Host_Entry_Type
) return Natural is
285 return E
.Addresses_Length
;
286 end Addresses_Length
;
293 (E
: Host_Entry_Type
;
294 N
: Positive := 1) return String
297 return To_String
(E
.Aliases
(N
));
305 (S
: Service_Entry_Type
;
306 N
: Positive := 1) return String
309 return To_String
(S
.Aliases
(N
));
316 function Aliases_Length
(E
: Host_Entry_Type
) return Natural is
318 return E
.Aliases_Length
;
325 function Aliases_Length
(S
: Service_Entry_Type
) return Natural is
327 return S
.Aliases_Length
;
334 procedure Bind_Socket
335 (Socket
: Socket_Type
;
336 Address
: Sock_Addr_Type
)
339 Sin
: aliased Sockaddr_In
;
340 Len
: constant C
.int
:= Sin
'Size / 8;
343 if Address
.Family
= Family_Inet6
then
347 Set_Length
(Sin
'Unchecked_Access, Len
);
348 Set_Family
(Sin
'Unchecked_Access, Families
(Address
.Family
));
350 (Sin
'Unchecked_Access,
351 Short_To_Network
(C
.unsigned_short
(Address
.Port
)));
353 Res
:= C_Bind
(C
.int
(Socket
), Sin
'Address, Len
);
355 if Res
= Failure
then
356 Raise_Socket_Error
(Socket_Errno
);
364 procedure Check_Selector
365 (Selector
: in out Selector_Type
;
366 R_Socket_Set
: in out Socket_Set_Type
;
367 W_Socket_Set
: in out Socket_Set_Type
;
368 Status
: out Selector_Status
;
369 Timeout
: Selector_Duration
:= Forever
)
371 E_Socket_Set
: Socket_Set_Type
; -- (No_Socket, No_Socket_Set)
374 (Selector
, R_Socket_Set
, W_Socket_Set
, E_Socket_Set
, Status
, Timeout
);
377 procedure Check_Selector
378 (Selector
: in out Selector_Type
;
379 R_Socket_Set
: in out Socket_Set_Type
;
380 W_Socket_Set
: in out Socket_Set_Type
;
381 E_Socket_Set
: in out Socket_Set_Type
;
382 Status
: out Selector_Status
;
383 Timeout
: Selector_Duration
:= Forever
)
387 RSet
: Socket_Set_Type
;
388 WSet
: Socket_Set_Type
;
389 ESet
: Socket_Set_Type
;
390 TVal
: aliased Timeval
;
391 TPtr
: Timeval_Access
;
396 -- No timeout or Forever is indicated by a null timeval pointer
398 if Timeout
= Forever
then
401 TVal
:= To_Timeval
(Timeout
);
402 TPtr
:= TVal
'Unchecked_Access;
405 -- Copy R_Socket_Set in RSet and add read signalling socket
407 RSet
:= (Set
=> New_Socket_Set
(R_Socket_Set
.Set
),
408 Last
=> R_Socket_Set
.Last
);
409 Set
(RSet
, Selector
.R_Sig_Socket
);
411 -- Copy W_Socket_Set in WSet
413 WSet
:= (Set
=> New_Socket_Set
(W_Socket_Set
.Set
),
414 Last
=> W_Socket_Set
.Last
);
416 -- Copy E_Socket_Set in ESet
418 ESet
:= (Set
=> New_Socket_Set
(E_Socket_Set
.Set
),
419 Last
=> E_Socket_Set
.Last
);
421 Last
:= C
.int
'Max (C
.int
'Max (C
.int
(RSet
.Last
),
433 if Res
= Failure
then
434 Raise_Socket_Error
(Socket_Errno
);
437 -- If Select was resumed because of read signalling socket,
438 -- read this data and remove socket from set.
440 if Is_Set
(RSet
, Selector
.R_Sig_Socket
) then
441 Clear
(RSet
, Selector
.R_Sig_Socket
);
447 Res
:= C_Recv
(C
.int
(Selector
.R_Sig_Socket
), Buf
'Address, 1, 0);
449 if Res
= Failure
then
450 Raise_Socket_Error
(Socket_Errno
);
460 -- Update RSet, WSet and ESet in regard to their new socket
467 -- Reset RSet as it should be if R_Sig_Socket was not added
469 if Is_Empty
(RSet
) then
473 if Is_Empty
(WSet
) then
477 if Is_Empty
(ESet
) then
481 -- Deliver RSet, WSet and ESet
483 Empty
(R_Socket_Set
);
484 R_Socket_Set
:= RSet
;
486 Empty
(W_Socket_Set
);
487 W_Socket_Set
:= WSet
;
489 Empty
(E_Socket_Set
);
490 E_Socket_Set
:= ESet
;
498 (Item
: in out Socket_Set_Type
;
499 Socket
: Socket_Type
)
501 Last
: aliased C
.int
:= C
.int
(Item
.Last
);
504 if Item
.Last
/= No_Socket
then
505 Remove_Socket_From_Set
(Item
.Set
, C
.int
(Socket
));
506 Last_Socket_In_Set
(Item
.Set
, Last
'Unchecked_Access);
507 Item
.Last
:= Socket_Type
(Last
);
515 -- Comments needed below ???
516 -- Why are exceptions ignored ???
518 procedure Close_Selector
(Selector
: in out Selector_Type
) is
521 Close_Socket
(Selector
.R_Sig_Socket
);
529 Close_Socket
(Selector
.W_Sig_Socket
);
541 procedure Close_Socket
(Socket
: Socket_Type
) is
545 Res
:= C_Close
(C
.int
(Socket
));
547 if Res
= Failure
then
548 Raise_Socket_Error
(Socket_Errno
);
556 procedure Connect_Socket
557 (Socket
: Socket_Type
;
558 Server
: in out Sock_Addr_Type
)
561 Sin
: aliased Sockaddr_In
;
562 Len
: constant C
.int
:= Sin
'Size / 8;
565 if Server
.Family
= Family_Inet6
then
569 Set_Length
(Sin
'Unchecked_Access, Len
);
570 Set_Family
(Sin
'Unchecked_Access, Families
(Server
.Family
));
571 Set_Address
(Sin
'Unchecked_Access, To_In_Addr
(Server
.Addr
));
573 (Sin
'Unchecked_Access,
574 Short_To_Network
(C
.unsigned_short
(Server
.Port
)));
576 Res
:= C_Connect
(C
.int
(Socket
), Sin
'Address, Len
);
578 if Res
= Failure
then
579 Raise_Socket_Error
(Socket_Errno
);
587 procedure Control_Socket
588 (Socket
: Socket_Type
;
589 Request
: in out Request_Type
)
596 when Non_Blocking_IO
=>
597 Arg
:= C
.int
(Boolean'Pos (Request
.Enabled
));
599 when N_Bytes_To_Read
=>
606 Requests
(Request
.Name
),
607 Arg
'Unchecked_Access);
609 if Res
= Failure
then
610 Raise_Socket_Error
(Socket_Errno
);
614 when Non_Blocking_IO
=>
617 when N_Bytes_To_Read
=>
618 Request
.Size
:= Natural (Arg
);
628 (Source
: Socket_Set_Type
;
629 Target
: in out Socket_Set_Type
)
633 if Source
.Last
/= No_Socket
then
634 Target
.Set
:= New_Socket_Set
(Source
.Set
);
635 Target
.Last
:= Source
.Last
;
639 ---------------------
640 -- Create_Selector --
641 ---------------------
643 procedure Create_Selector
(Selector
: out Selector_Type
) is
648 Sin
: aliased Sockaddr_In
;
649 Len
: aliased C
.int
:= Sin
'Size / 8;
653 -- We open two signalling sockets. One of them is used to send data to
654 -- send data to the other, which is included in a C_Select socket set.
655 -- The communication is used to force the call to C_Select to complete,
656 -- and the waiting task to resume its execution.
658 -- Create a listening socket
660 S0
:= C_Socket
(Constants
.AF_INET
, Constants
.SOCK_STREAM
, 0);
662 Raise_Socket_Error
(Socket_Errno
);
665 -- Bind the socket to any unused port on localhost
667 Sin
.Sin_Addr
.S_B1
:= 127;
668 Sin
.Sin_Addr
.S_B2
:= 0;
669 Sin
.Sin_Addr
.S_B3
:= 0;
670 Sin
.Sin_Addr
.S_B4
:= 1;
673 Res
:= C_Bind
(S0
, Sin
'Address, Len
);
674 if Res
= Failure
then
677 Raise_Socket_Error
(Err
);
680 -- Get the port used by the socket
682 Res
:= C_Getsockname
(S0
, Sin
'Address, Len
'Access);
684 if Res
= Failure
then
687 Raise_Socket_Error
(Err
);
690 -- Set backlog to 1 to guarantee that exactly one call to connect(2)
693 Res
:= C_Listen
(S0
, 1);
695 if Res
= Failure
then
698 Raise_Socket_Error
(Err
);
701 S1
:= C_Socket
(Constants
.AF_INET
, Constants
.SOCK_STREAM
, 0);
706 Raise_Socket_Error
(Err
);
709 -- Do a connect and accept the connection
711 Res
:= C_Connect
(S1
, Sin
'Address, Len
);
713 if Res
= Failure
then
717 Raise_Socket_Error
(Err
);
720 -- Since the call to connect(2) has suceeded and the backlog limit on
721 -- the listening socket is 1, we know that there is now exactly one
722 -- pending connection on S0, which is the one from S1.
724 S2
:= C_Accept
(S0
, Sin
'Address, Len
'Access);
730 Raise_Socket_Error
(Err
);
735 if Res
= Failure
then
736 Raise_Socket_Error
(Socket_Errno
);
739 Selector
.R_Sig_Socket
:= Socket_Type
(S1
);
740 Selector
.W_Sig_Socket
:= Socket_Type
(S2
);
747 procedure Create_Socket
748 (Socket
: out Socket_Type
;
749 Family
: Family_Type
:= Family_Inet
;
750 Mode
: Mode_Type
:= Socket_Stream
)
755 Res
:= C_Socket
(Families
(Family
), Modes
(Mode
), 0);
757 if Res
= Failure
then
758 Raise_Socket_Error
(Socket_Errno
);
761 Socket
:= Socket_Type
(Res
);
768 procedure Empty
(Item
: in out Socket_Set_Type
) is
770 if Item
.Set
/= No_Socket_Set
then
771 Free_Socket_Set
(Item
.Set
);
772 Item
.Set
:= No_Socket_Set
;
775 Item
.Last
:= No_Socket
;
782 procedure Finalize
is
797 (Item
: in out Socket_Set_Type
;
798 Socket
: out Socket_Type
)
801 L
: aliased C
.int
:= C
.int
(Item
.Last
);
804 if Item
.Last
/= No_Socket
then
806 (Item
.Set
, L
'Unchecked_Access, S
'Unchecked_Access);
807 Item
.Last
:= Socket_Type
(L
);
808 Socket
:= Socket_Type
(S
);
818 function Get_Address
(Stream
: Stream_Access
) return Sock_Addr_Type
is
820 if Stream
= null then
823 elsif Stream
.all in Datagram_Socket_Stream_Type
then
824 return Datagram_Socket_Stream_Type
(Stream
.all).From
;
827 return Get_Peer_Name
(Stream_Socket_Stream_Type
(Stream
.all).Socket
);
831 -------------------------
832 -- Get_Host_By_Address --
833 -------------------------
835 function Get_Host_By_Address
836 (Address
: Inet_Addr_Type
;
837 Family
: Family_Type
:= Family_Inet
) return Host_Entry_Type
839 pragma Unreferenced
(Family
);
841 HA
: aliased In_Addr
:= To_In_Addr
(Address
);
842 Res
: Hostent_Access
;
846 -- This C function is not always thread-safe. Protect against
847 -- concurrent access.
850 Res
:= C_Gethostbyaddr
(HA
'Address, HA
'Size / 8, Constants
.AF_INET
);
855 Raise_Host_Error
(Err
);
858 -- Translate from the C format to the API format
861 HE
: constant Host_Entry_Type
:= To_Host_Entry
(Res
.all);
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
874 HN
: constant C
.char_array
:= C
.To_C
(Name
);
875 Res
: Hostent_Access
;
879 -- Detect IP address name and redirect to Inet_Addr
881 if Is_IP_Address
(Name
) then
882 return Get_Host_By_Address
(Inet_Addr
(Name
));
885 -- This C function is not always thread-safe. Protect against
886 -- concurrent access.
889 Res
:= C_Gethostbyname
(HN
);
894 Raise_Host_Error
(Err
);
897 -- Translate from the C format to the API format
900 HE
: constant Host_Entry_Type
:= To_Host_Entry
(Res
.all);
906 end Get_Host_By_Name
;
912 function Get_Peer_Name
(Socket
: Socket_Type
) return Sock_Addr_Type
is
913 Sin
: aliased Sockaddr_In
;
914 Len
: aliased C
.int
:= Sin
'Size / 8;
915 Res
: Sock_Addr_Type
(Family_Inet
);
918 if C_Getpeername
(C
.int
(Socket
), Sin
'Address, Len
'Access) = Failure
then
919 Raise_Socket_Error
(Socket_Errno
);
922 Res
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
923 Res
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
928 -------------------------
929 -- Get_Service_By_Name --
930 -------------------------
932 function Get_Service_By_Name
934 Protocol
: String) return Service_Entry_Type
936 SN
: constant C
.char_array
:= C
.To_C
(Name
);
937 SP
: constant C
.char_array
:= C
.To_C
(Protocol
);
938 Res
: Servent_Access
;
941 -- This C function is not always thread-safe. Protect against
942 -- concurrent access.
945 Res
:= C_Getservbyname
(SN
, SP
);
949 Ada
.Exceptions
.Raise_Exception
950 (Service_Error
'Identity, "Service not found");
953 -- Translate from the C format to the API format
956 SE
: constant Service_Entry_Type
:= To_Service_Entry
(Res
.all);
962 end Get_Service_By_Name
;
964 -------------------------
965 -- Get_Service_By_Port --
966 -------------------------
968 function Get_Service_By_Port
970 Protocol
: String) return Service_Entry_Type
972 SP
: constant C
.char_array
:= C
.To_C
(Protocol
);
973 Res
: Servent_Access
;
976 -- This C function is not always thread-safe. Protect against
977 -- concurrent access.
980 Res
:= C_Getservbyport
981 (C
.int
(Short_To_Network
(C
.unsigned_short
(Port
))), SP
);
985 Ada
.Exceptions
.Raise_Exception
986 (Service_Error
'Identity, "Service not found");
989 -- Translate from the C format to the API format
992 SE
: constant Service_Entry_Type
:= To_Service_Entry
(Res
.all);
998 end Get_Service_By_Port
;
1000 ---------------------
1001 -- Get_Socket_Name --
1002 ---------------------
1004 function Get_Socket_Name
1005 (Socket
: Socket_Type
) return Sock_Addr_Type
1007 Sin
: aliased Sockaddr_In
;
1008 Len
: aliased C
.int
:= Sin
'Size / 8;
1010 Addr
: Sock_Addr_Type
:= No_Sock_Addr
;
1013 Res
:= C_Getsockname
(C
.int
(Socket
), Sin
'Address, Len
'Access);
1014 if Res
/= Failure
then
1015 Addr
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
1016 Addr
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
1020 end Get_Socket_Name
;
1022 -----------------------
1023 -- Get_Socket_Option --
1024 -----------------------
1026 function Get_Socket_Option
1027 (Socket
: Socket_Type
;
1028 Level
: Level_Type
:= Socket_Level
;
1029 Name
: Option_Name
) return Option_Type
1031 use type C
.unsigned_char
;
1033 V8
: aliased Two_Int
;
1035 V1
: aliased C
.unsigned_char
;
1036 Len
: aliased C
.int
;
1037 Add
: System
.Address
;
1039 Opt
: Option_Type
(Name
);
1043 when Multicast_Loop |
1071 Add
, Len
'Unchecked_Access);
1073 if Res
= Failure
then
1074 Raise_Socket_Error
(Socket_Errno
);
1082 Opt
.Enabled
:= (V4
/= 0);
1085 Opt
.Enabled
:= (V8
(V8
'First) /= 0);
1086 Opt
.Seconds
:= Natural (V8
(V8
'Last));
1090 Opt
.Size
:= Natural (V4
);
1093 Opt
.Error
:= Resolve_Error
(Integer (V4
));
1095 when Add_Membership |
1097 Opt
.Multicast_Address
:= To_Inet_Addr
(To_In_Addr
(V8
(V8
'First)));
1098 Opt
.Local_Interface
:= To_Inet_Addr
(To_In_Addr
(V8
(V8
'Last)));
1100 when Multicast_TTL
=>
1101 Opt
.Time_To_Live
:= Integer (V1
);
1103 when Multicast_Loop
=>
1104 Opt
.Enabled
:= (V1
/= 0);
1109 end Get_Socket_Option
;
1115 function Host_Name
return String is
1116 Name
: aliased C
.char_array
(1 .. 64);
1120 Res
:= C_Gethostname
(Name
'Address, Name
'Length);
1122 if Res
= Failure
then
1123 Raise_Socket_Error
(Socket_Errno
);
1126 return C
.To_Ada
(Name
);
1134 (Val
: Inet_Addr_VN_Type
;
1135 Hex
: Boolean := False) return String
1137 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
1138 -- has at most a length of 3 plus one '.' character.
1140 Buffer
: String (1 .. 4 * Val
'Length);
1141 Length
: Natural := 1;
1142 Separator
: Character;
1144 procedure Img10
(V
: Inet_Addr_Comp_Type
);
1145 -- Append to Buffer image of V in decimal format
1147 procedure Img16
(V
: Inet_Addr_Comp_Type
);
1148 -- Append to Buffer image of V in hexadecimal format
1154 procedure Img10
(V
: Inet_Addr_Comp_Type
) is
1155 Img
: constant String := V
'Img;
1156 Len
: constant Natural := Img
'Length - 1;
1159 Buffer
(Length
.. Length
+ Len
- 1) := Img
(2 .. Img
'Last);
1160 Length
:= Length
+ Len
;
1167 procedure Img16
(V
: Inet_Addr_Comp_Type
) is
1169 Buffer
(Length
) := Hex_To_Char
(Natural (V
/ 16) + 1);
1170 Buffer
(Length
+ 1) := Hex_To_Char
(Natural (V
mod 16) + 1);
1171 Length
:= Length
+ 2;
1174 -- Start of processing for Image
1183 for J
in Val
'Range loop
1190 if J
/= Val
'Last then
1191 Buffer
(Length
) := Separator
;
1192 Length
:= Length
+ 1;
1196 return Buffer
(1 .. Length
- 1);
1203 function Image
(Value
: Inet_Addr_Type
) return String is
1205 if Value
.Family
= Family_Inet
then
1206 return Image
(Inet_Addr_VN_Type
(Value
.Sin_V4
), Hex
=> False);
1208 return Image
(Inet_Addr_VN_Type
(Value
.Sin_V6
), Hex
=> True);
1216 function Image
(Value
: Sock_Addr_Type
) return String is
1217 Port
: constant String := Value
.Port
'Img;
1219 return Image
(Value
.Addr
) & ':' & Port
(2 .. Port
'Last);
1226 function Image
(Socket
: Socket_Type
) return String is
1235 function Inet_Addr
(Image
: String) return Inet_Addr_Type
is
1236 use Interfaces
.C
.Strings
;
1242 -- Special case for the all-ones broadcast address: this address
1243 -- has the same in_addr_t value as Failure, and thus cannot be
1244 -- properly returned by inet_addr(3).
1246 if Image
(Image
'Range) = "255.255.255.255" then
1247 return Broadcast_Inet_Addr
;
1250 Img
:= New_String
(Image
);
1251 Res
:= C_Inet_Addr
(Img
);
1254 if Res
= Failure
then
1255 Raise_Socket_Error
(Constants
.EINVAL
);
1258 return To_Inet_Addr
(To_In_Addr
(Res
));
1265 procedure Initialize
(Process_Blocking_IO
: Boolean := False) is
1267 if not Initialized
then
1268 Initialized
:= True;
1269 Thin
.Initialize
(Process_Blocking_IO
);
1277 function Is_Empty
(Item
: Socket_Set_Type
) return Boolean is
1279 return Item
.Last
= No_Socket
;
1286 function Is_IP_Address
(Name
: String) return Boolean is
1288 for J
in Name
'Range loop
1290 and then Name
(J
) not in '0' .. '9'
1304 (Item
: Socket_Set_Type
;
1305 Socket
: Socket_Type
) return Boolean
1308 return Item
.Last
/= No_Socket
1309 and then Socket
<= Item
.Last
1310 and then Is_Socket_In_Set
(Item
.Set
, C
.int
(Socket
)) /= 0;
1317 procedure Listen_Socket
1318 (Socket
: Socket_Type
;
1319 Length
: Positive := 15)
1321 Res
: constant C
.int
:= C_Listen
(C
.int
(Socket
), C
.int
(Length
));
1323 if Res
= Failure
then
1324 Raise_Socket_Error
(Socket_Errno
);
1332 procedure Narrow
(Item
: in out Socket_Set_Type
) is
1333 Last
: aliased C
.int
:= C
.int
(Item
.Last
);
1335 if Item
.Set
/= No_Socket_Set
then
1336 Last_Socket_In_Set
(Item
.Set
, Last
'Unchecked_Access);
1337 Item
.Last
:= Socket_Type
(Last
);
1345 function Official_Name
(E
: Host_Entry_Type
) return String is
1347 return To_String
(E
.Official
);
1354 function Official_Name
(S
: Service_Entry_Type
) return String is
1356 return To_String
(S
.Official
);
1363 function Port_Number
(S
: Service_Entry_Type
) return Port_Type
is
1372 function Protocol_Name
(S
: Service_Entry_Type
) return String is
1374 return To_String
(S
.Protocol
);
1377 ----------------------
1378 -- Raise_Host_Error --
1379 ----------------------
1381 procedure Raise_Host_Error
(Error
: Integer) is
1383 function Host_Error_Message
return String;
1384 -- We do not use a C function like strerror because hstrerror
1385 -- that would correspond seems to be obsolete. Return
1386 -- appropriate string for error value.
1388 ------------------------
1389 -- Host_Error_Message --
1390 ------------------------
1392 function Host_Error_Message
return String is
1395 when Constants
.HOST_NOT_FOUND
=> return "Host not found";
1396 when Constants
.TRY_AGAIN
=> return "Try again";
1397 when Constants
.NO_RECOVERY
=> return "No recovery";
1398 when Constants
.NO_DATA
=> return "No address";
1399 when others => return "Unknown error";
1401 end Host_Error_Message
;
1403 -- Start of processing for Raise_Host_Error
1406 Ada
.Exceptions
.Raise_Exception
(Host_Error
'Identity, Host_Error_Message
);
1407 end Raise_Host_Error
;
1409 ------------------------
1410 -- Raise_Socket_Error --
1411 ------------------------
1413 procedure Raise_Socket_Error
(Error
: Integer) is
1414 use type C
.Strings
.chars_ptr
;
1416 function Image
(E
: Integer) return String;
1422 function Image
(E
: Integer) return String is
1423 Msg
: String := E
'Img & "] ";
1425 Msg
(Msg
'First) := '[';
1429 -- Start of processing for Raise_Socket_Error
1432 Ada
.Exceptions
.Raise_Exception
1433 (Socket_Error
'Identity,
1434 Image
(Error
) & C
.Strings
.Value
(Socket_Error_Message
(Error
)));
1435 end Raise_Socket_Error
;
1442 (Stream
: in out Datagram_Socket_Stream_Type
;
1443 Item
: out Ada
.Streams
.Stream_Element_Array
;
1444 Last
: out Ada
.Streams
.Stream_Element_Offset
)
1446 First
: Ada
.Streams
.Stream_Element_Offset
:= Item
'First;
1447 Index
: Ada
.Streams
.Stream_Element_Offset
:= First
- 1;
1448 Max
: constant Ada
.Streams
.Stream_Element_Offset
:= Item
'Last;
1454 Item
(First
.. Max
),
1460 -- Exit when all or zero data received. Zero means that
1461 -- the socket peer is closed.
1463 exit when Index
< First
or else Index
= Max
;
1474 (Stream
: in out Stream_Socket_Stream_Type
;
1475 Item
: out Ada
.Streams
.Stream_Element_Array
;
1476 Last
: out Ada
.Streams
.Stream_Element_Offset
)
1478 First
: Ada
.Streams
.Stream_Element_Offset
:= Item
'First;
1479 Index
: Ada
.Streams
.Stream_Element_Offset
:= First
- 1;
1480 Max
: constant Ada
.Streams
.Stream_Element_Offset
:= Item
'Last;
1484 Receive_Socket
(Stream
.Socket
, Item
(First
.. Max
), Index
);
1487 -- Exit when all or zero data received. Zero means that
1488 -- the socket peer is closed.
1490 exit when Index
< First
or else Index
= Max
;
1496 --------------------
1497 -- Receive_Socket --
1498 --------------------
1500 procedure Receive_Socket
1501 (Socket
: Socket_Type
;
1502 Item
: out Ada
.Streams
.Stream_Element_Array
;
1503 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1504 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1506 use type Ada
.Streams
.Stream_Element_Offset
;
1513 Item
(Item
'First)'Address,
1517 if Res
= Failure
then
1518 Raise_Socket_Error
(Socket_Errno
);
1521 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1524 --------------------
1525 -- Receive_Socket --
1526 --------------------
1528 procedure Receive_Socket
1529 (Socket
: Socket_Type
;
1530 Item
: out Ada
.Streams
.Stream_Element_Array
;
1531 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1532 From
: out Sock_Addr_Type
;
1533 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1535 use type Ada
.Streams
.Stream_Element_Offset
;
1538 Sin
: aliased Sockaddr_In
;
1539 Len
: aliased C
.int
:= Sin
'Size / 8;
1545 Item
(Item
'First)'Address,
1548 Sin
'Unchecked_Access,
1549 Len
'Unchecked_Access);
1551 if Res
= Failure
then
1552 Raise_Socket_Error
(Socket_Errno
);
1555 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1557 From
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
1558 From
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
1565 function Resolve_Error
1566 (Error_Value
: Integer;
1567 From_Errno
: Boolean := True) return Error_Type
1569 use GNAT
.Sockets
.Constants
;
1572 if not From_Errno
then
1574 when Constants
.HOST_NOT_FOUND
=> return Unknown_Host
;
1575 when Constants
.TRY_AGAIN
=> return Host_Name_Lookup_Failure
;
1576 when Constants
.NO_RECOVERY
=>
1577 return Non_Recoverable_Error
;
1578 when Constants
.NO_DATA
=> return Unknown_Server_Error
;
1579 when others => return Cannot_Resolve_Error
;
1584 when ENOERROR
=> return Success
;
1585 when EACCES
=> return Permission_Denied
;
1586 when EADDRINUSE
=> return Address_Already_In_Use
;
1587 when EADDRNOTAVAIL
=> return Cannot_Assign_Requested_Address
;
1588 when EAFNOSUPPORT
=>
1589 return Address_Family_Not_Supported_By_Protocol
;
1590 when EALREADY
=> return Operation_Already_In_Progress
;
1591 when EBADF
=> return Bad_File_Descriptor
;
1592 when ECONNABORTED
=> return Software_Caused_Connection_Abort
;
1593 when ECONNREFUSED
=> return Connection_Refused
;
1594 when ECONNRESET
=> return Connection_Reset_By_Peer
;
1595 when EDESTADDRREQ
=> return Destination_Address_Required
;
1596 when EFAULT
=> return Bad_Address
;
1597 when EHOSTDOWN
=> return Host_Is_Down
;
1598 when EHOSTUNREACH
=> return No_Route_To_Host
;
1599 when EINPROGRESS
=> return Operation_Now_In_Progress
;
1600 when EINTR
=> return Interrupted_System_Call
;
1601 when EINVAL
=> return Invalid_Argument
;
1602 when EIO
=> return Input_Output_Error
;
1603 when EISCONN
=> return Transport_Endpoint_Already_Connected
;
1604 when ELOOP
=> return Too_Many_Symbolic_Links
;
1605 when EMFILE
=> return Too_Many_Open_Files
;
1606 when EMSGSIZE
=> return Message_Too_Long
;
1607 when ENAMETOOLONG
=> return File_Name_Too_Long
;
1608 when ENETDOWN
=> return Network_Is_Down
;
1610 return Network_Dropped_Connection_Because_Of_Reset
;
1611 when ENETUNREACH
=> return Network_Is_Unreachable
;
1612 when ENOBUFS
=> return No_Buffer_Space_Available
;
1613 when ENOPROTOOPT
=> return Protocol_Not_Available
;
1614 when ENOTCONN
=> return Transport_Endpoint_Not_Connected
;
1615 when ENOTSOCK
=> return Socket_Operation_On_Non_Socket
;
1616 when EOPNOTSUPP
=> return Operation_Not_Supported
;
1617 when EPFNOSUPPORT
=> return Protocol_Family_Not_Supported
;
1618 when EPROTONOSUPPORT
=> return Protocol_Not_Supported
;
1619 when EPROTOTYPE
=> return Protocol_Wrong_Type_For_Socket
;
1621 return Cannot_Send_After_Transport_Endpoint_Shutdown
;
1622 when ESOCKTNOSUPPORT
=> return Socket_Type_Not_Supported
;
1623 when ETIMEDOUT
=> return Connection_Timed_Out
;
1624 when ETOOMANYREFS
=> return Too_Many_References
;
1625 when EWOULDBLOCK
=> return Resource_Temporarily_Unavailable
;
1626 when others => null;
1629 return Cannot_Resolve_Error
;
1632 -----------------------
1633 -- Resolve_Exception --
1634 -----------------------
1636 function Resolve_Exception
1637 (Occurrence
: Exception_Occurrence
) return Error_Type
1639 Id
: constant Exception_Id
:= Exception_Identity
(Occurrence
);
1640 Msg
: constant String := Exception_Message
(Occurrence
);
1641 First
: Natural := Msg
'First;
1646 while First
<= Msg
'Last
1647 and then Msg
(First
) not in '0' .. '9'
1652 if First
> Msg
'Last then
1653 return Cannot_Resolve_Error
;
1658 while Last
< Msg
'Last
1659 and then Msg
(Last
+ 1) in '0' .. '9'
1664 Val
:= Integer'Value (Msg
(First
.. Last
));
1666 if Id
= Socket_Error_Id
then
1667 return Resolve_Error
(Val
);
1668 elsif Id
= Host_Error_Id
then
1669 return Resolve_Error
(Val
, False);
1671 return Cannot_Resolve_Error
;
1673 end Resolve_Exception
;
1675 --------------------
1676 -- Receive_Vector --
1677 --------------------
1679 procedure Receive_Vector
1680 (Socket
: Socket_Type
;
1681 Vector
: Vector_Type
;
1682 Count
: out Ada
.Streams
.Stream_Element_Count
)
1690 Vector
(Vector
'First)'Address,
1693 if Res
= Failure
then
1694 Raise_Socket_Error
(Socket_Errno
);
1697 Count
:= Ada
.Streams
.Stream_Element_Count
(Res
);
1704 procedure Send_Socket
1705 (Socket
: Socket_Type
;
1706 Item
: Ada
.Streams
.Stream_Element_Array
;
1707 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1708 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1710 use type Ada
.Streams
.Stream_Element_Offset
;
1718 Item
(Item
'First)'Address,
1720 Set_Forced_Flags
(To_Int
(Flags
)));
1722 if Res
= Failure
then
1723 Raise_Socket_Error
(Socket_Errno
);
1726 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1733 procedure Send_Socket
1734 (Socket
: Socket_Type
;
1735 Item
: Ada
.Streams
.Stream_Element_Array
;
1736 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1737 To
: Sock_Addr_Type
;
1738 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1740 use type Ada
.Streams
.Stream_Element_Offset
;
1743 Sin
: aliased Sockaddr_In
;
1744 Len
: constant C
.int
:= Sin
'Size / 8;
1747 Set_Length
(Sin
'Unchecked_Access, Len
);
1748 Set_Family
(Sin
'Unchecked_Access, Families
(To
.Family
));
1749 Set_Address
(Sin
'Unchecked_Access, To_In_Addr
(To
.Addr
));
1751 (Sin
'Unchecked_Access,
1752 Short_To_Network
(C
.unsigned_short
(To
.Port
)));
1756 Item
(Item
'First)'Address,
1758 Set_Forced_Flags
(To_Int
(Flags
)),
1759 Sin
'Unchecked_Access,
1762 if Res
= Failure
then
1763 Raise_Socket_Error
(Socket_Errno
);
1766 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1773 procedure Send_Vector
1774 (Socket
: Socket_Type
;
1775 Vector
: Vector_Type
;
1776 Count
: out Ada
.Streams
.Stream_Element_Count
)
1784 Vector
(Vector
'First)'Address,
1787 if Res
= Failure
then
1788 Raise_Socket_Error
(Socket_Errno
);
1791 Count
:= Ada
.Streams
.Stream_Element_Count
(Res
);
1798 procedure Set
(Item
: in out Socket_Set_Type
; Socket
: Socket_Type
) is
1800 if Item
.Set
= No_Socket_Set
then
1801 Item
.Set
:= New_Socket_Set
(No_Socket_Set
);
1802 Item
.Last
:= Socket
;
1804 elsif Item
.Last
< Socket
then
1805 Item
.Last
:= Socket
;
1808 Insert_Socket_In_Set
(Item
.Set
, C
.int
(Socket
));
1811 ----------------------
1812 -- Set_Forced_Flags --
1813 ----------------------
1815 function Set_Forced_Flags
(F
: C
.int
) return C
.int
is
1816 use type C
.unsigned
;
1817 function To_unsigned
is
1818 new Ada
.Unchecked_Conversion
(C
.int
, C
.unsigned
);
1820 new Ada
.Unchecked_Conversion
(C
.unsigned
, C
.int
);
1822 return To_int
(To_unsigned
(F
) or Constants
.MSG_Forced_Flags
);
1823 end Set_Forced_Flags
;
1825 -----------------------
1826 -- Set_Socket_Option --
1827 -----------------------
1829 procedure Set_Socket_Option
1830 (Socket
: Socket_Type
;
1831 Level
: Level_Type
:= Socket_Level
;
1832 Option
: Option_Type
)
1834 V8
: aliased Two_Int
;
1836 V1
: aliased C
.unsigned_char
;
1837 Len
: aliased C
.int
;
1838 Add
: System
.Address
:= Null_Address
;
1847 V4
:= C
.int
(Boolean'Pos (Option
.Enabled
));
1852 V8
(V8
'First) := C
.int
(Boolean'Pos (Option
.Enabled
));
1853 V8
(V8
'Last) := C
.int
(Option
.Seconds
);
1859 V4
:= C
.int
(Option
.Size
);
1864 V4
:= C
.int
(Boolean'Pos (True));
1868 when Add_Membership |
1870 V8
(V8
'First) := To_Int
(To_In_Addr
(Option
.Multicast_Address
));
1871 V8
(V8
'Last) := To_Int
(To_In_Addr
(Option
.Local_Interface
));
1875 when Multicast_TTL
=>
1876 V1
:= C
.unsigned_char
(Option
.Time_To_Live
);
1880 when Multicast_Loop
=>
1881 V1
:= C
.unsigned_char
(Boolean'Pos (Option
.Enabled
));
1890 Options
(Option
.Name
),
1893 if Res
= Failure
then
1894 Raise_Socket_Error
(Socket_Errno
);
1896 end Set_Socket_Option
;
1898 ----------------------
1899 -- Short_To_Network --
1900 ----------------------
1902 function Short_To_Network
(S
: C
.unsigned_short
) return C
.unsigned_short
is
1903 use type C
.unsigned_short
;
1906 -- Big-endian case. No conversion needed. On these platforms,
1907 -- htons() defaults to a null procedure.
1909 pragma Warnings
(Off
);
1910 -- Since the test can generate "always True/False" warning
1912 if Default_Bit_Order
= High_Order_First
then
1915 pragma Warnings
(On
);
1917 -- Little-endian case. We must swap the high and low bytes of this
1918 -- short to make the port number network compliant.
1921 return (S
/ 256) + (S
mod 256) * 256;
1923 end Short_To_Network
;
1925 ---------------------
1926 -- Shutdown_Socket --
1927 ---------------------
1929 procedure Shutdown_Socket
1930 (Socket
: Socket_Type
;
1931 How
: Shutmode_Type
:= Shut_Read_Write
)
1936 Res
:= C_Shutdown
(C
.int
(Socket
), Shutmodes
(How
));
1938 if Res
= Failure
then
1939 Raise_Socket_Error
(Socket_Errno
);
1941 end Shutdown_Socket
;
1948 (Socket
: Socket_Type
;
1949 Send_To
: Sock_Addr_Type
) return Stream_Access
1951 S
: Datagram_Socket_Stream_Access
;
1954 S
:= new Datagram_Socket_Stream_Type
;
1957 S
.From
:= Get_Socket_Name
(Socket
);
1958 return Stream_Access
(S
);
1965 function Stream
(Socket
: Socket_Type
) return Stream_Access
is
1966 S
: Stream_Socket_Stream_Access
;
1969 S
:= new Stream_Socket_Stream_Type
;
1971 return Stream_Access
(S
);
1978 function To_C
(Socket
: Socket_Type
) return Integer is
1980 return Integer (Socket
);
1987 function To_Host_Entry
(E
: Hostent
) return Host_Entry_Type
is
1990 Official
: constant String :=
1991 C
.Strings
.Value
(E
.H_Name
);
1993 Aliases
: constant Chars_Ptr_Array
:=
1994 Chars_Ptr_Pointers
.Value
(E
.H_Aliases
);
1995 -- H_Aliases points to a list of name aliases. The list is
1996 -- terminated by a NULL pointer.
1998 Addresses
: constant In_Addr_Access_Array
:=
1999 In_Addr_Access_Pointers
.Value
(E
.H_Addr_List
);
2000 -- H_Addr_List points to a list of binary addresses (in network
2001 -- byte order). The list is terminated by a NULL pointer.
2003 -- H_Length is not used because it is currently only set to 4.
2004 -- H_Addrtype is always AF_INET
2006 Result
: Host_Entry_Type
2007 (Aliases_Length
=> Aliases
'Length - 1,
2008 Addresses_Length
=> Addresses
'Length - 1);
2009 -- The last element is a null pointer
2015 Result
.Official
:= To_Name
(Official
);
2017 Source
:= Aliases
'First;
2018 Target
:= Result
.Aliases
'First;
2019 while Target
<= Result
.Aliases_Length
loop
2020 Result
.Aliases
(Target
) :=
2021 To_Name
(C
.Strings
.Value
(Aliases
(Source
)));
2022 Source
:= Source
+ 1;
2023 Target
:= Target
+ 1;
2026 Source
:= Addresses
'First;
2027 Target
:= Result
.Addresses
'First;
2028 while Target
<= Result
.Addresses_Length
loop
2029 Result
.Addresses
(Target
) :=
2030 To_Inet_Addr
(Addresses
(Source
).all);
2031 Source
:= Source
+ 1;
2032 Target
:= Target
+ 1;
2042 function To_In_Addr
(Addr
: Inet_Addr_Type
) return Thin
.In_Addr
is
2044 if Addr
.Family
= Family_Inet
then
2045 return (S_B1
=> C
.unsigned_char
(Addr
.Sin_V4
(1)),
2046 S_B2
=> C
.unsigned_char
(Addr
.Sin_V4
(2)),
2047 S_B3
=> C
.unsigned_char
(Addr
.Sin_V4
(3)),
2048 S_B4
=> C
.unsigned_char
(Addr
.Sin_V4
(4)));
2058 function To_Inet_Addr
2059 (Addr
: In_Addr
) return Inet_Addr_Type
2061 Result
: Inet_Addr_Type
;
2063 Result
.Sin_V4
(1) := Inet_Addr_Comp_Type
(Addr
.S_B1
);
2064 Result
.Sin_V4
(2) := Inet_Addr_Comp_Type
(Addr
.S_B2
);
2065 Result
.Sin_V4
(3) := Inet_Addr_Comp_Type
(Addr
.S_B3
);
2066 Result
.Sin_V4
(4) := Inet_Addr_Comp_Type
(Addr
.S_B4
);
2074 function To_Int
(F
: Request_Flag_Type
) return C
.int
2076 Current
: Request_Flag_Type
:= F
;
2077 Result
: C
.int
:= 0;
2080 for J
in Flags
'Range loop
2081 exit when Current
= 0;
2083 if Current
mod 2 /= 0 then
2084 if Flags
(J
) = -1 then
2085 Raise_Socket_Error
(Constants
.EOPNOTSUPP
);
2087 Result
:= Result
+ Flags
(J
);
2090 Current
:= Current
/ 2;
2100 function To_Name
(N
: String) return Name_Type
is
2102 return Name_Type
'(N'Length, N);
2105 ----------------------
2106 -- To_Service_Entry --
2107 ----------------------
2109 function To_Service_Entry (E : Servent) return Service_Entry_Type is
2112 Official : constant String :=
2113 C.Strings.Value (E.S_Name);
2115 Aliases : constant Chars_Ptr_Array :=
2116 Chars_Ptr_Pointers.Value (E.S_Aliases);
2117 -- S_Aliases points to a list of name aliases. The list is
2118 -- terminated by a NULL pointer.
2120 Protocol : constant String :=
2121 C.Strings.Value (E.S_Proto);
2123 Result : Service_Entry_Type
2124 (Aliases_Length => Aliases'Length - 1);
2125 -- The last element is a null pointer
2131 Result.Official := To_Name (Official);
2133 Source := Aliases'First;
2134 Target := Result.Aliases'First;
2135 while Target <= Result.Aliases_Length loop
2136 Result.Aliases (Target) :=
2137 To_Name (C.Strings.Value (Aliases (Source)));
2138 Source := Source + 1;
2139 Target := Target + 1;
2143 Port_Type (Network_To_Short (C.unsigned_short (E.S_Port)));
2145 Result.Protocol := To_Name (Protocol);
2148 end To_Service_Entry;
2154 function To_String (HN : Name_Type) return String is
2156 return HN.Name (1 .. HN.Length);
2163 function To_Timeval (Val : Selector_Duration) return Timeval is
2168 -- If zero, set result as zero (otherwise it gets rounded down to -1)
2174 -- Normal case where we do round down
2177 S := Timeval_Unit (Val - 0.5);
2178 MS := Timeval_Unit (1_000_000 * (Val - Selector_Duration (S)));
2189 (Stream : in out Datagram_Socket_Stream_Type;
2190 Item : Ada.Streams.Stream_Element_Array)
2192 First : Ada.Streams.Stream_Element_Offset := Item'First;
2193 Index : Ada.Streams.Stream_Element_Offset := First - 1;
2194 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2200 Item (First .. Max),
2204 -- Exit when all or zero data sent. Zero means that the
2205 -- socket has been closed by peer.
2207 exit when Index < First or else Index = Max;
2212 if Index /= Max then
2222 (Stream : in out Stream_Socket_Stream_Type;
2223 Item : Ada.Streams.Stream_Element_Array)
2225 First : Ada.Streams.Stream_Element_Offset := Item'First;
2226 Index : Ada.Streams.Stream_Element_Offset := First - 1;
2227 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2231 Send_Socket (Stream.Socket, Item (First .. Max), Index);
2233 -- Exit when all or zero data sent. Zero means that the
2234 -- socket has been closed by peer.
2236 exit when Index < First or else Index = Max;
2241 if Index /= Max then