* dwarf2out.c (loc_descriptor_from_tree, case CONSTRUCTOR): New case.
[official-gcc.git] / gcc / ada / g-socket.adb
blob27ebe1c366d860e907fda3469a59f96d966d15fd
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T . S O C K E T S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2002 Ada Core Technologies, Inc. --
10 -- --
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. --
21 -- --
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. --
28 -- --
29 -- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com). --
30 -- --
31 ------------------------------------------------------------------------------
33 with Ada.Streams; use Ada.Streams;
34 with Ada.Exceptions; use Ada.Exceptions;
35 with Ada.Unchecked_Deallocation;
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;
43 with GNAT.Task_Lock;
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 -- Correspondance tables
60 Families : constant array (Family_Type) of C.int :=
61 (Family_Inet => Constants.AF_INET,
62 Family_Inet6 => Constants.AF_INET6);
64 Levels : constant array (Level_Type) of C.int :=
65 (Socket_Level => Constants.SOL_SOCKET,
66 IP_Protocol_For_IP_Level => Constants.IPPROTO_IP,
67 IP_Protocol_For_UDP_Level => Constants.IPPROTO_UDP,
68 IP_Protocol_For_TCP_Level => Constants.IPPROTO_TCP);
70 Modes : constant array (Mode_Type) of C.int :=
71 (Socket_Stream => Constants.SOCK_STREAM,
72 Socket_Datagram => Constants.SOCK_DGRAM);
74 Shutmodes : constant array (Shutmode_Type) of C.int :=
75 (Shut_Read => Constants.SHUT_RD,
76 Shut_Write => Constants.SHUT_WR,
77 Shut_Read_Write => Constants.SHUT_RDWR);
79 Requests : constant array (Request_Name) of C.int :=
80 (Non_Blocking_IO => Constants.FIONBIO,
81 N_Bytes_To_Read => Constants.FIONREAD);
83 Options : constant array (Option_Name) of C.int :=
84 (Keep_Alive => Constants.SO_KEEPALIVE,
85 Reuse_Address => Constants.SO_REUSEADDR,
86 Broadcast => Constants.SO_BROADCAST,
87 Send_Buffer => Constants.SO_SNDBUF,
88 Receive_Buffer => Constants.SO_RCVBUF,
89 Linger => Constants.SO_LINGER,
90 Error => Constants.SO_ERROR,
91 No_Delay => Constants.TCP_NODELAY,
92 Add_Membership => Constants.IP_ADD_MEMBERSHIP,
93 Drop_Membership => Constants.IP_DROP_MEMBERSHIP,
94 Multicast_TTL => Constants.IP_MULTICAST_TTL,
95 Multicast_Loop => Constants.IP_MULTICAST_LOOP);
97 Socket_Error_Id : constant Exception_Id := Socket_Error'Identity;
98 Host_Error_Id : constant Exception_Id := Host_Error'Identity;
100 Hex_To_Char : constant String (1 .. 16) := "0123456789ABCDEF";
101 -- Use to print in hexadecimal format
103 function To_In_Addr is new Ada.Unchecked_Conversion (C.int, In_Addr);
104 function To_Int is new Ada.Unchecked_Conversion (In_Addr, C.int);
106 -----------------------
107 -- Local subprograms --
108 -----------------------
110 function Resolve_Error
111 (Error_Value : Integer;
112 From_Errno : Boolean := True)
113 return Error_Type;
114 -- Associate an enumeration value (error_type) to en error value
115 -- (errno). From_Errno prevents from mixing h_errno with errno.
117 function To_Host_Name (N : String) return Host_Name_Type;
118 function To_String (HN : Host_Name_Type) return String;
119 -- Conversion functions
121 function Port_To_Network
122 (Port : C.unsigned_short)
123 return C.unsigned_short;
124 pragma Inline (Port_To_Network);
125 -- Convert a port number into a network port number
127 function Network_To_Port
128 (Net_Port : C.unsigned_short)
129 return C.unsigned_short
130 renames Port_To_Network;
131 -- Symetric operation
133 function Image
134 (Val : Inet_Addr_VN_Type;
135 Hex : Boolean := False)
136 return String;
137 -- Output an array of inet address components either in
138 -- hexadecimal or in decimal mode.
140 function To_In_Addr (Addr : Inet_Addr_Type) return Thin.In_Addr;
141 function To_Inet_Addr (Addr : In_Addr) return Inet_Addr_Type;
142 -- Conversion functions
144 function To_Host_Entry (Host : Hostent) return Host_Entry_Type;
145 -- Conversion function
147 function To_Timeval (Val : Duration) return Timeval;
148 -- Separate Val in seconds and microseconds
150 procedure Raise_Socket_Error (Error : Integer);
151 -- Raise Socket_Error with an exception message describing
152 -- the error code.
154 procedure Raise_Host_Error (Error : Integer);
155 -- Raise Host_Error exception with message describing error code
156 -- (note hstrerror seems to be obsolete).
158 -- Types needed for Socket_Set_Type
160 type Socket_Set_Record is new Fd_Set;
162 procedure Free is
163 new Ada.Unchecked_Deallocation (Socket_Set_Record, Socket_Set_Type);
165 -- Types needed for Datagram_Socket_Stream_Type
167 type Datagram_Socket_Stream_Type is new Root_Stream_Type with record
168 Socket : Socket_Type;
169 To : Sock_Addr_Type;
170 From : Sock_Addr_Type;
171 end record;
173 type Datagram_Socket_Stream_Access is
174 access all Datagram_Socket_Stream_Type;
176 procedure Read
177 (Stream : in out Datagram_Socket_Stream_Type;
178 Item : out Ada.Streams.Stream_Element_Array;
179 Last : out Ada.Streams.Stream_Element_Offset);
181 procedure Write
182 (Stream : in out Datagram_Socket_Stream_Type;
183 Item : Ada.Streams.Stream_Element_Array);
185 -- Types needed for Stream_Socket_Stream_Type
187 type Stream_Socket_Stream_Type is new Root_Stream_Type with record
188 Socket : Socket_Type;
189 end record;
191 type Stream_Socket_Stream_Access is
192 access all Stream_Socket_Stream_Type;
194 procedure Read
195 (Stream : in out Stream_Socket_Stream_Type;
196 Item : out Ada.Streams.Stream_Element_Array;
197 Last : out Ada.Streams.Stream_Element_Offset);
199 procedure Write
200 (Stream : in out Stream_Socket_Stream_Type;
201 Item : Ada.Streams.Stream_Element_Array);
203 --------------------
204 -- Abort_Selector --
205 --------------------
207 procedure Abort_Selector (Selector : Selector_Type) is
208 Buf : Character;
209 Res : C.int;
211 begin
212 -- Send an empty array to unblock C select system call
214 if Selector.In_Progress then
215 Res := C_Write (C.int (Selector.W_Sig_Socket), Buf'Address, 1);
216 end if;
217 end Abort_Selector;
219 -------------------
220 -- Accept_Socket --
221 -------------------
223 procedure Accept_Socket
224 (Server : Socket_Type;
225 Socket : out Socket_Type;
226 Address : out Sock_Addr_Type)
228 Res : C.int;
229 Sin : aliased Sockaddr_In;
230 Len : aliased C.int := Sin'Size / 8;
232 begin
233 Res := C_Accept (C.int (Server), Sin'Address, Len'Access);
235 if Res = Failure then
236 Raise_Socket_Error (Socket_Errno);
237 end if;
239 Socket := Socket_Type (Res);
241 Address.Addr := To_Inet_Addr (Sin.Sin_Addr);
242 Address.Port := Port_Type (Network_To_Port (Sin.Sin_Port));
243 end Accept_Socket;
245 ---------------
246 -- Addresses --
247 ---------------
249 function Addresses
250 (E : Host_Entry_Type;
251 N : Positive := 1)
252 return Inet_Addr_Type
254 begin
255 return E.Addresses (N);
256 end Addresses;
258 ----------------------
259 -- Addresses_Length --
260 ----------------------
262 function Addresses_Length (E : Host_Entry_Type) return Natural is
263 begin
264 return E.Addresses_Length;
265 end Addresses_Length;
267 -------------
268 -- Aliases --
269 -------------
271 function Aliases
272 (E : Host_Entry_Type;
273 N : Positive := 1)
274 return String
276 begin
277 return To_String (E.Aliases (N));
278 end Aliases;
280 --------------------
281 -- Aliases_Length --
282 --------------------
284 function Aliases_Length (E : Host_Entry_Type) return Natural is
285 begin
286 return E.Aliases_Length;
287 end Aliases_Length;
289 -----------------
290 -- Bind_Socket --
291 -----------------
293 procedure Bind_Socket
294 (Socket : Socket_Type;
295 Address : Sock_Addr_Type)
297 Res : C.int;
298 Sin : aliased Sockaddr_In;
299 Len : aliased C.int := Sin'Size / 8;
301 begin
302 if Address.Family = Family_Inet6 then
303 raise Socket_Error;
304 end if;
306 Sin.Sin_Family := C.unsigned_short (Families (Address.Family));
307 Sin.Sin_Port := Port_To_Network (C.unsigned_short (Address.Port));
309 Res := C_Bind (C.int (Socket), Sin'Address, Len);
311 if Res = Failure then
312 Raise_Socket_Error (Socket_Errno);
313 end if;
314 end Bind_Socket;
316 --------------------
317 -- Check_Selector --
318 --------------------
320 procedure Check_Selector
321 (Selector : in out Selector_Type;
322 R_Socket_Set : in out Socket_Set_Type;
323 W_Socket_Set : in out Socket_Set_Type;
324 Status : out Selector_Status;
325 Timeout : Duration := Forever)
327 Res : C.int;
328 Len : C.int;
329 RSet : aliased Fd_Set;
330 WSet : aliased Fd_Set;
331 TVal : aliased Timeval;
332 TPtr : Timeval_Access;
334 begin
335 Status := Completed;
337 -- No timeout or Forever is indicated by a null timeval pointer.
339 if Timeout = Forever then
340 TPtr := null;
341 else
342 TVal := To_Timeval (Timeout);
343 TPtr := TVal'Unchecked_Access;
344 end if;
346 -- Copy R_Socket_Set in RSet and add read signalling socket.
348 if R_Socket_Set = null then
349 RSet := Null_Fd_Set;
350 else
351 RSet := Fd_Set (R_Socket_Set.all);
352 end if;
354 Set (RSet, C.int (Selector.R_Sig_Socket));
355 Len := Max (RSet) + 1;
357 -- Copy W_Socket_Set in WSet.
359 if W_Socket_Set = null then
360 WSet := Null_Fd_Set;
361 else
362 WSet := Fd_Set (W_Socket_Set.all);
363 end if;
365 Len := C.int'Max (Max (RSet) + 1, Len);
367 Selector.In_Progress := True;
368 Res :=
369 C_Select
370 (Len,
371 RSet'Unchecked_Access,
372 WSet'Unchecked_Access,
373 null, TPtr);
374 Selector.In_Progress := False;
376 -- If Select was resumed because of read signalling socket,
377 -- read this data and remove socket from set.
379 if Is_Set (RSet, C.int (Selector.R_Sig_Socket)) then
380 Clear (RSet, C.int (Selector.R_Sig_Socket));
382 declare
383 Buf : Character;
384 begin
385 Res := C_Read (C.int (Selector.R_Sig_Socket), Buf'Address, 1);
386 end;
388 -- Select was resumed because of read signalling socket, but
389 -- the call is said aborted only when there is no other read
390 -- or write event.
392 if Is_Empty (RSet)
393 and then Is_Empty (WSet)
394 then
395 Status := Aborted;
396 end if;
398 elsif Res = 0 then
399 Status := Expired;
400 end if;
402 if R_Socket_Set /= null then
403 R_Socket_Set.all := Socket_Set_Record (RSet);
404 end if;
406 if W_Socket_Set /= null then
407 W_Socket_Set.all := Socket_Set_Record (WSet);
408 end if;
409 end Check_Selector;
411 -----------
412 -- Clear --
413 -----------
415 procedure Clear
416 (Item : in out Socket_Set_Type;
417 Socket : Socket_Type)
419 begin
420 if Item = null then
421 Item := new Socket_Set_Record;
422 Empty (Fd_Set (Item.all));
423 end if;
425 Clear (Fd_Set (Item.all), C.int (Socket));
426 end Clear;
428 --------------------
429 -- Close_Selector --
430 --------------------
432 procedure Close_Selector (Selector : in out Selector_Type) is
433 begin
434 begin
435 Close_Socket (Selector.R_Sig_Socket);
436 exception when Socket_Error =>
437 null;
438 end;
440 begin
441 Close_Socket (Selector.W_Sig_Socket);
442 exception when Socket_Error =>
443 null;
444 end;
445 end Close_Selector;
447 ------------------
448 -- Close_Socket --
449 ------------------
451 procedure Close_Socket (Socket : Socket_Type) is
452 Res : C.int;
454 begin
455 Res := C_Close (C.int (Socket));
457 if Res = Failure then
458 Raise_Socket_Error (Socket_Errno);
459 end if;
460 end Close_Socket;
462 --------------------
463 -- Connect_Socket --
464 --------------------
466 procedure Connect_Socket
467 (Socket : Socket_Type;
468 Server : in out Sock_Addr_Type)
470 Res : C.int;
471 Sin : aliased Sockaddr_In;
472 Len : aliased C.int := Sin'Size / 8;
474 begin
475 if Server.Family = Family_Inet6 then
476 raise Socket_Error;
477 end if;
479 Sin.Sin_Family := C.unsigned_short (Families (Server.Family));
480 Sin.Sin_Addr := To_In_Addr (Server.Addr);
481 Sin.Sin_Port := Port_To_Network (C.unsigned_short (Server.Port));
483 Res := C_Connect (C.int (Socket), Sin'Address, Len);
485 if Res = Failure then
486 Raise_Socket_Error (Socket_Errno);
487 end if;
488 end Connect_Socket;
490 --------------------
491 -- Control_Socket --
492 --------------------
494 procedure Control_Socket
495 (Socket : Socket_Type;
496 Request : in out Request_Type)
498 Arg : aliased C.int;
499 Res : C.int;
501 begin
502 case Request.Name is
503 when Non_Blocking_IO =>
504 Arg := C.int (Boolean'Pos (Request.Enabled));
506 when N_Bytes_To_Read =>
507 null;
509 end case;
511 Res := C_Ioctl
512 (C.int (Socket),
513 Requests (Request.Name),
514 Arg'Unchecked_Access);
516 if Res = Failure then
517 Raise_Socket_Error (Socket_Errno);
518 end if;
520 case Request.Name is
521 when Non_Blocking_IO =>
522 null;
524 when N_Bytes_To_Read =>
525 Request.Size := Natural (Arg);
527 end case;
528 end Control_Socket;
530 ---------------------
531 -- Create_Selector --
532 ---------------------
534 procedure Create_Selector (Selector : out Selector_Type) is
535 S0 : C.int;
536 S1 : C.int;
537 S2 : C.int;
538 Res : C.int;
539 Sin : aliased Sockaddr_In;
540 Len : aliased C.int := Sin'Size / 8;
541 Err : Integer;
543 begin
544 -- We open two signalling sockets. One socket to send a signal
545 -- to a another socket that always included in a C_Select
546 -- socket set. When received, it resumes the task suspended in
547 -- C_Select.
549 -- Create a listening socket
551 S0 := C_Socket (Constants.AF_INET, Constants.SOCK_STREAM, 0);
552 if S0 = Failure then
553 Raise_Socket_Error (Socket_Errno);
554 end if;
556 -- Sin is already correctly initialized. Bind the socket to any
557 -- unused port.
559 Res := C_Bind (S0, Sin'Address, Len);
560 if Res = Failure then
561 Err := Socket_Errno;
562 Res := C_Close (S0);
563 Raise_Socket_Error (Err);
564 end if;
566 -- Get the port used by the socket
568 Res := C_Getsockname (S0, Sin'Address, Len'Access);
570 if Res = Failure then
571 Err := Socket_Errno;
572 Res := C_Close (S0);
573 Raise_Socket_Error (Err);
574 end if;
576 Res := C_Listen (S0, 2);
578 if Res = Failure then
579 Err := Socket_Errno;
580 Res := C_Close (S0);
581 Raise_Socket_Error (Err);
582 end if;
584 S1 := C_Socket (Constants.AF_INET, Constants.SOCK_STREAM, 0);
586 if S1 = Failure then
587 Err := Socket_Errno;
588 Res := C_Close (S0);
589 Raise_Socket_Error (Err);
590 end if;
592 -- Use INADDR_LOOPBACK
594 Sin.Sin_Addr.S_B1 := 127;
595 Sin.Sin_Addr.S_B2 := 0;
596 Sin.Sin_Addr.S_B3 := 0;
597 Sin.Sin_Addr.S_B4 := 1;
599 -- Do a connect and accept the connection
601 Res := C_Connect (S1, Sin'Address, Len);
603 if Res = Failure then
604 Err := Socket_Errno;
605 Res := C_Close (S0);
606 Res := C_Close (S1);
607 Raise_Socket_Error (Err);
608 end if;
610 S2 := C_Accept (S0, Sin'Address, Len'Access);
612 if S2 = Failure then
613 Err := Socket_Errno;
614 Res := C_Close (S0);
615 Res := C_Close (S1);
616 Raise_Socket_Error (Err);
617 end if;
619 Res := C_Close (S0);
621 if Res = Failure then
622 Raise_Socket_Error (Socket_Errno);
623 end if;
625 Selector.R_Sig_Socket := Socket_Type (S1);
626 Selector.W_Sig_Socket := Socket_Type (S2);
627 end Create_Selector;
629 -------------------
630 -- Create_Socket --
631 -------------------
633 procedure Create_Socket
634 (Socket : out Socket_Type;
635 Family : Family_Type := Family_Inet;
636 Mode : Mode_Type := Socket_Stream)
638 Res : C.int;
640 begin
641 Res := C_Socket (Families (Family), Modes (Mode), 0);
643 if Res = Failure then
644 Raise_Socket_Error (Socket_Errno);
645 end if;
647 Socket := Socket_Type (Res);
648 end Create_Socket;
650 -----------
651 -- Empty --
652 -----------
654 procedure Empty (Item : in out Socket_Set_Type) is
655 begin
656 if Item /= null then
657 Free (Item);
658 end if;
659 end Empty;
661 --------------
662 -- Finalize --
663 --------------
665 procedure Finalize is
666 begin
667 if not Finalized
668 and then Initialized
669 then
670 Finalized := True;
671 Thin.Finalize;
672 end if;
673 end Finalize;
675 -----------------
676 -- Get_Address --
677 -----------------
679 function Get_Address (Stream : Stream_Access) return Sock_Addr_Type is
680 begin
681 if Stream = null then
682 raise Socket_Error;
684 elsif Stream.all in Datagram_Socket_Stream_Type then
685 return Datagram_Socket_Stream_Type (Stream.all).From;
687 else
688 return Get_Peer_Name (Stream_Socket_Stream_Type (Stream.all).Socket);
689 end if;
690 end Get_Address;
692 -------------------------
693 -- Get_Host_By_Address --
694 -------------------------
696 function Get_Host_By_Address
697 (Address : Inet_Addr_Type;
698 Family : Family_Type := Family_Inet)
699 return Host_Entry_Type
701 pragma Unreferenced (Family);
703 HA : aliased In_Addr := To_In_Addr (Address);
704 Res : Hostent_Access;
705 Err : Integer;
707 begin
708 -- This C function is not always thread-safe. Protect against
709 -- concurrent access.
711 Task_Lock.Lock;
712 Res := C_Gethostbyaddr (HA'Address, HA'Size / 8, Constants.AF_INET);
714 if Res = null then
715 Err := Socket_Errno;
716 Task_Lock.Unlock;
717 Raise_Host_Error (Err);
718 end if;
720 -- Translate from the C format to the API format
722 declare
723 HE : Host_Entry_Type := To_Host_Entry (Res.all);
725 begin
726 Task_Lock.Unlock;
727 return HE;
728 end;
729 end Get_Host_By_Address;
731 ----------------------
732 -- Get_Host_By_Name --
733 ----------------------
735 function Get_Host_By_Name
736 (Name : String)
737 return Host_Entry_Type
739 HN : C.char_array := C.To_C (Name);
740 Res : Hostent_Access;
741 Err : Integer;
743 begin
744 -- This C function is not always thread-safe. Protect against
745 -- concurrent access.
747 Task_Lock.Lock;
748 Res := C_Gethostbyname (HN);
750 if Res = null then
751 Err := Socket_Errno;
752 Task_Lock.Unlock;
753 Raise_Host_Error (Err);
754 end if;
756 -- Translate from the C format to the API format
758 declare
759 HE : Host_Entry_Type := To_Host_Entry (Res.all);
761 begin
762 Task_Lock.Unlock;
763 return HE;
764 end;
765 end Get_Host_By_Name;
767 -------------------
768 -- Get_Peer_Name --
769 -------------------
771 function Get_Peer_Name
772 (Socket : Socket_Type)
773 return Sock_Addr_Type
775 Sin : aliased Sockaddr_In;
776 Len : aliased C.int := Sin'Size / 8;
777 Res : Sock_Addr_Type (Family_Inet);
779 begin
780 if C_Getpeername (C.int (Socket), Sin'Address, Len'Access) = Failure then
781 Raise_Socket_Error (Socket_Errno);
782 end if;
784 Res.Addr := To_Inet_Addr (Sin.Sin_Addr);
785 Res.Port := Port_Type (Network_To_Port (Sin.Sin_Port));
787 return Res;
788 end Get_Peer_Name;
790 ---------------------
791 -- Get_Socket_Name --
792 ---------------------
794 function Get_Socket_Name
795 (Socket : Socket_Type)
796 return Sock_Addr_Type
798 Sin : aliased Sockaddr_In;
799 Len : aliased C.int := Sin'Size / 8;
800 Res : Sock_Addr_Type (Family_Inet);
802 begin
803 if C_Getsockname (C.int (Socket), Sin'Address, Len'Access) = Failure then
804 Raise_Socket_Error (Socket_Errno);
805 end if;
807 Res.Addr := To_Inet_Addr (Sin.Sin_Addr);
808 Res.Port := Port_Type (Network_To_Port (Sin.Sin_Port));
810 return Res;
811 end Get_Socket_Name;
813 -----------------------
814 -- Get_Socket_Option --
815 -----------------------
817 function Get_Socket_Option
818 (Socket : Socket_Type;
819 Level : Level_Type := Socket_Level;
820 Name : Option_Name)
821 return Option_Type
823 use type C.unsigned_char;
825 V8 : aliased Two_Int;
826 V4 : aliased C.int;
827 V1 : aliased C.unsigned_char;
828 Len : aliased C.int;
829 Add : System.Address;
830 Res : C.int;
831 Opt : Option_Type (Name);
833 begin
834 case Name is
835 when Multicast_Loop |
836 Multicast_TTL =>
837 Len := V1'Size / 8;
838 Add := V1'Address;
840 when Keep_Alive |
841 Reuse_Address |
842 Broadcast |
843 No_Delay |
844 Send_Buffer |
845 Receive_Buffer |
846 Error =>
847 Len := V4'Size / 8;
848 Add := V4'Address;
850 when Linger |
851 Add_Membership |
852 Drop_Membership =>
853 Len := V8'Size / 8;
854 Add := V8'Address;
856 end case;
858 Res :=
859 C_Getsockopt
860 (C.int (Socket),
861 Levels (Level),
862 Options (Name),
863 Add, Len'Unchecked_Access);
865 if Res = Failure then
866 Raise_Socket_Error (Socket_Errno);
867 end if;
869 case Name is
870 when Keep_Alive |
871 Reuse_Address |
872 Broadcast |
873 No_Delay =>
874 Opt.Enabled := (V4 /= 0);
876 when Linger =>
877 Opt.Enabled := (V8 (V8'First) /= 0);
878 Opt.Seconds := Natural (V8 (V8'Last));
880 when Send_Buffer |
881 Receive_Buffer =>
882 Opt.Size := Natural (V4);
884 when Error =>
885 Opt.Error := Resolve_Error (Integer (V4));
887 when Add_Membership |
888 Drop_Membership =>
889 Opt.Multiaddr := To_Inet_Addr (To_In_Addr (V8 (V8'First)));
890 Opt.Interface := To_Inet_Addr (To_In_Addr (V8 (V8'Last)));
892 when Multicast_TTL =>
893 Opt.Time_To_Live := Integer (V1);
895 when Multicast_Loop =>
896 Opt.Enabled := (V1 /= 0);
898 end case;
900 return Opt;
901 end Get_Socket_Option;
903 ---------------
904 -- Host_Name --
905 ---------------
907 function Host_Name return String is
908 Name : aliased C.char_array (1 .. 64);
909 Res : C.int;
911 begin
912 Res := C_Gethostname (Name'Address, Name'Length);
914 if Res = Failure then
915 Raise_Socket_Error (Socket_Errno);
916 end if;
918 return C.To_Ada (Name);
919 end Host_Name;
921 -----------
922 -- Image --
923 -----------
925 function Image
926 (Val : Inet_Addr_VN_Type;
927 Hex : Boolean := False)
928 return String
930 -- The largest Inet_Addr_Comp_Type image occurs with IPv4. It
931 -- has at most a length of 3 plus one '.' character.
933 Buffer : String (1 .. 4 * Val'Length);
934 Length : Natural := 1;
935 Separator : Character;
937 procedure Img10 (V : Inet_Addr_Comp_Type);
938 -- Append to Buffer image of V in decimal format
940 procedure Img16 (V : Inet_Addr_Comp_Type);
941 -- Append to Buffer image of V in hexadecimal format
943 procedure Img10 (V : Inet_Addr_Comp_Type) is
944 Img : constant String := V'Img;
945 Len : Natural := Img'Length - 1;
947 begin
948 Buffer (Length .. Length + Len - 1) := Img (2 .. Img'Last);
949 Length := Length + Len;
950 end Img10;
952 procedure Img16 (V : Inet_Addr_Comp_Type) is
953 begin
954 Buffer (Length) := Hex_To_Char (Natural (V / 16) + 1);
955 Buffer (Length + 1) := Hex_To_Char (Natural (V mod 16) + 1);
956 Length := Length + 2;
957 end Img16;
959 -- Start of processing for Image
961 begin
962 if Hex then
963 Separator := ':';
964 else
965 Separator := '.';
966 end if;
968 for J in Val'Range loop
969 if Hex then
970 Img16 (Val (J));
971 else
972 Img10 (Val (J));
973 end if;
975 if J /= Val'Last then
976 Buffer (Length) := Separator;
977 Length := Length + 1;
978 end if;
979 end loop;
981 return Buffer (1 .. Length - 1);
982 end Image;
984 -----------
985 -- Image --
986 -----------
988 function Image (Value : Inet_Addr_Type) return String is
989 begin
990 if Value.Family = Family_Inet then
991 return Image (Inet_Addr_VN_Type (Value.Sin_V4), Hex => False);
992 else
993 return Image (Inet_Addr_VN_Type (Value.Sin_V6), Hex => True);
994 end if;
995 end Image;
997 -----------
998 -- Image --
999 -----------
1001 function Image (Value : Sock_Addr_Type) return String is
1002 Port : constant String := Value.Port'Img;
1004 begin
1005 return Image (Value.Addr) & ':' & Port (2 .. Port'Last);
1006 end Image;
1008 -----------
1009 -- Image --
1010 -----------
1012 function Image (Socket : Socket_Type) return String is
1013 begin
1014 return Socket'Img;
1015 end Image;
1017 ---------------
1018 -- Inet_Addr --
1019 ---------------
1021 function Inet_Addr (Image : String) return Inet_Addr_Type is
1022 use Interfaces.C.Strings;
1024 Img : chars_ptr := New_String (Image);
1025 Res : C.int;
1026 Err : Integer;
1028 begin
1029 Res := C_Inet_Addr (Img);
1030 Err := Errno;
1031 Free (Img);
1033 if Res = Failure then
1034 Raise_Socket_Error (Err);
1035 end if;
1037 return To_Inet_Addr (To_In_Addr (Res));
1038 end Inet_Addr;
1040 ----------------
1041 -- Initialize --
1042 ----------------
1044 procedure Initialize (Process_Blocking_IO : Boolean := False) is
1045 begin
1046 if not Initialized then
1047 Initialized := True;
1048 Thin.Initialize (Process_Blocking_IO);
1049 end if;
1050 end Initialize;
1052 --------------
1053 -- Is_Empty --
1054 --------------
1056 function Is_Empty (Item : Socket_Set_Type) return Boolean is
1057 begin
1058 return Item = null or else Is_Empty (Fd_Set (Item.all));
1059 end Is_Empty;
1061 ------------
1062 -- Is_Set --
1063 ------------
1065 function Is_Set
1066 (Item : Socket_Set_Type;
1067 Socket : Socket_Type) return Boolean
1069 begin
1070 return Item /= null
1071 and then Is_Set (Fd_Set (Item.all), C.int (Socket));
1072 end Is_Set;
1074 -------------------
1075 -- Listen_Socket --
1076 -------------------
1078 procedure Listen_Socket
1079 (Socket : Socket_Type;
1080 Length : Positive := 15)
1082 Res : C.int;
1084 begin
1085 Res := C_Listen (C.int (Socket), C.int (Length));
1086 if Res = Failure then
1087 Raise_Socket_Error (Socket_Errno);
1088 end if;
1089 end Listen_Socket;
1091 -------------------
1092 -- Official_Name --
1093 -------------------
1095 function Official_Name (E : Host_Entry_Type) return String is
1096 begin
1097 return To_String (E.Official);
1098 end Official_Name;
1100 ---------------------
1101 -- Port_To_Network --
1102 ---------------------
1104 function Port_To_Network
1105 (Port : C.unsigned_short)
1106 return C.unsigned_short
1108 use type C.unsigned_short;
1109 begin
1110 if Default_Bit_Order = High_Order_First then
1112 -- No conversion needed. On these platforms, htons() defaults
1113 -- to a null procedure.
1115 return Port;
1117 else
1118 -- We need to swap the high and low byte on this short to make
1119 -- the port number network compliant.
1121 return (Port / 256) + (Port mod 256) * 256;
1122 end if;
1123 end Port_To_Network;
1125 ----------------------
1126 -- Raise_Host_Error --
1127 ----------------------
1129 procedure Raise_Host_Error (Error : Integer) is
1131 function Error_Message return String;
1132 -- We do not use a C function like strerror because hstrerror
1133 -- that would correspond seems to be obsolete. Return
1134 -- appropriate string for error value.
1136 function Error_Message return String is
1137 begin
1138 case Error is
1139 when Constants.HOST_NOT_FOUND => return "Host not found";
1140 when Constants.TRY_AGAIN => return "Try again";
1141 when Constants.NO_RECOVERY => return "No recovery";
1142 when Constants.NO_ADDRESS => return "No address";
1143 when others => return "Unknown error";
1144 end case;
1145 end Error_Message;
1147 -- Start of processing for Raise_Host_Error
1149 begin
1150 Ada.Exceptions.Raise_Exception (Host_Error'Identity, Error_Message);
1151 end Raise_Host_Error;
1153 ------------------------
1154 -- Raise_Socket_Error --
1155 ------------------------
1157 procedure Raise_Socket_Error (Error : Integer) is
1158 use type C.Strings.chars_ptr;
1160 function Image (E : Integer) return String;
1161 function Image (E : Integer) return String is
1162 Msg : String := E'Img & "] ";
1163 begin
1164 Msg (Msg'First) := '[';
1165 return Msg;
1166 end Image;
1168 begin
1169 Ada.Exceptions.Raise_Exception
1170 (Socket_Error'Identity, Image (Error) & Socket_Error_Message (Error));
1171 end Raise_Socket_Error;
1173 ----------
1174 -- Read --
1175 ----------
1177 procedure Read
1178 (Stream : in out Datagram_Socket_Stream_Type;
1179 Item : out Ada.Streams.Stream_Element_Array;
1180 Last : out Ada.Streams.Stream_Element_Offset)
1182 First : Ada.Streams.Stream_Element_Offset := Item'First;
1183 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1184 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1186 begin
1187 loop
1188 Receive_Socket
1189 (Stream.Socket,
1190 Item (First .. Max),
1191 Index,
1192 Stream.From);
1194 Last := Index;
1196 -- Exit when all or zero data received. Zero means that
1197 -- the socket peer is closed.
1199 exit when Index < First or else Index = Max;
1201 First := Index + 1;
1202 end loop;
1203 end Read;
1205 ----------
1206 -- Read --
1207 ----------
1209 procedure Read
1210 (Stream : in out Stream_Socket_Stream_Type;
1211 Item : out Ada.Streams.Stream_Element_Array;
1212 Last : out Ada.Streams.Stream_Element_Offset)
1214 First : Ada.Streams.Stream_Element_Offset := Item'First;
1215 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1216 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1218 begin
1219 loop
1220 Receive_Socket (Stream.Socket, Item (First .. Max), Index);
1221 Last := Index;
1223 -- Exit when all or zero data received. Zero means that
1224 -- the socket peer is closed.
1226 exit when Index < First or else Index = Max;
1228 First := Index + 1;
1229 end loop;
1230 end Read;
1232 -------------------
1233 -- Resolve_Error --
1234 -------------------
1236 function Resolve_Error
1237 (Error_Value : Integer;
1238 From_Errno : Boolean := True)
1239 return Error_Type
1241 use GNAT.Sockets.Constants;
1243 begin
1244 if not From_Errno then
1245 case Error_Value is
1246 when HOST_NOT_FOUND => return Unknown_Host;
1247 when TRY_AGAIN => return Host_Name_Lookup_Failure;
1248 when NO_RECOVERY => return No_Address_Associated_With_Name;
1249 when NO_ADDRESS => return Unknown_Server_Error;
1250 when others => return Cannot_Resolve_Error;
1251 end case;
1252 end if;
1254 case Error_Value is
1255 when EACCES => return Permission_Denied;
1256 when EADDRINUSE => return Address_Already_In_Use;
1257 when EADDRNOTAVAIL => return Cannot_Assign_Requested_Address;
1258 when EAFNOSUPPORT =>
1259 return Address_Family_Not_Supported_By_Protocol;
1260 when EALREADY => return Operation_Already_In_Progress;
1261 when EBADF => return Bad_File_Descriptor;
1262 when ECONNREFUSED => return Connection_Refused;
1263 when EFAULT => return Bad_Address;
1264 when EINPROGRESS => return Operation_Now_In_Progress;
1265 when EINTR => return Interrupted_System_Call;
1266 when EINVAL => return Invalid_Argument;
1267 when EIO => return Input_Output_Error;
1268 when EISCONN => return Transport_Endpoint_Already_Connected;
1269 when EMSGSIZE => return Message_Too_Long;
1270 when ENETUNREACH => return Network_Is_Unreachable;
1271 when ENOBUFS => return No_Buffer_Space_Available;
1272 when ENOPROTOOPT => return Protocol_Not_Available;
1273 when ENOTCONN => return Transport_Endpoint_Not_Connected;
1274 when EOPNOTSUPP => return Operation_Not_Supported;
1275 when EPROTONOSUPPORT => return Protocol_Not_Supported;
1276 when ESOCKTNOSUPPORT => return Socket_Type_Not_Supported;
1277 when ETIMEDOUT => return Connection_Timed_Out;
1278 when EWOULDBLOCK => return Resource_Temporarily_Unavailable;
1279 when others => return Cannot_Resolve_Error;
1280 end case;
1281 end Resolve_Error;
1283 -----------------------
1284 -- Resolve_Exception --
1285 -----------------------
1287 function Resolve_Exception
1288 (Occurrence : Exception_Occurrence)
1289 return Error_Type
1291 Id : Exception_Id := Exception_Identity (Occurrence);
1292 Msg : constant String := Exception_Message (Occurrence);
1293 First : Natural := Msg'First;
1294 Last : Natural;
1295 Val : Integer;
1297 begin
1298 while First <= Msg'Last
1299 and then Msg (First) not in '0' .. '9'
1300 loop
1301 First := First + 1;
1302 end loop;
1304 if First > Msg'Last then
1305 return Cannot_Resolve_Error;
1306 end if;
1308 Last := First;
1310 while Last < Msg'Last
1311 and then Msg (Last + 1) in '0' .. '9'
1312 loop
1313 Last := Last + 1;
1314 end loop;
1316 Val := Integer'Value (Msg (First .. Last));
1318 if Id = Socket_Error_Id then
1319 return Resolve_Error (Val);
1321 elsif Id = Host_Error_Id then
1322 return Resolve_Error (Val, False);
1324 else
1325 return Cannot_Resolve_Error;
1326 end if;
1327 end Resolve_Exception;
1329 --------------------
1330 -- Receive_Socket --
1331 --------------------
1333 procedure Receive_Socket
1334 (Socket : Socket_Type;
1335 Item : out Ada.Streams.Stream_Element_Array;
1336 Last : out Ada.Streams.Stream_Element_Offset)
1338 use type Ada.Streams.Stream_Element_Offset;
1340 Res : C.int;
1342 begin
1343 Res := C_Recv
1344 (C.int (Socket),
1345 Item (Item'First)'Address,
1346 Item'Length, 0);
1348 if Res = Failure then
1349 Raise_Socket_Error (Socket_Errno);
1350 end if;
1352 Last := Item'First + Ada.Streams.Stream_Element_Offset (Res - 1);
1353 end Receive_Socket;
1355 --------------------
1356 -- Receive_Socket --
1357 --------------------
1359 procedure Receive_Socket
1360 (Socket : Socket_Type;
1361 Item : out Ada.Streams.Stream_Element_Array;
1362 Last : out Ada.Streams.Stream_Element_Offset;
1363 From : out Sock_Addr_Type)
1365 use type Ada.Streams.Stream_Element_Offset;
1367 Res : C.int;
1368 Sin : aliased Sockaddr_In;
1369 Len : aliased C.int := Sin'Size / 8;
1371 begin
1372 Res := C_Recvfrom
1373 (C.int (Socket),
1374 Item (Item'First)'Address,
1375 Item'Length, 0,
1376 Sin'Unchecked_Access,
1377 Len'Unchecked_Access);
1379 if Res = Failure then
1380 Raise_Socket_Error (Socket_Errno);
1381 end if;
1383 Last := Item'First + Ada.Streams.Stream_Element_Offset (Res - 1);
1385 From.Addr := To_Inet_Addr (Sin.Sin_Addr);
1386 From.Port := Port_Type (Network_To_Port (Sin.Sin_Port));
1387 end Receive_Socket;
1389 -----------------
1390 -- Send_Socket --
1391 -----------------
1393 procedure Send_Socket
1394 (Socket : Socket_Type;
1395 Item : Ada.Streams.Stream_Element_Array;
1396 Last : out Ada.Streams.Stream_Element_Offset)
1398 use type Ada.Streams.Stream_Element_Offset;
1400 Res : C.int;
1402 begin
1403 Res := C_Send
1404 (C.int (Socket),
1405 Item (Item'First)'Address,
1406 Item'Length, 0);
1408 if Res = Failure then
1409 Raise_Socket_Error (Socket_Errno);
1410 end if;
1412 Last := Item'First + Ada.Streams.Stream_Element_Offset (Res - 1);
1413 end Send_Socket;
1415 -----------------
1416 -- Send_Socket --
1417 -----------------
1419 procedure Send_Socket
1420 (Socket : Socket_Type;
1421 Item : Ada.Streams.Stream_Element_Array;
1422 Last : out Ada.Streams.Stream_Element_Offset;
1423 To : Sock_Addr_Type)
1425 use type Ada.Streams.Stream_Element_Offset;
1427 Res : C.int;
1428 Sin : aliased Sockaddr_In;
1429 Len : aliased C.int := Sin'Size / 8;
1431 begin
1432 Sin.Sin_Family := C.unsigned_short (Families (To.Family));
1433 Sin.Sin_Addr := To_In_Addr (To.Addr);
1434 Sin.Sin_Port := Port_To_Network (C.unsigned_short (To.Port));
1436 Res := C_Sendto
1437 (C.int (Socket),
1438 Item (Item'First)'Address,
1439 Item'Length, 0,
1440 Sin'Unchecked_Access,
1441 Len);
1443 if Res = Failure then
1444 Raise_Socket_Error (Socket_Errno);
1445 end if;
1447 Last := Item'First + Ada.Streams.Stream_Element_Offset (Res - 1);
1448 end Send_Socket;
1450 ---------
1451 -- Set --
1452 ---------
1454 procedure Set (Item : in out Socket_Set_Type; Socket : Socket_Type) is
1455 begin
1456 if Item = null then
1457 Item := new Socket_Set_Record'(Socket_Set_Record (Null_Fd_Set));
1458 end if;
1460 Set (Fd_Set (Item.all), C.int (Socket));
1461 end Set;
1463 -----------------------
1464 -- Set_Socket_Option --
1465 -----------------------
1467 procedure Set_Socket_Option
1468 (Socket : Socket_Type;
1469 Level : Level_Type := Socket_Level;
1470 Option : Option_Type)
1472 V8 : aliased Two_Int;
1473 V4 : aliased C.int;
1474 V1 : aliased C.unsigned_char;
1475 Len : aliased C.int;
1476 Add : System.Address := Null_Address;
1477 Res : C.int;
1479 begin
1480 case Option.Name is
1481 when Keep_Alive |
1482 Reuse_Address |
1483 Broadcast |
1484 No_Delay =>
1485 V4 := C.int (Boolean'Pos (Option.Enabled));
1486 Len := V4'Size / 8;
1487 Add := V4'Address;
1489 when Linger =>
1490 V8 (V8'First) := C.int (Boolean'Pos (Option.Enabled));
1491 V8 (V8'Last) := C.int (Option.Seconds);
1492 Len := V8'Size / 8;
1493 Add := V8'Address;
1495 when Send_Buffer |
1496 Receive_Buffer =>
1497 V4 := C.int (Option.Size);
1498 Len := V4'Size / 8;
1499 Add := V4'Address;
1501 when Error =>
1502 V4 := C.int (Boolean'Pos (True));
1503 Len := V4'Size / 8;
1504 Add := V4'Address;
1506 when Add_Membership |
1507 Drop_Membership =>
1508 V8 (V8'First) := To_Int (To_In_Addr (Option.Multiaddr));
1509 V8 (V8'Last) := To_Int (To_In_Addr (Option.Interface));
1510 Len := V8'Size / 8;
1511 Add := V8'Address;
1513 when Multicast_TTL =>
1514 V1 := C.unsigned_char (Option.Time_To_Live);
1515 Len := V1'Size / 8;
1516 Add := V1'Address;
1518 when Multicast_Loop =>
1519 V1 := C.unsigned_char (Boolean'Pos (Option.Enabled));
1520 Len := V1'Size / 8;
1521 Add := V1'Address;
1523 end case;
1525 Res := C_Setsockopt
1526 (C.int (Socket),
1527 Levels (Level),
1528 Options (Option.Name),
1529 Add, Len);
1531 if Res = Failure then
1532 Raise_Socket_Error (Socket_Errno);
1533 end if;
1534 end Set_Socket_Option;
1536 ---------------------
1537 -- Shutdown_Socket --
1538 ---------------------
1540 procedure Shutdown_Socket
1541 (Socket : Socket_Type;
1542 How : Shutmode_Type := Shut_Read_Write)
1544 Res : C.int;
1546 begin
1547 Res := C_Shutdown (C.int (Socket), Shutmodes (How));
1549 if Res = Failure then
1550 Raise_Socket_Error (Socket_Errno);
1551 end if;
1552 end Shutdown_Socket;
1554 ------------
1555 -- Stream --
1556 ------------
1558 function Stream
1559 (Socket : Socket_Type;
1560 Send_To : Sock_Addr_Type)
1561 return Stream_Access
1563 S : Datagram_Socket_Stream_Access;
1565 begin
1566 S := new Datagram_Socket_Stream_Type;
1567 S.Socket := Socket;
1568 S.To := Send_To;
1569 S.From := Get_Socket_Name (Socket);
1570 return Stream_Access (S);
1571 end Stream;
1573 ------------
1574 -- Stream --
1575 ------------
1577 function Stream
1578 (Socket : Socket_Type)
1579 return Stream_Access
1581 S : Stream_Socket_Stream_Access;
1583 begin
1584 S := new Stream_Socket_Stream_Type;
1585 S.Socket := Socket;
1586 return Stream_Access (S);
1587 end Stream;
1589 ----------
1590 -- To_C --
1591 ----------
1593 function To_C (Socket : Socket_Type) return Integer is
1594 begin
1595 return Integer (Socket);
1596 end To_C;
1598 -------------------
1599 -- To_Host_Entry --
1600 -------------------
1602 function To_Host_Entry
1603 (Host : Hostent)
1604 return Host_Entry_Type
1606 use type C.size_t;
1608 Official : constant String :=
1609 C.Strings.Value (Host.H_Name);
1611 Aliases : constant Chars_Ptr_Array :=
1612 Chars_Ptr_Pointers.Value (Host.H_Aliases);
1613 -- H_Aliases points to a list of name aliases. The list is
1614 -- terminated by a NULL pointer.
1616 Addresses : constant In_Addr_Access_Array :=
1617 In_Addr_Access_Pointers.Value (Host.H_Addr_List);
1618 -- H_Addr_List points to a list of binary addresses (in network
1619 -- byte order). The list is terminated by a NULL pointer.
1621 -- H_Length is not used because it is currently only set to 4.
1622 -- H_Addrtype is always AF_INET
1624 Result : Host_Entry_Type
1625 (Aliases_Length => Aliases'Length - 1,
1626 Addresses_Length => Addresses'Length - 1);
1627 -- The last element is a null pointer.
1629 Source : C.size_t;
1630 Target : Natural;
1632 begin
1633 Result.Official := To_Host_Name (Official);
1635 Source := Aliases'First;
1636 Target := Result.Aliases'First;
1637 while Target <= Result.Aliases_Length loop
1638 Result.Aliases (Target) :=
1639 To_Host_Name (C.Strings.Value (Aliases (Source)));
1640 Source := Source + 1;
1641 Target := Target + 1;
1642 end loop;
1644 Source := Addresses'First;
1645 Target := Result.Addresses'First;
1646 while Target <= Result.Addresses_Length loop
1647 Result.Addresses (Target) :=
1648 To_Inet_Addr (Addresses (Source).all);
1649 Source := Source + 1;
1650 Target := Target + 1;
1651 end loop;
1653 return Result;
1654 end To_Host_Entry;
1656 ------------------
1657 -- To_Host_Name --
1658 ------------------
1660 function To_Host_Name (N : String) return Host_Name_Type is
1661 begin
1662 return (N'Length, N);
1663 end To_Host_Name;
1665 ----------------
1666 -- To_In_Addr --
1667 ----------------
1669 function To_In_Addr (Addr : Inet_Addr_Type) return Thin.In_Addr is
1670 begin
1671 if Addr.Family = Family_Inet then
1672 return (S_B1 => C.unsigned_char (Addr.Sin_V4 (1)),
1673 S_B2 => C.unsigned_char (Addr.Sin_V4 (2)),
1674 S_B3 => C.unsigned_char (Addr.Sin_V4 (3)),
1675 S_B4 => C.unsigned_char (Addr.Sin_V4 (4)));
1676 end if;
1678 raise Socket_Error;
1679 end To_In_Addr;
1681 ------------------
1682 -- To_Inet_Addr --
1683 ------------------
1685 function To_Inet_Addr
1686 (Addr : In_Addr)
1687 return Inet_Addr_Type
1689 Result : Inet_Addr_Type;
1691 begin
1692 Result.Sin_V4 (1) := Inet_Addr_Comp_Type (Addr.S_B1);
1693 Result.Sin_V4 (2) := Inet_Addr_Comp_Type (Addr.S_B2);
1694 Result.Sin_V4 (3) := Inet_Addr_Comp_Type (Addr.S_B3);
1695 Result.Sin_V4 (4) := Inet_Addr_Comp_Type (Addr.S_B4);
1697 return Result;
1698 end To_Inet_Addr;
1700 ---------------
1701 -- To_String --
1702 ---------------
1704 function To_String (HN : Host_Name_Type) return String is
1705 begin
1706 return HN.Name (1 .. HN.Length);
1707 end To_String;
1709 ----------------
1710 -- To_Timeval --
1711 ----------------
1713 function To_Timeval (Val : Duration) return Timeval is
1714 S : Timeval_Unit := Timeval_Unit (Val);
1715 MS : Timeval_Unit := Timeval_Unit (1_000_000 * (Val - Duration (S)));
1717 begin
1718 return (S, MS);
1719 end To_Timeval;
1721 -----------
1722 -- Write --
1723 -----------
1725 procedure Write
1726 (Stream : in out Datagram_Socket_Stream_Type;
1727 Item : Ada.Streams.Stream_Element_Array)
1729 First : Ada.Streams.Stream_Element_Offset := Item'First;
1730 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1731 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1733 begin
1734 loop
1735 Send_Socket
1736 (Stream.Socket,
1737 Item (First .. Max),
1738 Index,
1739 Stream.To);
1741 -- Exit when all or zero data sent. Zero means that the
1742 -- socket has been closed by peer.
1744 exit when Index < First or else Index = Max;
1746 First := Index + 1;
1747 end loop;
1749 if Index /= Max then
1750 raise Socket_Error;
1751 end if;
1752 end Write;
1754 -----------
1755 -- Write --
1756 -----------
1758 procedure Write
1759 (Stream : in out Stream_Socket_Stream_Type;
1760 Item : Ada.Streams.Stream_Element_Array)
1762 First : Ada.Streams.Stream_Element_Offset := Item'First;
1763 Index : Ada.Streams.Stream_Element_Offset := First - 1;
1764 Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
1766 begin
1767 loop
1768 Send_Socket (Stream.Socket, Item (First .. Max), Index);
1770 -- Exit when all or zero data sent. Zero means that the
1771 -- socket has been closed by peer.
1773 exit when Index < First or else Index = Max;
1775 First := Index + 1;
1776 end loop;
1778 if Index /= Max then
1779 raise Socket_Error;
1780 end if;
1781 end Write;
1783 end GNAT.Sockets;