1--
2--  Copyright (C) 2011-2013 secunet Security Networks AG
3--  Copyright (C) 2011-2014 Reto Buerki <reet@codelabs.ch>
4--  Copyright (C) 2011-2014 Adrian-Ken Rueegsegger <ken@codelabs.ch>
5--
6--  This program is free software; you can redistribute it and/or modify it
7--  under the terms of the GNU General Public License as published by the
8--  Free Software Foundation; either version 2 of the License, or (at your
9--  option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10--
11--  This program is distributed in the hope that it will be useful, but
12--  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13--  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14--  for more details.
15--
16--  As a special exception, if other files instantiate generics from this
17--  unit,  or  you  link  this  unit  with  other  files  to  produce  an
18--  executable   this  unit  does  not  by  itself  cause  the  resulting
19--  executable to  be  covered by the  GNU General  Public License.  This
20--  exception does  not  however  invalidate  any  other reasons why  the
21--  executable file might be covered by the GNU Public License.
22--
23
24private with Ada.Finalization;
25
26with Interfaces.C;
27
28with Anet.Constants;
29with Anet.Socket_Families;
30
31package Anet.Sockets is
32
33   type Mode_Type is
34     (Datagram_Socket,
35      Raw_Socket,
36      Stream_Socket);
37   --  Supported socket modes.
38
39   type Level_Type is (Socket_Level, TCP_Level);
40   --  Protocol level type.
41
42   type Sock_Shutdown_Cmd is
43     (Block_Reception,
44      Block_Transmission,
45      Block_All_Communication);
46   --  Socket shutdown methods.
47
48   type Socket_Type is abstract tagged limited private;
49   --  Communication socket.
50
51   procedure Close (Socket : in out Socket_Type);
52   --  Close given socket.
53
54   procedure Shutdown
55     (Socket : Socket_Type;
56      Method : Sock_Shutdown_Cmd);
57   --  Controlled shutdown of given socket.
58
59   procedure Send
60     (Socket : Socket_Type;
61      Item   : Ada.Streams.Stream_Element_Array);
62   --  Send data on socket to connected endpoint.
63
64   procedure Receive
65     (Socket :     Socket_Type;
66      Item   : out Ada.Streams.Stream_Element_Array;
67      Last   : out Ada.Streams.Stream_Element_Offset);
68   --  Receive data from given socket. This procedure blocks until data has
69   --  been received. Last is the index value such that Item (Last) is the last
70   --  character assigned. An exception is raised if a socket error occurs.
71
72   procedure Listen
73     (Socket  : Socket_Type;
74      Backlog : Positive := 1);
75   --  Listen for specified amount of requests on given socket.
76
77   --  Enable/disable non-blocking mode of operation. Newly created sockets
78   --  operate in blocking mode by default.
79   procedure Set_Nonblocking_Mode
80     (Socket : Socket_Type;
81      Enable : Boolean := True);
82
83   type Dgram_Socket_Type is limited interface;
84   --  Datagram socket.
85
86   type Stream_Socket_Type is limited interface;
87   --  Stream socket.
88
89   procedure Send
90     (Socket : Stream_Socket_Type;
91      Item   : Ada.Streams.Stream_Element_Array) is abstract;
92   --  Send data on socket to connected endpoint.
93
94   procedure Receive
95     (Socket :     Stream_Socket_Type;
96      Item   : out Ada.Streams.Stream_Element_Array;
97      Last   : out Ada.Streams.Stream_Element_Offset) is abstract;
98   --  Receive data from given socket. This procedure blocks until data has
99   --  been received. Last is the index value such that Item (Last) is the last
100   --  character assigned. An exception is raised if a socket error occurs.
101
102   procedure Listen
103     (Socket  : Stream_Socket_Type;
104      Backlog : Positive := 1) is abstract;
105   --  Listen for specified amount of requests on given socket.
106
107   procedure Accept_Connection
108     (Socket     :     Stream_Socket_Type;
109      New_Socket : out Stream_Socket_Type) is abstract;
110   --  Accept first connection request from listening socket and return new
111   --  connected socket.
112
113   type Option_Name_Bool is
114     (Broadcast,
115      Reuse_Address,
116      TCP_Nodelay);
117   --  Supported boolean socket options.
118
119   type Option_Name_Str is (Bind_To_Device);
120   --  Supported string based socket options.
121
122   procedure Set_Socket_Option
123     (Socket : Socket_Type;
124      Level  : Level_Type := Socket_Level;
125      Option : Option_Name_Bool;
126      Value  : Boolean);
127   --  Set socket option of given socket to specified boolean value. The level
128   --  argument specifies the protocol level this option applies to.
129
130   procedure Set_Socket_Option
131     (Socket : Socket_Type;
132      Level  : Level_Type := Socket_Level;
133      Option : Option_Name_Str;
134      Value  : String);
135   --  Set socket option of given socket to specified string value. The level
136   --  argument specifies the protocol level this option applies to.
137
138private
139
140   use type Interfaces.C.int;
141
142   Modes : constant array (Mode_Type) of Interfaces.C.int
143     := (Datagram_Socket => Constants.Sys.SOCK_DGRAM,
144         Raw_Socket      => Constants.SOCK_RAW,
145         Stream_Socket   => Constants.Sys.SOCK_STREAM);
146   --  Socket mode mapping.
147
148   Levels : constant array (Level_Type) of Interfaces.C.int
149     := (Socket_Level => Constants.Sys.SOL_SOCKET,
150         TCP_Level    => Constants.Sys.IPPROTO_TCP);
151   --  Protocol level mapping.
152
153   Options_Bool : constant array (Option_Name_Bool) of Interfaces.C.int
154     := (Reuse_Address => Constants.Sys.SO_REUSEADDR,
155         Broadcast     => Constants.Sys.SO_BROADCAST,
156         TCP_Nodelay   => Constants.Sys.TCP_NODELAY);
157   --  Mapping for option names with boolean value.
158
159   Options_Str : constant array (Option_Name_Str) of Interfaces.C.int
160     := (Bind_To_Device => Constants.SO_BINDTODEVICE);
161   --  Mapping for option names with string value.
162
163   Shutdown_Methods : constant array (Sock_Shutdown_Cmd) of Interfaces.C.int
164     := (Block_Reception         => Constants.Sys.SHUT_RD,
165         Block_Transmission      => Constants.Sys.SHUT_WR,
166         Block_All_Communication => Constants.Sys.SHUT_RDWR);
167   --  Mapping of socket shutdown methods.
168
169   type Socket_Type is new Ada.Finalization.Limited_Controlled with record
170      Sock_FD  : Interfaces.C.int := -1;
171      Protocol : Double_Byte      := 0;
172   end record;
173
174   overriding
175   procedure Finalize (Socket : in out Socket_Type);
176   --  Close socket.
177
178   procedure Init
179     (Socket   : in out Socket_Type;
180      Family   :        Socket_Families.Family_Type;
181      Mode     :        Mode_Type;
182      Protocol :        Double_Byte := 0);
183   --  Initialize given socket with specified family, mode and protocol.
184
185   procedure Check_Complete_Send
186     (Item      : Ada.Streams.Stream_Element_Array;
187      Result    : Interfaces.C.long;
188      Error_Msg : String);
189   --  Verify that a Send operation was able to transmit all bytes of given
190   --  buffer by calculating the actual number of bytes sent from the buffer
191   --  range and the send(2)/sendto(2) result specified. The procedure raises
192   --  an exception starting with the given error message if the check fails.
193
194   type Recv_Result_Type is
195     (Recv_Op_Ok,
196      Recv_Op_Aborted,
197      Recv_Op_Error,
198      Recv_Op_Orderly_Shutdown);
199   --  Receive operation result status.
200
201   function Check_Receive (Result : Interfaces.C.long) return Recv_Result_Type;
202   --  Determine the result of a receive operation.
203
204   type Accept_Result_Type is
205     (Accept_Op_Ok,
206      Accept_Op_Aborted,
207      Accept_Op_Error);
208   --  Accept operation result status.
209
210   function Check_Accept (Result : Interfaces.C.int) return Accept_Result_Type;
211   --  Determine the result of an accept operation.
212
213end Anet.Sockets;
214