1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--              G N A T . S O C K E T S . T H I N _ C O M M O N             --
6--                                                                          --
7--                                 S p e c                                  --
8--                                                                          --
9--                     Copyright (C) 2008-2018, AdaCore                     --
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 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.                                     --
17--                                                                          --
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.               --
21--                                                                          --
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/>.                                          --
26--                                                                          --
27-- GNAT was originally developed  by the GNAT team at  New York University. --
28-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29--                                                                          --
30------------------------------------------------------------------------------
31
32--  This is the target-independent part of the thin sockets mapping.
33--  This package should not be directly with'ed by an applications program.
34
35with Ada.Unchecked_Conversion;
36
37with Interfaces.C;
38with Interfaces.C.Pointers;
39
40package GNAT.Sockets.Thin_Common is
41
42   package C renames Interfaces.C;
43
44   Success : constant C.int :=  0;
45   Failure : constant C.int := -1;
46
47   type time_t is
48     range -2 ** (8 * SOSC.SIZEOF_tv_sec - 1)
49         .. 2 ** (8 * SOSC.SIZEOF_tv_sec - 1) - 1;
50   for time_t'Size use 8 * SOSC.SIZEOF_tv_sec;
51   pragma Convention (C, time_t);
52
53   type suseconds_t is
54     range -2 ** (8 * SOSC.SIZEOF_tv_usec - 1)
55         .. 2 ** (8 * SOSC.SIZEOF_tv_usec - 1) - 1;
56   for suseconds_t'Size use 8 * SOSC.SIZEOF_tv_usec;
57   pragma Convention (C, suseconds_t);
58
59   type Timeval is record
60      Tv_Sec  : time_t;
61      Tv_Usec : suseconds_t;
62   end record;
63   pragma Convention (C, Timeval);
64
65   type Timeval_Access is access all Timeval;
66   pragma Convention (C, Timeval_Access);
67
68   Immediat : constant Timeval := (0, 0);
69
70   -------------------------------------------
71   -- Mapping tables to low level constants --
72   -------------------------------------------
73
74   Families : constant array (Family_Type) of C.int :=
75                (Family_Inet  => SOSC.AF_INET,
76                 Family_Inet6 => SOSC.AF_INET6);
77
78   Lengths  : constant array (Family_Type) of C.unsigned_char :=
79                (Family_Inet  => SOSC.SIZEOF_sockaddr_in,
80                 Family_Inet6 => SOSC.SIZEOF_sockaddr_in6);
81
82   ----------------------------
83   -- Generic socket address --
84   ----------------------------
85
86   --  Common header
87
88   --  All socket address types (struct sockaddr, struct sockaddr_storage,
89   --  and protocol specific address types) start with the same 2-byte header,
90   --  which is either a length and a family (one byte each) or just a two-byte
91   --  family. The following unchecked union describes the two possible layouts
92   --  and is meant to be constrained with SOSC.Have_Sockaddr_Len.
93
94   type Sockaddr_Length_And_Family
95     (Has_Sockaddr_Len : Boolean := False)
96   is record
97      case Has_Sockaddr_Len is
98         when True =>
99            Length      : C.unsigned_char;
100            Char_Family : C.unsigned_char;
101
102         when False =>
103            Short_Family : C.unsigned_short;
104      end case;
105   end record;
106   pragma Unchecked_Union (Sockaddr_Length_And_Family);
107   pragma Convention (C, Sockaddr_Length_And_Family);
108
109   procedure Set_Family
110     (Length_And_Family : out Sockaddr_Length_And_Family;
111      Family            : Family_Type);
112   --  Set the family component to the appropriate value for Family, and also
113   --  set Length accordingly if applicable on this platform.
114
115   type Sockaddr is record
116      Sa_Family : Sockaddr_Length_And_Family;
117      --  Address family (and address length on some platforms)
118
119      Sa_Data : C.char_array (1 .. 14) := (others => C.nul);
120      --  Family-specific data
121      --  Note that some platforms require that all unused (reserved) bytes
122      --  in addresses be initialized to 0 (e.g. VxWorks).
123   end record;
124   pragma Convention (C, Sockaddr);
125   --  Generic socket address
126
127   type Sockaddr_Access is access all Sockaddr;
128   pragma Convention (C, Sockaddr_Access);
129   --  Access to socket address
130
131   ----------------------------
132   -- AF_INET socket address --
133   ----------------------------
134
135   type In_Addr is record
136      S_B1, S_B2, S_B3, S_B4 : C.unsigned_char;
137   end record;
138   for In_Addr'Alignment use C.int'Alignment;
139   pragma Convention (C, In_Addr);
140   --  IPv4 address, represented as a network-order C.int. Note that the
141   --  underlying operating system may assume that values of this type have
142   --  C.int alignment, so we need to provide a suitable alignment clause here.
143
144   function To_In_Addr is new Ada.Unchecked_Conversion (C.int, In_Addr);
145   function To_Int     is new Ada.Unchecked_Conversion (In_Addr, C.int);
146
147   type In_Addr_Access is access all In_Addr;
148   pragma Convention (C, In_Addr_Access);
149   --  Access to internet address
150
151   Inaddr_Any : aliased constant In_Addr := (others => 0);
152   --  Any internet address (all the interfaces)
153
154   type In_Addr_Access_Array is array (C.size_t range <>)
155     of aliased In_Addr_Access;
156   pragma Convention (C, In_Addr_Access_Array);
157
158   package In_Addr_Access_Pointers is new C.Pointers
159     (C.size_t, In_Addr_Access, In_Addr_Access_Array, null);
160   --  Array of internet addresses
161
162   type Sockaddr_In is record
163      Sin_Family : Sockaddr_Length_And_Family;
164      --  Address family (and address length on some platforms)
165
166      Sin_Port : C.unsigned_short;
167      --  Port in network byte order
168
169      Sin_Addr : In_Addr;
170      --  IPv4 address
171
172      Sin_Zero : C.char_array (1 .. 8) := (others => C.nul);
173      --  Padding
174      --
175      --  Note that some platforms require that all unused (reserved) bytes
176      --  in addresses be initialized to 0 (e.g. VxWorks).
177   end record;
178   pragma Convention (C, Sockaddr_In);
179   --  Internet socket address
180
181   type Sockaddr_In_Access is access all Sockaddr_In;
182   pragma Convention (C, Sockaddr_In_Access);
183   --  Access to internet socket address
184
185   procedure Set_Port
186     (Sin  : Sockaddr_In_Access;
187      Port : C.unsigned_short);
188   pragma Inline (Set_Port);
189   --  Set Sin.Sin_Port to Port
190
191   procedure Set_Address
192     (Sin     : Sockaddr_In_Access;
193      Address : In_Addr);
194   pragma Inline (Set_Address);
195   --  Set Sin.Sin_Addr to Address
196
197   ------------------
198   -- Host entries --
199   ------------------
200
201   type Hostent is new
202     System.Storage_Elements.Storage_Array (1 .. SOSC.SIZEOF_struct_hostent);
203   for Hostent'Alignment use 8;
204   --  Host entry. This is an opaque type used only via the following
205   --  accessor functions, because 'struct hostent' has different layouts on
206   --  different platforms.
207
208   type Hostent_Access is access all Hostent;
209   pragma Convention (C, Hostent_Access);
210   --  Access to host entry
211
212   function Hostent_H_Name
213     (E : Hostent_Access) return System.Address;
214
215   function Hostent_H_Alias
216     (E : Hostent_Access; I : C.int) return System.Address;
217
218   function Hostent_H_Addrtype
219     (E : Hostent_Access) return C.int;
220
221   function Hostent_H_Length
222     (E : Hostent_Access) return C.int;
223
224   function Hostent_H_Addr
225     (E : Hostent_Access; Index : C.int) return System.Address;
226
227   ---------------------
228   -- Service entries --
229   ---------------------
230
231   type Servent is new
232     System.Storage_Elements.Storage_Array (1 .. SOSC.SIZEOF_struct_servent);
233   for Servent'Alignment use 8;
234   --  Service entry. This is an opaque type used only via the following
235   --  accessor functions, because 'struct servent' has different layouts on
236   --  different platforms.
237
238   type Servent_Access is access all Servent;
239   pragma Convention (C, Servent_Access);
240   --  Access to service entry
241
242   function Servent_S_Name
243     (E : Servent_Access) return System.Address;
244
245   function Servent_S_Alias
246     (E : Servent_Access; Index : C.int) return System.Address;
247
248   function Servent_S_Port
249     (E : Servent_Access) return C.unsigned_short;
250
251   function Servent_S_Proto
252     (E : Servent_Access) return System.Address;
253
254   ------------------
255   -- NetDB access --
256   ------------------
257
258   --  There are three possible situations for the following NetDB access
259   --  functions:
260   --    - inherently thread safe (case of data returned in a thread specific
261   --      buffer);
262   --    - thread safe using user-provided buffer;
263   --    - thread unsafe.
264   --
265   --  In the first and third cases, the Buf and Buflen are ignored. In the
266   --  second case, the caller must provide a buffer large enough to
267   --  accommodate the returned data. In the third case, the caller must ensure
268   --  that these functions are called within a critical section.
269
270   function C_Gethostbyname
271     (Name     : C.char_array;
272      Ret      : not null access Hostent;
273      Buf      : System.Address;
274      Buflen   : C.int;
275      H_Errnop : not null access C.int) return C.int;
276
277   function C_Gethostbyaddr
278     (Addr      : System.Address;
279      Addr_Len  : C.int;
280      Addr_Type : C.int;
281      Ret       : not null access Hostent;
282      Buf       : System.Address;
283      Buflen    : C.int;
284      H_Errnop  : not null access C.int) return C.int;
285
286   function C_Getservbyname
287     (Name   : C.char_array;
288      Proto  : C.char_array;
289      Ret    : not null access Servent;
290      Buf    : System.Address;
291      Buflen : C.int) return C.int;
292
293   function C_Getservbyport
294     (Port   : C.int;
295      Proto  : C.char_array;
296      Ret    : not null access Servent;
297      Buf    : System.Address;
298      Buflen : C.int) return C.int;
299
300   ------------------------------------
301   -- Scatter/gather vector handling --
302   ------------------------------------
303
304   type Msghdr is record
305      Msg_Name       : System.Address;
306      Msg_Namelen    : C.unsigned;
307      Msg_Iov        : System.Address;
308      Msg_Iovlen     : SOSC.Msg_Iovlen_T;
309      Msg_Control    : System.Address;
310      Msg_Controllen : C.size_t;
311      Msg_Flags      : C.int;
312   end record;
313   pragma Convention (C, Msghdr);
314
315   ----------------------------
316   -- Socket sets management --
317   ----------------------------
318
319   procedure Get_Socket_From_Set
320     (Set    : access Fd_Set;
321      Last   : access C.int;
322      Socket : access C.int);
323   --  Get last socket in Socket and remove it from the socket set. The
324   --  parameter Last is a maximum value of the largest socket. This hint is
325   --  used to avoid scanning very large socket sets. After a call to
326   --  Get_Socket_From_Set, Last is set back to the real largest socket in the
327   --  socket set.
328
329   procedure Insert_Socket_In_Set
330     (Set    : access Fd_Set;
331      Socket : C.int);
332   --  Insert socket in the socket set
333
334   function  Is_Socket_In_Set
335     (Set    : access constant Fd_Set;
336      Socket : C.int) return C.int;
337   --  Check whether Socket is in the socket set, return a non-zero
338   --  value if it is, zero if it is not.
339
340   procedure Last_Socket_In_Set
341     (Set  : access Fd_Set;
342      Last : access C.int);
343   --  Find the largest socket in the socket set. This is needed for select().
344   --  When Last_Socket_In_Set is called, parameter Last is a maximum value of
345   --  the largest socket. This hint is used to avoid scanning very large
346   --  socket sets. After the call, Last is set back to the real largest socket
347   --  in the socket set.
348
349   procedure Remove_Socket_From_Set (Set : access Fd_Set; Socket : C.int);
350   --  Remove socket from the socket set
351
352   procedure Reset_Socket_Set (Set : access Fd_Set);
353   --  Make Set empty
354
355   ------------------------------------------
356   -- Pairs of signalling file descriptors --
357   ------------------------------------------
358
359   type Two_Ints is array (0 .. 1) of C.int;
360   pragma Convention (C, Two_Ints);
361   --  Container for two int values
362
363   subtype Fd_Pair is Two_Ints;
364   --  Two_Ints as used for Create_Signalling_Fds: a pair of connected file
365   --  descriptors, one of which (the "read end" of the connection) being used
366   --  for reading, the other one (the "write end") being used for writing.
367
368   Read_End  : constant := 0;
369   Write_End : constant := 1;
370   --  Indexes into an Fd_Pair value providing access to each of the connected
371   --  file descriptors.
372
373   function Inet_Pton
374     (Af  : C.int;
375      Cp  : System.Address;
376      Inp : System.Address) return C.int;
377
378   function C_Ioctl
379     (Fd  : C.int;
380      Req : SOSC.IOCTL_Req_T;
381      Arg : access C.int) return C.int;
382
383private
384   pragma Import (C, Get_Socket_From_Set, "__gnat_get_socket_from_set");
385   pragma Import (C, Is_Socket_In_Set, "__gnat_is_socket_in_set");
386   pragma Import (C, Last_Socket_In_Set, "__gnat_last_socket_in_set");
387   pragma Import (C, Insert_Socket_In_Set, "__gnat_insert_socket_in_set");
388   pragma Import (C, Remove_Socket_From_Set, "__gnat_remove_socket_from_set");
389   pragma Import (C, Reset_Socket_Set, "__gnat_reset_socket_set");
390   pragma Import (C, C_Ioctl, "__gnat_socket_ioctl");
391   pragma Import (C, Inet_Pton, SOSC.Inet_Pton_Linkname);
392
393   pragma Import (C, C_Gethostbyname, "__gnat_gethostbyname");
394   pragma Import (C, C_Gethostbyaddr, "__gnat_gethostbyaddr");
395   pragma Import (C, C_Getservbyname, "__gnat_getservbyname");
396   pragma Import (C, C_Getservbyport, "__gnat_getservbyport");
397
398   pragma Import (C, Servent_S_Name,  "__gnat_servent_s_name");
399   pragma Import (C, Servent_S_Alias, "__gnat_servent_s_alias");
400   pragma Import (C, Servent_S_Port,  "__gnat_servent_s_port");
401   pragma Import (C, Servent_S_Proto, "__gnat_servent_s_proto");
402
403   pragma Import (C, Hostent_H_Name,     "__gnat_hostent_h_name");
404   pragma Import (C, Hostent_H_Alias,    "__gnat_hostent_h_alias");
405   pragma Import (C, Hostent_H_Addrtype, "__gnat_hostent_h_addrtype");
406   pragma Import (C, Hostent_H_Length,   "__gnat_hostent_h_length");
407   pragma Import (C, Hostent_H_Addr,     "__gnat_hostent_h_addr");
408
409end GNAT.Sockets.Thin_Common;
410