1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . S O C K E T S . T H I N --
9 -- Copyright (C) 2002-2010, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This package provides a target dependent thin interface to the sockets
33 -- layer for use by the GNAT.Sockets package (g-socket.ads). This package
34 -- should not be directly with'ed by an applications program.
36 -- This version is for VxWorks
38 with GNAT.OS_Lib; use GNAT.OS_Lib;
41 with Interfaces.C; use Interfaces.C;
43 package body GNAT.Sockets.Thin is
45 Non_Blocking_Sockets : aliased Fd_Set;
46 -- When this package is initialized with Process_Blocking_IO set
47 -- to True, sockets are set in non-blocking mode to avoid blocking
48 -- the whole process when a thread wants to perform a blocking IO
49 -- operation. But the user can also set a socket in non-blocking
50 -- mode by purpose. In order to make a difference between these
51 -- two situations, we track the origin of non-blocking mode in
52 -- Non_Blocking_Sockets. If S is in Non_Blocking_Sockets, it has
53 -- been set in non-blocking mode by the user.
55 Quantum : constant Duration := 0.2;
56 -- When SOSC.Thread_Blocking_IO is False, we set sockets in
57 -- non-blocking mode and we spend a period of time Quantum between
58 -- two attempts on a blocking operation.
60 Unknown_System_Error : constant C.Strings.chars_ptr :=
61 C.Strings.New_String ("Unknown system error");
63 -----------------------
64 -- Local Subprograms --
65 -----------------------
67 -- All these require comments ???
69 function Syscall_Accept
71 Addr : System.Address;
72 Addrlen : not null access C.int) return C.int;
73 pragma Import (C, Syscall_Accept, "accept");
75 function Syscall_Connect
77 Name : System.Address;
78 Namelen : C.int) return C.int;
79 pragma Import (C, Syscall_Connect, "connect");
85 Flags : C.int) return C.int;
86 pragma Import (C, Syscall_Recv, "recv");
88 function Syscall_Recvfrom
93 From : System.Address;
94 Fromlen : not null access C.int) return C.int;
95 pragma Import (C, Syscall_Recvfrom, "recvfrom");
97 function Syscall_Recvmsg
100 Flags : C.int) return C.int;
101 pragma Import (C, Syscall_Recvmsg, "recvmsg");
103 function Syscall_Sendmsg
105 Msg : System.Address;
106 Flags : C.int) return C.int;
107 pragma Import (C, Syscall_Sendmsg, "sendmsg");
109 function Syscall_Send
111 Msg : System.Address;
113 Flags : C.int) return C.int;
114 pragma Import (C, Syscall_Send, "send");
116 function Syscall_Sendto
118 Msg : System.Address;
122 Tolen : C.int) return C.int;
123 pragma Import (C, Syscall_Sendto, "sendto");
125 function Syscall_Socket
128 Protocol : C.int) return C.int;
129 pragma Import (C, Syscall_Socket, "socket");
131 function Non_Blocking_Socket (S : C.int) return Boolean;
132 procedure Set_Non_Blocking_Socket (S : C.int; V : Boolean);
140 Addr : System.Address;
141 Addrlen : not null access C.int) return C.int
144 Val : aliased C.int := 1;
147 pragma Unreferenced (Res);
151 R := Syscall_Accept (S, Addr, Addrlen);
152 exit when SOSC.Thread_Blocking_IO
154 or else Non_Blocking_Socket (S)
155 or else Errno /= SOSC.EWOULDBLOCK;
159 if not SOSC.Thread_Blocking_IO
160 and then R /= Failure
162 -- A socket inherits the properties of its server especially
163 -- the FIONBIO flag. Do not use Socket_Ioctl as this subprogram
164 -- tracks sockets set in non-blocking mode by user.
166 Set_Non_Blocking_Socket (R, Non_Blocking_Socket (S));
167 Res := C_Ioctl (R, SOSC.FIONBIO, Val'Access);
168 -- Is it OK to ignore result ???
180 Name : System.Address;
181 Namelen : C.int) return C.int
186 Res := Syscall_Connect (S, Name, Namelen);
188 if SOSC.Thread_Blocking_IO
189 or else Res /= Failure
190 or else Non_Blocking_Socket (S)
191 or else Errno /= SOSC.EINPROGRESS
197 WSet : aliased Fd_Set;
198 Now : aliased Timeval;
200 Reset_Socket_Set (WSet'Access);
202 Insert_Socket_In_Set (WSet'Access, S);
209 Now'Unchecked_Access);
213 if Res = Failure then
221 Res := Syscall_Connect (S, Name, Namelen);
224 and then Errno = SOSC.EISCONN
226 return Thin_Common.Success;
236 function Socket_Ioctl
239 Arg : access C.int) return C.int
242 if not SOSC.Thread_Blocking_IO and then Req = SOSC.FIONBIO then
244 Set_Non_Blocking_Socket (S, True);
248 return C_Ioctl (S, Req, Arg);
257 Msg : System.Address;
259 Flags : C.int) return C.int
265 Res := Syscall_Recv (S, Msg, Len, Flags);
266 exit when SOSC.Thread_Blocking_IO
267 or else Res /= Failure
268 or else Non_Blocking_Socket (S)
269 or else Errno /= SOSC.EWOULDBLOCK;
282 Msg : System.Address;
285 From : System.Address;
286 Fromlen : not null access C.int) return C.int
292 Res := Syscall_Recvfrom (S, Msg, Len, Flags, From, Fromlen);
293 exit when SOSC.Thread_Blocking_IO
294 or else Res /= Failure
295 or else Non_Blocking_Socket (S)
296 or else Errno /= SOSC.EWOULDBLOCK;
309 Msg : System.Address;
310 Flags : C.int) return System.CRTL.ssize_t
316 Res := Syscall_Recvmsg (S, Msg, Flags);
317 exit when SOSC.Thread_Blocking_IO
318 or else Res /= Failure
319 or else Non_Blocking_Socket (S)
320 or else Errno /= SOSC.EWOULDBLOCK;
324 return System.CRTL.ssize_t (Res);
333 Msg : System.Address;
334 Flags : C.int) return System.CRTL.ssize_t
340 Res := Syscall_Sendmsg (S, Msg, Flags);
341 exit when SOSC.Thread_Blocking_IO
342 or else Res /= Failure
343 or else Non_Blocking_Socket (S)
344 or else Errno /= SOSC.EWOULDBLOCK;
348 return System.CRTL.ssize_t (Res);
357 Msg : System.Address;
361 Tolen : C.int) return C.int
369 if To = Null_Address then
371 -- In violation of the standard sockets API, VxWorks does not
372 -- support sendto(2) calls on connected sockets with a null
373 -- destination address, so use send(2) instead in that case.
375 Res := Syscall_Send (S, Msg, Len, Flags);
377 -- Normal case where destination address is non-null
380 Res := Syscall_Sendto (S, Msg, Len, Flags, To, Tolen);
383 exit when SOSC.Thread_Blocking_IO
384 or else Res /= Failure
385 or else Non_Blocking_Socket (S)
386 or else Errno /= SOSC.EWOULDBLOCK;
400 Protocol : C.int) return C.int
403 Val : aliased C.int := 1;
406 pragma Unreferenced (Res);
409 R := Syscall_Socket (Domain, Typ, Protocol);
411 if not SOSC.Thread_Blocking_IO
412 and then R /= Failure
414 -- Do not use Socket_Ioctl as this subprogram tracks sockets set
415 -- in non-blocking mode by user.
417 Res := C_Ioctl (R, SOSC.FIONBIO, Val'Access);
418 -- Is it OK to ignore result ???
419 Set_Non_Blocking_Socket (R, False);
429 procedure Finalize is
434 -------------------------
435 -- Host_Error_Messages --
436 -------------------------
438 package body Host_Error_Messages is separate;
444 procedure Initialize is
446 Reset_Socket_Set (Non_Blocking_Sockets'Access);
449 -------------------------
450 -- Non_Blocking_Socket --
451 -------------------------
453 function Non_Blocking_Socket (S : C.int) return Boolean is
457 R := (Is_Socket_In_Set (Non_Blocking_Sockets'Access, S) /= 0);
460 end Non_Blocking_Socket;
462 -----------------------------
463 -- Set_Non_Blocking_Socket --
464 -----------------------------
466 procedure Set_Non_Blocking_Socket (S : C.int; V : Boolean) is
470 Insert_Socket_In_Set (Non_Blocking_Sockets'Access, S);
472 Remove_Socket_From_Set (Non_Blocking_Sockets'Access, S);
476 end Set_Non_Blocking_Socket;
482 package body Signalling_Fds is separate;
484 --------------------------
485 -- Socket_Error_Message --
486 --------------------------
488 function Socket_Error_Message
489 (Errno : Integer) return C.Strings.chars_ptr
492 end GNAT.Sockets.Thin;