1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . S O C K E T S --
9 -- Copyright (C) 2001-2004 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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, 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
.OS_Lib
; use GNAT
.OS_Lib
;
41 with GNAT
.Sockets
.Constants
;
42 with GNAT
.Sockets
.Thin
; use GNAT
.Sockets
.Thin
;
45 with GNAT
.Sockets
.Linker_Options
;
46 pragma Warnings
(Off
, GNAT
.Sockets
.Linker_Options
);
47 -- Need to include pragma Linker_Options which is platform dependent
49 with System
; use System
;
51 package body GNAT
.Sockets
is
53 use type C
.int
, System
.Address
;
55 Finalized
: Boolean := False;
56 Initialized
: Boolean := False;
58 ENOERROR
: constant := 0;
60 -- Correspondance tables
62 Families
: constant array (Family_Type
) of C
.int
:=
63 (Family_Inet
=> Constants
.AF_INET
,
64 Family_Inet6
=> Constants
.AF_INET6
);
66 Levels
: constant array (Level_Type
) of C
.int
:=
67 (Socket_Level
=> Constants
.SOL_SOCKET
,
68 IP_Protocol_For_IP_Level
=> Constants
.IPPROTO_IP
,
69 IP_Protocol_For_UDP_Level
=> Constants
.IPPROTO_UDP
,
70 IP_Protocol_For_TCP_Level
=> Constants
.IPPROTO_TCP
);
72 Modes
: constant array (Mode_Type
) of C
.int
:=
73 (Socket_Stream
=> Constants
.SOCK_STREAM
,
74 Socket_Datagram
=> Constants
.SOCK_DGRAM
);
76 Shutmodes
: constant array (Shutmode_Type
) of C
.int
:=
77 (Shut_Read
=> Constants
.SHUT_RD
,
78 Shut_Write
=> Constants
.SHUT_WR
,
79 Shut_Read_Write
=> Constants
.SHUT_RDWR
);
81 Requests
: constant array (Request_Name
) of C
.int
:=
82 (Non_Blocking_IO
=> Constants
.FIONBIO
,
83 N_Bytes_To_Read
=> Constants
.FIONREAD
);
85 Options
: constant array (Option_Name
) of C
.int
:=
86 (Keep_Alive
=> Constants
.SO_KEEPALIVE
,
87 Reuse_Address
=> Constants
.SO_REUSEADDR
,
88 Broadcast
=> Constants
.SO_BROADCAST
,
89 Send_Buffer
=> Constants
.SO_SNDBUF
,
90 Receive_Buffer
=> Constants
.SO_RCVBUF
,
91 Linger
=> Constants
.SO_LINGER
,
92 Error
=> Constants
.SO_ERROR
,
93 No_Delay
=> Constants
.TCP_NODELAY
,
94 Add_Membership
=> Constants
.IP_ADD_MEMBERSHIP
,
95 Drop_Membership
=> Constants
.IP_DROP_MEMBERSHIP
,
96 Multicast_TTL
=> Constants
.IP_MULTICAST_TTL
,
97 Multicast_Loop
=> Constants
.IP_MULTICAST_LOOP
);
99 Flags
: constant array (0 .. 3) of C
.int
:=
100 (0 => Constants
.MSG_OOB
, -- Process_Out_Of_Band_Data
101 1 => Constants
.MSG_PEEK
, -- Peek_At_Incoming_Data
102 2 => Constants
.MSG_WAITALL
, -- Wait_For_A_Full_Reception
103 3 => Constants
.MSG_EOR
); -- Send_End_Of_Record
105 Socket_Error_Id
: constant Exception_Id
:= Socket_Error
'Identity;
106 Host_Error_Id
: constant Exception_Id
:= Host_Error
'Identity;
108 Hex_To_Char
: constant String (1 .. 16) := "0123456789ABCDEF";
109 -- Use to print in hexadecimal format
111 function To_In_Addr
is new Ada
.Unchecked_Conversion
(C
.int
, In_Addr
);
112 function To_Int
is new Ada
.Unchecked_Conversion
(In_Addr
, C
.int
);
114 -----------------------
115 -- Local subprograms --
116 -----------------------
118 function Resolve_Error
119 (Error_Value
: Integer;
120 From_Errno
: Boolean := True)
122 -- Associate an enumeration value (error_type) to en error value
123 -- (errno). From_Errno prevents from mixing h_errno with errno.
125 function To_Name
(N
: String) return Name_Type
;
126 function To_String
(HN
: Name_Type
) return String;
127 -- Conversion functions
129 function To_Int
(F
: Request_Flag_Type
) return C
.int
;
131 function Short_To_Network
132 (S
: C
.unsigned_short
)
133 return C
.unsigned_short
;
134 pragma Inline
(Short_To_Network
);
135 -- Convert a port number into a network port number
137 function Network_To_Short
138 (S
: C
.unsigned_short
)
139 return C
.unsigned_short
140 renames Short_To_Network
;
141 -- Symetric operation
144 (Val
: Inet_Addr_VN_Type
;
145 Hex
: Boolean := False)
147 -- Output an array of inet address components either in
148 -- hexadecimal or in decimal mode.
150 function Is_IP_Address
(Name
: String) return Boolean;
151 -- Return true when Name is an IP address in standard dot notation.
153 function To_In_Addr
(Addr
: Inet_Addr_Type
) return Thin
.In_Addr
;
154 function To_Inet_Addr
(Addr
: In_Addr
) return Inet_Addr_Type
;
155 -- Conversion functions
157 function To_Host_Entry
(E
: Hostent
) return Host_Entry_Type
;
158 -- Conversion function
160 function To_Service_Entry
(E
: Servent
) return Service_Entry_Type
;
161 -- Conversion function
163 function To_Timeval
(Val
: Selector_Duration
) return Timeval
;
164 -- Separate Val in seconds and microseconds
166 procedure Raise_Socket_Error
(Error
: Integer);
167 -- Raise Socket_Error with an exception message describing
170 procedure Raise_Host_Error
(Error
: Integer);
171 -- Raise Host_Error exception with message describing error code
172 -- (note hstrerror seems to be obsolete).
174 procedure Narrow
(Item
: in out Socket_Set_Type
);
175 -- Update Last as it may be greater than the real last socket.
177 -- Types needed for Datagram_Socket_Stream_Type
179 type Datagram_Socket_Stream_Type
is new Root_Stream_Type
with record
180 Socket
: Socket_Type
;
182 From
: Sock_Addr_Type
;
185 type Datagram_Socket_Stream_Access
is
186 access all Datagram_Socket_Stream_Type
;
189 (Stream
: in out Datagram_Socket_Stream_Type
;
190 Item
: out Ada
.Streams
.Stream_Element_Array
;
191 Last
: out Ada
.Streams
.Stream_Element_Offset
);
194 (Stream
: in out Datagram_Socket_Stream_Type
;
195 Item
: Ada
.Streams
.Stream_Element_Array
);
197 -- Types needed for Stream_Socket_Stream_Type
199 type Stream_Socket_Stream_Type
is new Root_Stream_Type
with record
200 Socket
: Socket_Type
;
203 type Stream_Socket_Stream_Access
is
204 access all Stream_Socket_Stream_Type
;
207 (Stream
: in out Stream_Socket_Stream_Type
;
208 Item
: out Ada
.Streams
.Stream_Element_Array
;
209 Last
: out Ada
.Streams
.Stream_Element_Offset
);
212 (Stream
: in out Stream_Socket_Stream_Type
;
213 Item
: Ada
.Streams
.Stream_Element_Array
);
219 function "+" (L
, R
: Request_Flag_Type
) return Request_Flag_Type
is
228 procedure Abort_Selector
(Selector
: Selector_Type
) is
229 Buf
: aliased Character := ASCII
.NUL
;
231 pragma Unreferenced
(Discard
);
234 -- Send an empty array to unblock C select system call
236 Discard
:= C_Write
(C
.int
(Selector
.W_Sig_Socket
), Buf
'Address, 1);
243 procedure Accept_Socket
244 (Server
: Socket_Type
;
245 Socket
: out Socket_Type
;
246 Address
: out Sock_Addr_Type
)
249 Sin
: aliased Sockaddr_In
;
250 Len
: aliased C
.int
:= Sin
'Size / 8;
253 Res
:= C_Accept
(C
.int
(Server
), Sin
'Address, Len
'Access);
255 if Res
= Failure
then
256 Raise_Socket_Error
(Socket_Errno
);
259 Socket
:= Socket_Type
(Res
);
261 Address
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
262 Address
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
270 (E
: Host_Entry_Type
;
272 return Inet_Addr_Type
275 return E
.Addresses
(N
);
278 ----------------------
279 -- Addresses_Length --
280 ----------------------
282 function Addresses_Length
(E
: Host_Entry_Type
) return Natural is
284 return E
.Addresses_Length
;
285 end Addresses_Length
;
292 (E
: Host_Entry_Type
;
297 return To_String
(E
.Aliases
(N
));
305 (S
: Service_Entry_Type
;
310 return To_String
(S
.Aliases
(N
));
317 function Aliases_Length
(E
: Host_Entry_Type
) return Natural is
319 return E
.Aliases_Length
;
326 function Aliases_Length
(S
: Service_Entry_Type
) return Natural is
328 return S
.Aliases_Length
;
335 procedure Bind_Socket
336 (Socket
: Socket_Type
;
337 Address
: Sock_Addr_Type
)
340 Sin
: aliased Sockaddr_In
;
341 Len
: constant C
.int
:= Sin
'Size / 8;
344 if Address
.Family
= Family_Inet6
then
348 Set_Length
(Sin
'Unchecked_Access, Len
);
349 Set_Family
(Sin
'Unchecked_Access, Families
(Address
.Family
));
351 (Sin
'Unchecked_Access,
352 Short_To_Network
(C
.unsigned_short
(Address
.Port
)));
354 Res
:= C_Bind
(C
.int
(Socket
), Sin
'Address, Len
);
356 if Res
= Failure
then
357 Raise_Socket_Error
(Socket_Errno
);
365 procedure Check_Selector
366 (Selector
: in out Selector_Type
;
367 R_Socket_Set
: in out Socket_Set_Type
;
368 W_Socket_Set
: in out Socket_Set_Type
;
369 Status
: out Selector_Status
;
370 Timeout
: Selector_Duration
:= Forever
)
372 E_Socket_Set
: Socket_Set_Type
; -- (No_Socket, No_Socket_Set)
375 (Selector
, R_Socket_Set
, W_Socket_Set
, E_Socket_Set
, Status
, Timeout
);
378 procedure Check_Selector
379 (Selector
: in out Selector_Type
;
380 R_Socket_Set
: in out Socket_Set_Type
;
381 W_Socket_Set
: in out Socket_Set_Type
;
382 E_Socket_Set
: in out Socket_Set_Type
;
383 Status
: out Selector_Status
;
384 Timeout
: Selector_Duration
:= Forever
)
388 RSet
: Socket_Set_Type
;
389 WSet
: Socket_Set_Type
;
390 ESet
: Socket_Set_Type
;
391 TVal
: aliased Timeval
;
392 TPtr
: Timeval_Access
;
397 -- No timeout or Forever is indicated by a null timeval pointer
399 if Timeout
= Forever
then
402 TVal
:= To_Timeval
(Timeout
);
403 TPtr
:= TVal
'Unchecked_Access;
406 -- Copy R_Socket_Set in RSet and add read signalling socket
408 RSet
:= (Set
=> New_Socket_Set
(R_Socket_Set
.Set
),
409 Last
=> R_Socket_Set
.Last
);
410 Set
(RSet
, Selector
.R_Sig_Socket
);
412 -- Copy W_Socket_Set in WSet
414 WSet
:= (Set
=> New_Socket_Set
(W_Socket_Set
.Set
),
415 Last
=> W_Socket_Set
.Last
);
417 -- Copy E_Socket_Set in ESet
419 ESet
:= (Set
=> New_Socket_Set
(E_Socket_Set
.Set
),
420 Last
=> E_Socket_Set
.Last
);
422 Last
:= C
.int
'Max (C
.int
'Max (C
.int
(RSet
.Last
),
434 -- If Select was resumed because of read signalling socket,
435 -- read this data and remove socket from set.
437 if Is_Set
(RSet
, Selector
.R_Sig_Socket
) then
438 Clear
(RSet
, Selector
.R_Sig_Socket
);
443 Res
:= C_Read
(C
.int
(Selector
.R_Sig_Socket
), Buf
'Address, 1);
452 -- Update RSet, WSet and ESet in regard to their new socket
459 -- Reset RSet as it should be if R_Sig_Socket was not added.
461 if Is_Empty
(RSet
) then
465 if Is_Empty
(WSet
) then
469 if Is_Empty
(ESet
) then
473 -- Deliver RSet, WSet and ESet.
475 Empty
(R_Socket_Set
);
476 R_Socket_Set
:= RSet
;
478 Empty
(W_Socket_Set
);
479 W_Socket_Set
:= WSet
;
481 Empty
(E_Socket_Set
);
482 E_Socket_Set
:= ESet
;
490 (Item
: in out Socket_Set_Type
;
491 Socket
: Socket_Type
)
493 Last
: aliased C
.int
:= C
.int
(Item
.Last
);
496 if Item
.Last
/= No_Socket
then
497 Remove_Socket_From_Set
(Item
.Set
, C
.int
(Socket
));
498 Last_Socket_In_Set
(Item
.Set
, Last
'Unchecked_Access);
499 Item
.Last
:= Socket_Type
(Last
);
507 -- Comments needed below ???
508 -- Why are exceptions ignored ???
510 procedure Close_Selector
(Selector
: in out Selector_Type
) is
513 Close_Socket
(Selector
.R_Sig_Socket
);
521 Close_Socket
(Selector
.W_Sig_Socket
);
533 procedure Close_Socket
(Socket
: Socket_Type
) is
537 Res
:= C_Close
(C
.int
(Socket
));
539 if Res
= Failure
then
540 Raise_Socket_Error
(Socket_Errno
);
548 procedure Connect_Socket
549 (Socket
: Socket_Type
;
550 Server
: in out Sock_Addr_Type
)
553 Sin
: aliased Sockaddr_In
;
554 Len
: constant C
.int
:= Sin
'Size / 8;
557 if Server
.Family
= Family_Inet6
then
561 Set_Length
(Sin
'Unchecked_Access, Len
);
562 Set_Family
(Sin
'Unchecked_Access, Families
(Server
.Family
));
563 Set_Address
(Sin
'Unchecked_Access, To_In_Addr
(Server
.Addr
));
565 (Sin
'Unchecked_Access,
566 Short_To_Network
(C
.unsigned_short
(Server
.Port
)));
568 Res
:= C_Connect
(C
.int
(Socket
), Sin
'Address, Len
);
570 if Res
= Failure
then
571 Raise_Socket_Error
(Socket_Errno
);
579 procedure Control_Socket
580 (Socket
: Socket_Type
;
581 Request
: in out Request_Type
)
588 when Non_Blocking_IO
=>
589 Arg
:= C
.int
(Boolean'Pos (Request
.Enabled
));
591 when N_Bytes_To_Read
=>
598 Requests
(Request
.Name
),
599 Arg
'Unchecked_Access);
601 if Res
= Failure
then
602 Raise_Socket_Error
(Socket_Errno
);
606 when Non_Blocking_IO
=>
609 when N_Bytes_To_Read
=>
610 Request
.Size
:= Natural (Arg
);
620 (Source
: Socket_Set_Type
;
621 Target
: in out Socket_Set_Type
)
625 if Source
.Last
/= No_Socket
then
626 Target
.Set
:= New_Socket_Set
(Source
.Set
);
627 Target
.Last
:= Source
.Last
;
631 ---------------------
632 -- Create_Selector --
633 ---------------------
635 procedure Create_Selector
(Selector
: out Selector_Type
) is
640 Sin
: aliased Sockaddr_In
;
641 Len
: aliased C
.int
:= Sin
'Size / 8;
645 -- We open two signalling sockets. One of them is used to
646 -- send data to the other, which is included in a C_Select
647 -- socket set. The communication is used to force the call
648 -- to C_Select to complete, and the waiting task to resume
651 -- Create a listening socket
653 S0
:= C_Socket
(Constants
.AF_INET
, Constants
.SOCK_STREAM
, 0);
655 Raise_Socket_Error
(Socket_Errno
);
658 -- Sin is already correctly initialized. Bind the socket to any
661 Res
:= C_Bind
(S0
, Sin
'Address, Len
);
662 if Res
= Failure
then
665 Raise_Socket_Error
(Err
);
668 -- Get the port used by the socket
670 Res
:= C_Getsockname
(S0
, Sin
'Address, Len
'Access);
672 if Res
= Failure
then
675 Raise_Socket_Error
(Err
);
678 Res
:= C_Listen
(S0
, 2);
680 if Res
= Failure
then
683 Raise_Socket_Error
(Err
);
686 S1
:= C_Socket
(Constants
.AF_INET
, Constants
.SOCK_STREAM
, 0);
691 Raise_Socket_Error
(Err
);
694 -- Use INADDR_LOOPBACK
696 Sin
.Sin_Addr
.S_B1
:= 127;
697 Sin
.Sin_Addr
.S_B2
:= 0;
698 Sin
.Sin_Addr
.S_B3
:= 0;
699 Sin
.Sin_Addr
.S_B4
:= 1;
701 -- Do a connect and accept the connection
703 Res
:= C_Connect
(S1
, Sin
'Address, Len
);
705 if Res
= Failure
then
709 Raise_Socket_Error
(Err
);
712 S2
:= C_Accept
(S0
, Sin
'Address, Len
'Access);
718 Raise_Socket_Error
(Err
);
723 if Res
= Failure
then
724 Raise_Socket_Error
(Socket_Errno
);
727 Selector
.R_Sig_Socket
:= Socket_Type
(S1
);
728 Selector
.W_Sig_Socket
:= Socket_Type
(S2
);
735 procedure Create_Socket
736 (Socket
: out Socket_Type
;
737 Family
: Family_Type
:= Family_Inet
;
738 Mode
: Mode_Type
:= Socket_Stream
)
743 Res
:= C_Socket
(Families
(Family
), Modes
(Mode
), 0);
745 if Res
= Failure
then
746 Raise_Socket_Error
(Socket_Errno
);
749 Socket
:= Socket_Type
(Res
);
756 procedure Empty
(Item
: in out Socket_Set_Type
) is
758 if Item
.Set
/= No_Socket_Set
then
759 Free_Socket_Set
(Item
.Set
);
760 Item
.Set
:= No_Socket_Set
;
763 Item
.Last
:= No_Socket
;
770 procedure Finalize
is
785 (Item
: in out Socket_Set_Type
;
786 Socket
: out Socket_Type
)
789 L
: aliased C
.int
:= C
.int
(Item
.Last
);
792 if Item
.Last
/= No_Socket
then
794 (Item
.Set
, L
'Unchecked_Access, S
'Unchecked_Access);
795 Item
.Last
:= Socket_Type
(L
);
796 Socket
:= Socket_Type
(S
);
806 function Get_Address
(Stream
: Stream_Access
) return Sock_Addr_Type
is
808 if Stream
= null then
811 elsif Stream
.all in Datagram_Socket_Stream_Type
then
812 return Datagram_Socket_Stream_Type
(Stream
.all).From
;
815 return Get_Peer_Name
(Stream_Socket_Stream_Type
(Stream
.all).Socket
);
819 -------------------------
820 -- Get_Host_By_Address --
821 -------------------------
823 function Get_Host_By_Address
824 (Address
: Inet_Addr_Type
;
825 Family
: Family_Type
:= Family_Inet
)
826 return Host_Entry_Type
828 pragma Unreferenced
(Family
);
830 HA
: aliased In_Addr
:= To_In_Addr
(Address
);
831 Res
: Hostent_Access
;
835 -- This C function is not always thread-safe. Protect against
836 -- concurrent access.
839 Res
:= C_Gethostbyaddr
(HA
'Address, HA
'Size / 8, Constants
.AF_INET
);
844 Raise_Host_Error
(Err
);
847 -- Translate from the C format to the API format
850 HE
: constant Host_Entry_Type
:= To_Host_Entry
(Res
.all);
856 end Get_Host_By_Address
;
858 ----------------------
859 -- Get_Host_By_Name --
860 ----------------------
862 function Get_Host_By_Name
(Name
: String) return Host_Entry_Type
is
863 HN
: constant C
.char_array
:= C
.To_C
(Name
);
864 Res
: Hostent_Access
;
868 -- Detect IP address name and redirect to Inet_Addr.
870 if Is_IP_Address
(Name
) then
871 return Get_Host_By_Address
(Inet_Addr
(Name
));
874 -- This C function is not always thread-safe. Protect against
875 -- concurrent access.
878 Res
:= C_Gethostbyname
(HN
);
883 Raise_Host_Error
(Err
);
886 -- Translate from the C format to the API format
889 HE
: constant Host_Entry_Type
:= To_Host_Entry
(Res
.all);
895 end Get_Host_By_Name
;
901 function Get_Peer_Name
(Socket
: Socket_Type
) return Sock_Addr_Type
is
902 Sin
: aliased Sockaddr_In
;
903 Len
: aliased C
.int
:= Sin
'Size / 8;
904 Res
: Sock_Addr_Type
(Family_Inet
);
907 if C_Getpeername
(C
.int
(Socket
), Sin
'Address, Len
'Access) = Failure
then
908 Raise_Socket_Error
(Socket_Errno
);
911 Res
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
912 Res
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
917 -------------------------
918 -- Get_Service_By_Name --
919 -------------------------
921 function Get_Service_By_Name
924 return Service_Entry_Type
926 SN
: constant C
.char_array
:= C
.To_C
(Name
);
927 SP
: constant C
.char_array
:= C
.To_C
(Protocol
);
928 Res
: Servent_Access
;
931 -- This C function is not always thread-safe. Protect against
932 -- concurrent access.
935 Res
:= C_Getservbyname
(SN
, SP
);
939 Ada
.Exceptions
.Raise_Exception
940 (Service_Error
'Identity, "Service not found");
943 -- Translate from the C format to the API format
946 SE
: constant Service_Entry_Type
:= To_Service_Entry
(Res
.all);
952 end Get_Service_By_Name
;
954 -------------------------
955 -- Get_Service_By_Port --
956 -------------------------
958 function Get_Service_By_Port
961 return Service_Entry_Type
963 SP
: constant C
.char_array
:= C
.To_C
(Protocol
);
964 Res
: Servent_Access
;
967 -- This C function is not always thread-safe. Protect against
968 -- concurrent access.
971 Res
:= C_Getservbyport
972 (C
.int
(Short_To_Network
(C
.unsigned_short
(Port
))), SP
);
976 Ada
.Exceptions
.Raise_Exception
977 (Service_Error
'Identity, "Service not found");
980 -- Translate from the C format to the API format
983 SE
: constant Service_Entry_Type
:= To_Service_Entry
(Res
.all);
989 end Get_Service_By_Port
;
991 ---------------------
992 -- Get_Socket_Name --
993 ---------------------
995 function Get_Socket_Name
996 (Socket
: Socket_Type
)
997 return Sock_Addr_Type
999 Sin
: aliased Sockaddr_In
;
1000 Len
: aliased C
.int
:= Sin
'Size / 8;
1002 Addr
: Sock_Addr_Type
:= No_Sock_Addr
;
1005 Res
:= C_Getsockname
(C
.int
(Socket
), Sin
'Address, Len
'Access);
1006 if Res
/= Failure
then
1007 Addr
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
1008 Addr
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
1012 end Get_Socket_Name
;
1014 -----------------------
1015 -- Get_Socket_Option --
1016 -----------------------
1018 function Get_Socket_Option
1019 (Socket
: Socket_Type
;
1020 Level
: Level_Type
:= Socket_Level
;
1024 use type C
.unsigned_char
;
1026 V8
: aliased Two_Int
;
1028 V1
: aliased C
.unsigned_char
;
1029 Len
: aliased C
.int
;
1030 Add
: System
.Address
;
1032 Opt
: Option_Type
(Name
);
1036 when Multicast_Loop |
1064 Add
, Len
'Unchecked_Access);
1066 if Res
= Failure
then
1067 Raise_Socket_Error
(Socket_Errno
);
1075 Opt
.Enabled
:= (V4
/= 0);
1078 Opt
.Enabled
:= (V8
(V8
'First) /= 0);
1079 Opt
.Seconds
:= Natural (V8
(V8
'Last));
1083 Opt
.Size
:= Natural (V4
);
1086 Opt
.Error
:= Resolve_Error
(Integer (V4
));
1088 when Add_Membership |
1090 Opt
.Multiaddr
:= To_Inet_Addr
(To_In_Addr
(V8
(V8
'First)));
1091 Opt
.Interface
:= To_Inet_Addr
(To_In_Addr
(V8
(V8
'Last)));
1093 when Multicast_TTL
=>
1094 Opt
.Time_To_Live
:= Integer (V1
);
1096 when Multicast_Loop
=>
1097 Opt
.Enabled
:= (V1
/= 0);
1102 end Get_Socket_Option
;
1108 function Host_Name
return String is
1109 Name
: aliased C
.char_array
(1 .. 64);
1113 Res
:= C_Gethostname
(Name
'Address, Name
'Length);
1115 if Res
= Failure
then
1116 Raise_Socket_Error
(Socket_Errno
);
1119 return C
.To_Ada
(Name
);
1127 (Val
: Inet_Addr_VN_Type
;
1128 Hex
: Boolean := False)
1131 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
1132 -- has at most a length of 3 plus one '.' character.
1134 Buffer
: String (1 .. 4 * Val
'Length);
1135 Length
: Natural := 1;
1136 Separator
: Character;
1138 procedure Img10
(V
: Inet_Addr_Comp_Type
);
1139 -- Append to Buffer image of V in decimal format
1141 procedure Img16
(V
: Inet_Addr_Comp_Type
);
1142 -- Append to Buffer image of V in hexadecimal format
1144 procedure Img10
(V
: Inet_Addr_Comp_Type
) is
1145 Img
: constant String := V
'Img;
1146 Len
: constant Natural := Img
'Length - 1;
1149 Buffer
(Length
.. Length
+ Len
- 1) := Img
(2 .. Img
'Last);
1150 Length
:= Length
+ Len
;
1153 procedure Img16
(V
: Inet_Addr_Comp_Type
) is
1155 Buffer
(Length
) := Hex_To_Char
(Natural (V
/ 16) + 1);
1156 Buffer
(Length
+ 1) := Hex_To_Char
(Natural (V
mod 16) + 1);
1157 Length
:= Length
+ 2;
1160 -- Start of processing for Image
1169 for J
in Val
'Range loop
1176 if J
/= Val
'Last then
1177 Buffer
(Length
) := Separator
;
1178 Length
:= Length
+ 1;
1182 return Buffer
(1 .. Length
- 1);
1189 function Image
(Value
: Inet_Addr_Type
) return String is
1191 if Value
.Family
= Family_Inet
then
1192 return Image
(Inet_Addr_VN_Type
(Value
.Sin_V4
), Hex
=> False);
1194 return Image
(Inet_Addr_VN_Type
(Value
.Sin_V6
), Hex
=> True);
1202 function Image
(Value
: Sock_Addr_Type
) return String is
1203 Port
: constant String := Value
.Port
'Img;
1206 return Image
(Value
.Addr
) & ':' & Port
(2 .. Port
'Last);
1213 function Image
(Socket
: Socket_Type
) return String is
1222 function Inet_Addr
(Image
: String) return Inet_Addr_Type
is
1223 use Interfaces
.C
.Strings
;
1225 Img
: chars_ptr
:= New_String
(Image
);
1230 Res
:= C_Inet_Addr
(Img
);
1234 if Res
= Failure
then
1235 Raise_Socket_Error
(Err
);
1238 return To_Inet_Addr
(To_In_Addr
(Res
));
1245 procedure Initialize
(Process_Blocking_IO
: Boolean := False) is
1247 if not Initialized
then
1248 Initialized
:= True;
1249 Thin
.Initialize
(Process_Blocking_IO
);
1257 function Is_Empty
(Item
: Socket_Set_Type
) return Boolean is
1259 return Item
.Last
= No_Socket
;
1266 function Is_IP_Address
(Name
: String) return Boolean is
1268 for J
in Name
'Range loop
1270 and then Name
(J
) not in '0' .. '9'
1284 (Item
: Socket_Set_Type
;
1285 Socket
: Socket_Type
)
1289 return Item
.Last
/= No_Socket
1290 and then Socket
<= Item
.Last
1291 and then Is_Socket_In_Set
(Item
.Set
, C
.int
(Socket
)) /= 0;
1298 procedure Listen_Socket
1299 (Socket
: Socket_Type
;
1300 Length
: Positive := 15)
1305 Res
:= C_Listen
(C
.int
(Socket
), C
.int
(Length
));
1306 if Res
= Failure
then
1307 Raise_Socket_Error
(Socket_Errno
);
1315 procedure Narrow
(Item
: in out Socket_Set_Type
) is
1316 Last
: aliased C
.int
:= C
.int
(Item
.Last
);
1319 if Item
.Set
/= No_Socket_Set
then
1320 Last_Socket_In_Set
(Item
.Set
, Last
'Unchecked_Access);
1321 Item
.Last
:= Socket_Type
(Last
);
1329 function Official_Name
(E
: Host_Entry_Type
) return String is
1331 return To_String
(E
.Official
);
1338 function Official_Name
(S
: Service_Entry_Type
) return String is
1340 return To_String
(S
.Official
);
1347 function Port_Number
(S
: Service_Entry_Type
) return Port_Type
is
1356 function Protocol_Name
(S
: Service_Entry_Type
) return String is
1358 return To_String
(S
.Protocol
);
1361 ----------------------
1362 -- Raise_Host_Error --
1363 ----------------------
1365 procedure Raise_Host_Error
(Error
: Integer) is
1367 function Error_Message
return String;
1368 -- We do not use a C function like strerror because hstrerror
1369 -- that would correspond seems to be obsolete. Return
1370 -- appropriate string for error value.
1372 function Error_Message
return String is
1375 when Constants
.HOST_NOT_FOUND
=> return "Host not found";
1376 when Constants
.TRY_AGAIN
=> return "Try again";
1377 when Constants
.NO_RECOVERY
=> return "No recovery";
1378 when Constants
.NO_DATA
=> return "No address";
1379 when others => return "Unknown error";
1383 -- Start of processing for Raise_Host_Error
1386 Ada
.Exceptions
.Raise_Exception
(Host_Error
'Identity, Error_Message
);
1387 end Raise_Host_Error
;
1389 ------------------------
1390 -- Raise_Socket_Error --
1391 ------------------------
1393 procedure Raise_Socket_Error
(Error
: Integer) is
1394 use type C
.Strings
.chars_ptr
;
1396 function Image
(E
: Integer) return String;
1397 function Image
(E
: Integer) return String is
1398 Msg
: String := E
'Img & "] ";
1400 Msg
(Msg
'First) := '[';
1405 Ada
.Exceptions
.Raise_Exception
1406 (Socket_Error
'Identity,
1407 Image
(Error
) & C
.Strings
.Value
(Socket_Error_Message
(Error
)));
1408 end Raise_Socket_Error
;
1415 (Stream
: in out Datagram_Socket_Stream_Type
;
1416 Item
: out Ada
.Streams
.Stream_Element_Array
;
1417 Last
: out Ada
.Streams
.Stream_Element_Offset
)
1419 First
: Ada
.Streams
.Stream_Element_Offset
:= Item
'First;
1420 Index
: Ada
.Streams
.Stream_Element_Offset
:= First
- 1;
1421 Max
: constant Ada
.Streams
.Stream_Element_Offset
:= Item
'Last;
1427 Item
(First
.. Max
),
1433 -- Exit when all or zero data received. Zero means that
1434 -- the socket peer is closed.
1436 exit when Index
< First
or else Index
= Max
;
1447 (Stream
: in out Stream_Socket_Stream_Type
;
1448 Item
: out Ada
.Streams
.Stream_Element_Array
;
1449 Last
: out Ada
.Streams
.Stream_Element_Offset
)
1451 First
: Ada
.Streams
.Stream_Element_Offset
:= Item
'First;
1452 Index
: Ada
.Streams
.Stream_Element_Offset
:= First
- 1;
1453 Max
: constant Ada
.Streams
.Stream_Element_Offset
:= Item
'Last;
1457 Receive_Socket
(Stream
.Socket
, Item
(First
.. Max
), Index
);
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
;
1469 --------------------
1470 -- Receive_Socket --
1471 --------------------
1473 procedure Receive_Socket
1474 (Socket
: Socket_Type
;
1475 Item
: out Ada
.Streams
.Stream_Element_Array
;
1476 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1477 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1479 use type Ada
.Streams
.Stream_Element_Offset
;
1486 Item
(Item
'First)'Address,
1490 if Res
= Failure
then
1491 Raise_Socket_Error
(Socket_Errno
);
1494 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1497 --------------------
1498 -- Receive_Socket --
1499 --------------------
1501 procedure Receive_Socket
1502 (Socket
: Socket_Type
;
1503 Item
: out Ada
.Streams
.Stream_Element_Array
;
1504 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1505 From
: out Sock_Addr_Type
;
1506 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1508 use type Ada
.Streams
.Stream_Element_Offset
;
1511 Sin
: aliased Sockaddr_In
;
1512 Len
: aliased C
.int
:= Sin
'Size / 8;
1518 Item
(Item
'First)'Address,
1521 Sin
'Unchecked_Access,
1522 Len
'Unchecked_Access);
1524 if Res
= Failure
then
1525 Raise_Socket_Error
(Socket_Errno
);
1528 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1530 From
.Addr
:= To_Inet_Addr
(Sin
.Sin_Addr
);
1531 From
.Port
:= Port_Type
(Network_To_Short
(Sin
.Sin_Port
));
1538 function Resolve_Error
1539 (Error_Value
: Integer;
1540 From_Errno
: Boolean := True)
1543 use GNAT
.Sockets
.Constants
;
1546 if not From_Errno
then
1548 when Constants
.HOST_NOT_FOUND
=> return Unknown_Host
;
1549 when Constants
.TRY_AGAIN
=> return Host_Name_Lookup_Failure
;
1550 when Constants
.NO_RECOVERY
=>
1551 return Non_Recoverable_Error
;
1552 when Constants
.NO_DATA
=> return Unknown_Server_Error
;
1553 when others => return Cannot_Resolve_Error
;
1558 when ENOERROR
=> return Success
;
1559 when EACCES
=> return Permission_Denied
;
1560 when EADDRINUSE
=> return Address_Already_In_Use
;
1561 when EADDRNOTAVAIL
=> return Cannot_Assign_Requested_Address
;
1562 when EAFNOSUPPORT
=>
1563 return Address_Family_Not_Supported_By_Protocol
;
1564 when EALREADY
=> return Operation_Already_In_Progress
;
1565 when EBADF
=> return Bad_File_Descriptor
;
1566 when ECONNABORTED
=> return Software_Caused_Connection_Abort
;
1567 when ECONNREFUSED
=> return Connection_Refused
;
1568 when ECONNRESET
=> return Connection_Reset_By_Peer
;
1569 when EDESTADDRREQ
=> return Destination_Address_Required
;
1570 when EFAULT
=> return Bad_Address
;
1571 when EHOSTDOWN
=> return Host_Is_Down
;
1572 when EHOSTUNREACH
=> return No_Route_To_Host
;
1573 when EINPROGRESS
=> return Operation_Now_In_Progress
;
1574 when EINTR
=> return Interrupted_System_Call
;
1575 when EINVAL
=> return Invalid_Argument
;
1576 when EIO
=> return Input_Output_Error
;
1577 when EISCONN
=> return Transport_Endpoint_Already_Connected
;
1578 when ELOOP
=> return Too_Many_Symbolic_Links
;
1579 when EMFILE
=> return Too_Many_Open_Files
;
1580 when EMSGSIZE
=> return Message_Too_Long
;
1581 when ENAMETOOLONG
=> return File_Name_Too_Long
;
1582 when ENETDOWN
=> return Network_Is_Down
;
1584 return Network_Dropped_Connection_Because_Of_Reset
;
1585 when ENETUNREACH
=> return Network_Is_Unreachable
;
1586 when ENOBUFS
=> return No_Buffer_Space_Available
;
1587 when ENOPROTOOPT
=> return Protocol_Not_Available
;
1588 when ENOTCONN
=> return Transport_Endpoint_Not_Connected
;
1589 when ENOTSOCK
=> return Socket_Operation_On_Non_Socket
;
1590 when EOPNOTSUPP
=> return Operation_Not_Supported
;
1591 when EPFNOSUPPORT
=> return Protocol_Family_Not_Supported
;
1592 when EPROTONOSUPPORT
=> return Protocol_Not_Supported
;
1593 when EPROTOTYPE
=> return Protocol_Wrong_Type_For_Socket
;
1595 return Cannot_Send_After_Transport_Endpoint_Shutdown
;
1596 when ESOCKTNOSUPPORT
=> return Socket_Type_Not_Supported
;
1597 when ETIMEDOUT
=> return Connection_Timed_Out
;
1598 when ETOOMANYREFS
=> return Too_Many_References
;
1599 when EWOULDBLOCK
=> return Resource_Temporarily_Unavailable
;
1600 when others => null;
1603 return Cannot_Resolve_Error
;
1606 -----------------------
1607 -- Resolve_Exception --
1608 -----------------------
1610 function Resolve_Exception
1611 (Occurrence
: Exception_Occurrence
)
1614 Id
: constant Exception_Id
:= Exception_Identity
(Occurrence
);
1615 Msg
: constant String := Exception_Message
(Occurrence
);
1616 First
: Natural := Msg
'First;
1621 while First
<= Msg
'Last
1622 and then Msg
(First
) not in '0' .. '9'
1627 if First
> Msg
'Last then
1628 return Cannot_Resolve_Error
;
1633 while Last
< Msg
'Last
1634 and then Msg
(Last
+ 1) in '0' .. '9'
1639 Val
:= Integer'Value (Msg
(First
.. Last
));
1641 if Id
= Socket_Error_Id
then
1642 return Resolve_Error
(Val
);
1644 elsif Id
= Host_Error_Id
then
1645 return Resolve_Error
(Val
, False);
1648 return Cannot_Resolve_Error
;
1650 end Resolve_Exception
;
1652 --------------------
1653 -- Receive_Vector --
1654 --------------------
1656 procedure Receive_Vector
1657 (Socket
: Socket_Type
;
1658 Vector
: Vector_Type
;
1659 Count
: out Ada
.Streams
.Stream_Element_Count
)
1667 Vector
(Vector
'First)'Address,
1670 if Res
= Failure
then
1671 Raise_Socket_Error
(Socket_Errno
);
1674 Count
:= Ada
.Streams
.Stream_Element_Count
(Res
);
1681 procedure Send_Socket
1682 (Socket
: Socket_Type
;
1683 Item
: Ada
.Streams
.Stream_Element_Array
;
1684 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1685 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1687 use type Ada
.Streams
.Stream_Element_Offset
;
1695 Item
(Item
'First)'Address,
1699 if Res
= Failure
then
1700 Raise_Socket_Error
(Socket_Errno
);
1703 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1710 procedure Send_Socket
1711 (Socket
: Socket_Type
;
1712 Item
: Ada
.Streams
.Stream_Element_Array
;
1713 Last
: out Ada
.Streams
.Stream_Element_Offset
;
1714 To
: Sock_Addr_Type
;
1715 Flags
: Request_Flag_Type
:= No_Request_Flag
)
1717 use type Ada
.Streams
.Stream_Element_Offset
;
1720 Sin
: aliased Sockaddr_In
;
1721 Len
: constant C
.int
:= Sin
'Size / 8;
1724 Set_Length
(Sin
'Unchecked_Access, Len
);
1725 Set_Family
(Sin
'Unchecked_Access, Families
(To
.Family
));
1726 Set_Address
(Sin
'Unchecked_Access, To_In_Addr
(To
.Addr
));
1728 (Sin
'Unchecked_Access,
1729 Short_To_Network
(C
.unsigned_short
(To
.Port
)));
1733 Item
(Item
'First)'Address,
1736 Sin
'Unchecked_Access,
1739 if Res
= Failure
then
1740 Raise_Socket_Error
(Socket_Errno
);
1743 Last
:= Item
'First + Ada
.Streams
.Stream_Element_Offset
(Res
- 1);
1750 procedure Send_Vector
1751 (Socket
: Socket_Type
;
1752 Vector
: Vector_Type
;
1753 Count
: out Ada
.Streams
.Stream_Element_Count
)
1760 Vector
(Vector
'First)'Address,
1763 if Res
= Failure
then
1764 Raise_Socket_Error
(Socket_Errno
);
1767 Count
:= Ada
.Streams
.Stream_Element_Count
(Res
);
1774 procedure Set
(Item
: in out Socket_Set_Type
; Socket
: Socket_Type
) is
1776 if Item
.Set
= No_Socket_Set
then
1777 Item
.Set
:= New_Socket_Set
(No_Socket_Set
);
1778 Item
.Last
:= Socket
;
1780 elsif Item
.Last
< Socket
then
1781 Item
.Last
:= Socket
;
1784 Insert_Socket_In_Set
(Item
.Set
, C
.int
(Socket
));
1787 -----------------------
1788 -- Set_Socket_Option --
1789 -----------------------
1791 procedure Set_Socket_Option
1792 (Socket
: Socket_Type
;
1793 Level
: Level_Type
:= Socket_Level
;
1794 Option
: Option_Type
)
1796 V8
: aliased Two_Int
;
1798 V1
: aliased C
.unsigned_char
;
1799 Len
: aliased C
.int
;
1800 Add
: System
.Address
:= Null_Address
;
1809 V4
:= C
.int
(Boolean'Pos (Option
.Enabled
));
1814 V8
(V8
'First) := C
.int
(Boolean'Pos (Option
.Enabled
));
1815 V8
(V8
'Last) := C
.int
(Option
.Seconds
);
1821 V4
:= C
.int
(Option
.Size
);
1826 V4
:= C
.int
(Boolean'Pos (True));
1830 when Add_Membership |
1832 V8
(V8
'First) := To_Int
(To_In_Addr
(Option
.Multiaddr
));
1833 V8
(V8
'Last) := To_Int
(To_In_Addr
(Option
.Interface
));
1837 when Multicast_TTL
=>
1838 V1
:= C
.unsigned_char
(Option
.Time_To_Live
);
1842 when Multicast_Loop
=>
1843 V1
:= C
.unsigned_char
(Boolean'Pos (Option
.Enabled
));
1852 Options
(Option
.Name
),
1855 if Res
= Failure
then
1856 Raise_Socket_Error
(Socket_Errno
);
1858 end Set_Socket_Option
;
1860 ----------------------
1861 -- Short_To_Network --
1862 ----------------------
1864 function Short_To_Network
(S
: C
.unsigned_short
) return C
.unsigned_short
is
1865 use type C
.unsigned_short
;
1868 -- Big-endian case. No conversion needed. On these platforms,
1869 -- htons() defaults to a null procedure.
1871 pragma Warnings
(Off
);
1872 -- Since the test can generate "always True/False" warning
1874 if Default_Bit_Order
= High_Order_First
then
1877 pragma Warnings
(On
);
1879 -- Little-endian case. We must swap the high and low bytes of this
1880 -- short to make the port number network compliant.
1883 return (S
/ 256) + (S
mod 256) * 256;
1885 end Short_To_Network
;
1887 ---------------------
1888 -- Shutdown_Socket --
1889 ---------------------
1891 procedure Shutdown_Socket
1892 (Socket
: Socket_Type
;
1893 How
: Shutmode_Type
:= Shut_Read_Write
)
1898 Res
:= C_Shutdown
(C
.int
(Socket
), Shutmodes
(How
));
1900 if Res
= Failure
then
1901 Raise_Socket_Error
(Socket_Errno
);
1903 end Shutdown_Socket
;
1910 (Socket
: Socket_Type
;
1911 Send_To
: Sock_Addr_Type
)
1912 return Stream_Access
1914 S
: Datagram_Socket_Stream_Access
;
1917 S
:= new Datagram_Socket_Stream_Type
;
1920 S
.From
:= Get_Socket_Name
(Socket
);
1921 return Stream_Access
(S
);
1928 function Stream
(Socket
: Socket_Type
) return Stream_Access
is
1929 S
: Stream_Socket_Stream_Access
;
1932 S
:= new Stream_Socket_Stream_Type
;
1934 return Stream_Access
(S
);
1941 function To_C
(Socket
: Socket_Type
) return Integer is
1943 return Integer (Socket
);
1950 function To_Host_Entry
(E
: Hostent
) return Host_Entry_Type
is
1953 Official
: constant String :=
1954 C
.Strings
.Value
(E
.H_Name
);
1956 Aliases
: constant Chars_Ptr_Array
:=
1957 Chars_Ptr_Pointers
.Value
(E
.H_Aliases
);
1958 -- H_Aliases points to a list of name aliases. The list is
1959 -- terminated by a NULL pointer.
1961 Addresses
: constant In_Addr_Access_Array
:=
1962 In_Addr_Access_Pointers
.Value
(E
.H_Addr_List
);
1963 -- H_Addr_List points to a list of binary addresses (in network
1964 -- byte order). The list is terminated by a NULL pointer.
1966 -- H_Length is not used because it is currently only set to 4.
1967 -- H_Addrtype is always AF_INET
1969 Result
: Host_Entry_Type
1970 (Aliases_Length
=> Aliases
'Length - 1,
1971 Addresses_Length
=> Addresses
'Length - 1);
1972 -- The last element is a null pointer.
1978 Result
.Official
:= To_Name
(Official
);
1980 Source
:= Aliases
'First;
1981 Target
:= Result
.Aliases
'First;
1982 while Target
<= Result
.Aliases_Length
loop
1983 Result
.Aliases
(Target
) :=
1984 To_Name
(C
.Strings
.Value
(Aliases
(Source
)));
1985 Source
:= Source
+ 1;
1986 Target
:= Target
+ 1;
1989 Source
:= Addresses
'First;
1990 Target
:= Result
.Addresses
'First;
1991 while Target
<= Result
.Addresses_Length
loop
1992 Result
.Addresses
(Target
) :=
1993 To_Inet_Addr
(Addresses
(Source
).all);
1994 Source
:= Source
+ 1;
1995 Target
:= Target
+ 1;
2005 function To_In_Addr
(Addr
: Inet_Addr_Type
) return Thin
.In_Addr
is
2007 if Addr
.Family
= Family_Inet
then
2008 return (S_B1
=> C
.unsigned_char
(Addr
.Sin_V4
(1)),
2009 S_B2
=> C
.unsigned_char
(Addr
.Sin_V4
(2)),
2010 S_B3
=> C
.unsigned_char
(Addr
.Sin_V4
(3)),
2011 S_B4
=> C
.unsigned_char
(Addr
.Sin_V4
(4)));
2021 function To_Inet_Addr
2023 return Inet_Addr_Type
2025 Result
: Inet_Addr_Type
;
2028 Result
.Sin_V4
(1) := Inet_Addr_Comp_Type
(Addr
.S_B1
);
2029 Result
.Sin_V4
(2) := Inet_Addr_Comp_Type
(Addr
.S_B2
);
2030 Result
.Sin_V4
(3) := Inet_Addr_Comp_Type
(Addr
.S_B3
);
2031 Result
.Sin_V4
(4) := Inet_Addr_Comp_Type
(Addr
.S_B4
);
2040 function To_Int
(F
: Request_Flag_Type
) return C
.int
2042 Current
: Request_Flag_Type
:= F
;
2043 Result
: C
.int
:= 0;
2046 for J
in Flags
'Range loop
2047 exit when Current
= 0;
2049 if Current
mod 2 /= 0 then
2050 if Flags
(J
) = -1 then
2051 Raise_Socket_Error
(Constants
.EOPNOTSUPP
);
2053 Result
:= Result
+ Flags
(J
);
2056 Current
:= Current
/ 2;
2066 function To_Name
(N
: String) return Name_Type
is
2068 return Name_Type
'(N'Length, N);
2071 ----------------------
2072 -- To_Service_Entry --
2073 ----------------------
2075 function To_Service_Entry (E : Servent) return Service_Entry_Type is
2078 Official : constant String :=
2079 C.Strings.Value (E.S_Name);
2081 Aliases : constant Chars_Ptr_Array :=
2082 Chars_Ptr_Pointers.Value (E.S_Aliases);
2083 -- S_Aliases points to a list of name aliases. The list is
2084 -- terminated by a NULL pointer.
2086 Protocol : constant String :=
2087 C.Strings.Value (E.S_Proto);
2089 Result : Service_Entry_Type
2090 (Aliases_Length => Aliases'Length - 1);
2091 -- The last element is a null pointer.
2097 Result.Official := To_Name (Official);
2099 Source := Aliases'First;
2100 Target := Result.Aliases'First;
2101 while Target <= Result.Aliases_Length loop
2102 Result.Aliases (Target) :=
2103 To_Name (C.Strings.Value (Aliases (Source)));
2104 Source := Source + 1;
2105 Target := Target + 1;
2109 Port_Type (Network_To_Short (C.unsigned_short (E.S_Port)));
2111 Result.Protocol := To_Name (Protocol);
2114 end To_Service_Entry;
2120 function To_String (HN : Name_Type) return String is
2122 return HN.Name (1 .. HN.Length);
2129 function To_Timeval (Val : Selector_Duration) return Timeval is
2134 -- If zero, set result as zero (otherwise it gets rounded down to -1)
2140 -- Normal case where we do round down
2142 S := Timeval_Unit (Val - 0.5);
2143 MS := Timeval_Unit (1_000_000 * (Val - Selector_Duration (S)));
2154 (Stream : in out Datagram_Socket_Stream_Type;
2155 Item : Ada.Streams.Stream_Element_Array)
2157 First : Ada.Streams.Stream_Element_Offset := Item'First;
2158 Index : Ada.Streams.Stream_Element_Offset := First - 1;
2159 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2165 Item (First .. Max),
2169 -- Exit when all or zero data sent. Zero means that the
2170 -- socket has been closed by peer.
2172 exit when Index < First or else Index = Max;
2177 if Index /= Max then
2187 (Stream : in out Stream_Socket_Stream_Type;
2188 Item : Ada.Streams.Stream_Element_Array)
2190 First : Ada.Streams.Stream_Element_Offset := Item'First;
2191 Index : Ada.Streams.Stream_Element_Offset := First - 1;
2192 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
2196 Send_Socket (Stream.Socket, Item (First .. Max), Index);
2198 -- Exit when all or zero data sent. Zero means that the
2199 -- socket has been closed by peer.
2201 exit when Index < First or else Index = Max;
2206 if Index /= Max then