1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . S O C K E T S . T H I N --
9 -- Copyright (C) 2001-2008, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 -- This package provides a target dependent thin interface to the sockets
35 -- layer for use by the GNAT.Sockets package (g-socket.ads). This package
36 -- should not be directly with'ed by an applications program.
38 -- This is the default version
40 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
43 with Interfaces
.C
; use Interfaces
.C
;
45 package body GNAT
.Sockets
.Thin
is
47 Non_Blocking_Sockets
: constant Fd_Set_Access
:=
48 New_Socket_Set
(No_Fd_Set_Access
);
49 -- When this package is initialized with Process_Blocking_IO set
50 -- to True, sockets are set in non-blocking mode to avoid blocking
51 -- the whole process when a thread wants to perform a blocking IO
52 -- operation. But the user can also set a socket in non-blocking
53 -- mode by purpose. In order to make a difference between these
54 -- two situations, we track the origin of non-blocking mode in
55 -- Non_Blocking_Sockets. If S is in Non_Blocking_Sockets, it has
56 -- been set in non-blocking mode by the user.
58 Quantum
: constant Duration := 0.2;
59 -- When SOSC.Thread_Blocking_IO is False, we set sockets in
60 -- non-blocking mode and we spend a period of time Quantum between
61 -- two attempts on a blocking operation.
63 Unknown_System_Error
: constant C
.Strings
.chars_ptr
:=
64 C
.Strings
.New_String
("Unknown system error");
66 -- Comments required for following functions ???
68 function Syscall_Accept
70 Addr
: System
.Address
;
71 Addrlen
: not null access C
.int
) return C
.int
;
72 pragma Import
(C
, Syscall_Accept
, "accept");
74 function Syscall_Connect
76 Name
: System
.Address
;
77 Namelen
: C
.int
) return C
.int
;
78 pragma Import
(C
, Syscall_Connect
, "connect");
80 function Syscall_Ioctl
83 Arg
: Int_Access
) return C
.int
;
84 pragma Import
(C
, Syscall_Ioctl
, "ioctl");
90 Flags
: C
.int
) return C
.int
;
91 pragma Import
(C
, Syscall_Recv
, "recv");
93 function Syscall_Recvfrom
98 From
: Sockaddr_In_Access
;
99 Fromlen
: not null access C
.int
) return C
.int
;
100 pragma Import
(C
, Syscall_Recvfrom
, "recvfrom");
102 function Syscall_Send
104 Msg
: System
.Address
;
106 Flags
: C
.int
) return C
.int
;
107 pragma Import
(C
, Syscall_Send
, "send");
109 function Syscall_Sendto
111 Msg
: System
.Address
;
114 To
: Sockaddr_In_Access
;
115 Tolen
: C
.int
) return C
.int
;
116 pragma Import
(C
, Syscall_Sendto
, "sendto");
118 function Syscall_Socket
121 Protocol
: C
.int
) return C
.int
;
122 pragma Import
(C
, Syscall_Socket
, "socket");
124 procedure Disable_SIGPIPE
(S
: C
.int
);
125 pragma Import
(C
, Disable_SIGPIPE
, "__gnat_disable_sigpipe");
127 procedure Disable_All_SIGPIPEs
;
128 pragma Import
(C
, Disable_All_SIGPIPEs
, "__gnat_disable_all_sigpipes");
129 -- Sets the process to ignore all SIGPIPE signals on platforms that
130 -- don't support Disable_SIGPIPE for particular streams.
132 function Non_Blocking_Socket
(S
: C
.int
) return Boolean;
133 procedure Set_Non_Blocking_Socket
(S
: C
.int
; V
: Boolean);
141 Addr
: System
.Address
;
142 Addrlen
: not null access C
.int
) return C
.int
145 Val
: aliased C
.int
:= 1;
148 pragma Warnings
(Off
, Discard
);
152 R
:= Syscall_Accept
(S
, Addr
, Addrlen
);
153 exit when SOSC
.Thread_Blocking_IO
155 or else Non_Blocking_Socket
(S
)
156 or else Errno
/= SOSC
.EWOULDBLOCK
;
160 if not SOSC
.Thread_Blocking_IO
161 and then R
/= Failure
163 -- A socket inherits the properties ot its server especially
164 -- the FIONBIO flag. Do not use C_Ioctl as this subprogram
165 -- tracks sockets set in non-blocking mode by user.
167 Set_Non_Blocking_Socket
(R
, Non_Blocking_Socket
(S
));
168 Discard
:= Syscall_Ioctl
(R
, SOSC
.FIONBIO
, Val
'Unchecked_Access);
181 Name
: System
.Address
;
182 Namelen
: C
.int
) return C
.int
187 Res
:= Syscall_Connect
(S
, Name
, Namelen
);
189 if SOSC
.Thread_Blocking_IO
190 or else Res
/= Failure
191 or else Non_Blocking_Socket
(S
)
192 or else Errno
/= SOSC
.EINPROGRESS
198 WSet
: Fd_Set_Access
;
199 Now
: aliased Timeval
;
202 WSet
:= New_Socket_Set
(No_Fd_Set_Access
);
204 Insert_Socket_In_Set
(WSet
, S
);
211 Now
'Unchecked_Access);
215 if Res
= Failure
then
216 Free_Socket_Set
(WSet
);
223 Free_Socket_Set
(WSet
);
226 Res
:= Syscall_Connect
(S
, Name
, Namelen
);
229 and then Errno
= SOSC
.EISCONN
231 return Thin_Common
.Success
;
244 Arg
: Int_Access
) return C
.int
247 if not SOSC
.Thread_Blocking_IO
248 and then Req
= SOSC
.FIONBIO
251 Set_Non_Blocking_Socket
(S
, True);
255 return Syscall_Ioctl
(S
, Req
, Arg
);
264 Msg
: System
.Address
;
266 Flags
: C
.int
) return C
.int
272 Res
:= Syscall_Recv
(S
, Msg
, Len
, Flags
);
273 exit when SOSC
.Thread_Blocking_IO
274 or else Res
/= Failure
275 or else Non_Blocking_Socket
(S
)
276 or else Errno
/= SOSC
.EWOULDBLOCK
;
289 Msg
: System
.Address
;
292 From
: Sockaddr_In_Access
;
293 Fromlen
: not null access C
.int
) return C
.int
299 Res
:= Syscall_Recvfrom
(S
, Msg
, Len
, Flags
, From
, Fromlen
);
300 exit when SOSC
.Thread_Blocking_IO
301 or else Res
/= Failure
302 or else Non_Blocking_Socket
(S
)
303 or else Errno
/= SOSC
.EWOULDBLOCK
;
316 Msg
: System
.Address
;
318 Flags
: C
.int
) return C
.int
324 Res
:= Syscall_Send
(S
, Msg
, Len
, Flags
);
325 exit when SOSC
.Thread_Blocking_IO
326 or else Res
/= Failure
327 or else Non_Blocking_Socket
(S
)
328 or else Errno
/= SOSC
.EWOULDBLOCK
;
341 Msg
: System
.Address
;
344 To
: Sockaddr_In_Access
;
345 Tolen
: C
.int
) return C
.int
351 Res
:= Syscall_Sendto
(S
, Msg
, Len
, Flags
, To
, Tolen
);
352 exit when SOSC
.Thread_Blocking_IO
353 or else Res
/= Failure
354 or else Non_Blocking_Socket
(S
)
355 or else Errno
/= SOSC
.EWOULDBLOCK
;
369 Protocol
: C
.int
) return C
.int
372 Val
: aliased C
.int
:= 1;
375 pragma Unreferenced
(Discard
);
378 R
:= Syscall_Socket
(Domain
, Typ
, Protocol
);
380 if not SOSC
.Thread_Blocking_IO
381 and then R
/= Failure
383 -- Do not use C_Ioctl as this subprogram tracks sockets set
384 -- in non-blocking mode by user.
386 Discard
:= Syscall_Ioctl
(R
, SOSC
.FIONBIO
, Val
'Unchecked_Access);
387 Set_Non_Blocking_Socket
(R
, False);
397 procedure Finalize
is
402 -------------------------
403 -- Host_Error_Messages --
404 -------------------------
406 package body Host_Error_Messages
is separate;
412 procedure Initialize
is
414 Disable_All_SIGPIPEs
;
417 -------------------------
418 -- Non_Blocking_Socket --
419 -------------------------
421 function Non_Blocking_Socket
(S
: C
.int
) return Boolean is
425 R
:= (Is_Socket_In_Set
(Non_Blocking_Sockets
, S
) /= 0);
428 end Non_Blocking_Socket
;
430 -----------------------------
431 -- Set_Non_Blocking_Socket --
432 -----------------------------
434 procedure Set_Non_Blocking_Socket
(S
: C
.int
; V
: Boolean) is
439 Insert_Socket_In_Set
(Non_Blocking_Sockets
, S
);
441 Remove_Socket_From_Set
(Non_Blocking_Sockets
, S
);
445 end Set_Non_Blocking_Socket
;
451 package body Signalling_Fds
is
453 -- In this default implementation, we use a C version of these
454 -- subprograms provided by socket.c.
456 function C_Create
(Fds
: not null access Fd_Pair
) return C
.int
;
457 function C_Read
(Rsig
: C
.int
) return C
.int
;
458 function C_Write
(Wsig
: C
.int
) return C
.int
;
459 procedure C_Close
(Sig
: C
.int
);
461 pragma Import
(C
, C_Create
, "__gnat_create_signalling_fds");
462 pragma Import
(C
, C_Read
, "__gnat_read_signalling_fd");
463 pragma Import
(C
, C_Write
, "__gnat_write_signalling_fd");
464 pragma Import
(C
, C_Close
, "__gnat_close_signalling_fd");
467 (Fds
: not null access Fd_Pair
) return C
.int
renames C_Create
;
468 function Read
(Rsig
: C
.int
) return C
.int
renames C_Read
;
469 function Write
(Wsig
: C
.int
) return C
.int
renames C_Write
;
470 procedure Close
(Sig
: C
.int
) renames C_Close
;
474 --------------------------
475 -- Socket_Error_Message --
476 --------------------------
478 function Socket_Error_Message
479 (Errno
: Integer) return C
.Strings
.chars_ptr
481 use type Interfaces
.C
.Strings
.chars_ptr
;
483 C_Msg
: C
.Strings
.chars_ptr
;
486 C_Msg
:= C_Strerror
(C
.int
(Errno
));
488 if C_Msg
= C
.Strings
.Null_Ptr
then
489 return Unknown_System_Error
;
493 end Socket_Error_Message
;
495 end GNAT
.Sockets
.Thin
;