OSDN Git Service

2009-02-27 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / ada / g-socket.ads
index 3f37bb5..cd12b01 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---                     Copyright (C) 2001-2007, AdaCore                     --
+--                     Copyright (C) 2001-2008, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -39,8 +39,7 @@
 
 --       Multicast is available only on systems which provide support for this
 --       feature, so it is not available if Multicast is not supported, or not
---       installed. In particular Multicast is not available with the Windows
---       version.
+--       installed.
 
 --       The VMS implementation was implemented using the DECC RTL Socket API,
 --       and is thus subject to limitations in the implementation of this API.
@@ -53,13 +52,18 @@ with Ada.Exceptions;
 with Ada.Streams;
 with Ada.Unchecked_Deallocation;
 
-with System;
+with System.OS_Constants;
 
 package GNAT.Sockets is
 
    --  Sockets are designed to provide a consistent communication facility
-   --  between applications. This package provides an Ada-like interface
-   --  similar to that proposed as part of the BSD socket layer.
+   --  between applications. This package provides an Ada binding to the
+   --  the de-facto standard BSD sockets API. The documentation below covers
+   --  only the specific binding provided by this package. It assumes that
+   --  the reader is already familiar with general network programming and
+   --  sockets usage. A useful reference on this matter is W. Richard Stevens'
+   --  "UNIX Network Programming: The Sockets Networking API"
+   --  (ISBN: 0131411551).
 
    --  GNAT.Sockets has been designed with several ideas in mind
 
@@ -78,7 +82,7 @@ package GNAT.Sockets is
    --  notification of an asynchronous connect failure is delivered in the
    --  write socket set (POSIX) instead of the exception socket set (NT).
 
-   --  Here is a typical example of what you can do:
+   --  The example below demonstrates various features of GNAT.Sockets:
 
    --  with GNAT.Sockets; use GNAT.Sockets;
 
@@ -180,13 +184,6 @@ package GNAT.Sockets is
    --           Socket_Level,
    --           (Reuse_Address, True));
 
-   --        --  Join a multicast group
-
-   --        Set_Socket_Option
-   --          (Socket,
-   --           IP_Protocol_For_IP_Level,
-   --           (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
-
    --        --  Controls the live time of the datagram to avoid it being
    --        --  looped forever due to routing errors. Routers decrement
    --        --  the TTL of every datagram as it traverses from one network
@@ -213,6 +210,16 @@ package GNAT.Sockets is
 
    --        Bind_Socket (Socket, Address);
 
+   --        --  Join a multicast group
+
+   --        --  Portability note: On Windows, this option may be set only
+   --        --  on a bound socket.
+
+   --        Set_Socket_Option
+   --          (Socket,
+   --           IP_Protocol_For_IP_Level,
+   --           (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
+
    --        --  If this socket is intended to send messages, provide the
    --        --  receiver socket address.
 
@@ -308,11 +315,6 @@ package GNAT.Sockets is
    --        Set_Socket_Option
    --          (Socket,
    --           IP_Protocol_For_IP_Level,
-   --           (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
-
-   --        Set_Socket_Option
-   --          (Socket,
-   --           IP_Protocol_For_IP_Level,
    --           (Multicast_TTL, 1));
 
    --        Set_Socket_Option
@@ -325,6 +327,11 @@ package GNAT.Sockets is
 
    --        Bind_Socket (Socket, Address);
 
+   --        Set_Socket_Option
+   --          (Socket,
+   --           IP_Protocol_For_IP_Level,
+   --           (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
+
    --        Address.Addr := Inet_Addr (Group);
    --        Address.Port := 55505;
 
@@ -362,6 +369,12 @@ package GNAT.Sockets is
    --     Finalize;
    --  end PingPong;
 
+   package SOSC renames System.OS_Constants;
+   --  Renaming used to provide short-hand notations throughout the sockets
+   --  binding. Note that System.OS_Constants is an internal unit, and the
+   --  entities declared therein are not meant for direct access by users,
+   --  including through this renaming.
+
    procedure Initialize;
    --  Initialize must be called before using any other socket routines.
    --  Note that this operation is a no-op on UNIX platforms, but applications
@@ -390,6 +403,33 @@ package GNAT.Sockets is
 
    No_Socket : constant Socket_Type;
 
+   type Selector_Type is limited private;
+   type Selector_Access is access all Selector_Type;
+   --  Selector objects are used to wait for i/o events to occur on sockets
+
+   --  Timeval_Duration is a subtype of Standard.Duration because the full
+   --  range of Standard.Duration cannot be represented in the equivalent C
+   --  structure. Moreover, negative values are not allowed to avoid system
+   --  incompatibilities.
+
+   Immediate : constant Duration := 0.0;
+
+   Timeval_Forever : constant := 2.0 ** (SOSC.SIZEOF_tv_sec * 8 - 1) - 1.0;
+   Forever         : constant Duration :=
+                       Duration'Min (Duration'Last, Timeval_Forever);
+
+   subtype Timeval_Duration is Duration range Immediate .. Forever;
+
+   subtype Selector_Duration is Timeval_Duration;
+   --  Timeout value for selector operations
+
+   type Selector_Status is (Completed, Expired, Aborted);
+   --  Completion status of a selector operation, indicated as follows:
+   --    Complete: one of the expected events occurred
+   --    Expired:  no event occurred before the expiration of the timeout
+   --    Aborted:  an external action cancelled the wait operation before
+   --              any event occurred.
+
    Socket_Error : exception;
    --  There is only one exception in this package to deal with an error during
    --  a socket routine. Once raised, its message contains a string describing
@@ -428,10 +468,10 @@ package GNAT.Sockets is
    No_Port  : constant Port_Type;
 
    type Inet_Addr_Type (Family : Family_Type := Family_Inet) is private;
-   --  An Internet address depends on an address family (IPv4 contains 4
-   --  octets and Ipv6 contains 16 octets). Any_Inet_Addr is a special value
-   --  treated like a wildcard enabling all addresses. No_Inet_Addr provides a
-   --  special value to denote uninitialized inet addresses.
+   --  An Internet address depends on an address family (IPv4 contains 4 octets
+   --  and IPv6 contains 16 octets). Any_Inet_Addr is a special value treated
+   --  like a wildcard enabling all addresses. No_Inet_Addr provides a special
+   --  value to denote uninitialized inet addresses.
 
    Any_Inet_Addr       : constant Inet_Addr_Type;
    No_Inet_Addr        : constant Inet_Addr_Type;
@@ -501,8 +541,8 @@ package GNAT.Sockets is
    function Get_Host_By_Name
      (Name : String) return Host_Entry_Type;
    --  Return host entry structure for the given host name. Here name is
-   --  either a host name, or an IP address. If Name is an IP address, this is
-   --  equivalent to Get_Host_By_Address (Inet_Addr (Name)).
+   --  either a host name, or an IP address. If Name is an IP address, this
+   --  is equivalent to Get_Host_By_Address (Inet_Addr (Name)).
 
    function Host_Name return String;
    --  Return the name of the current host
@@ -542,10 +582,10 @@ package GNAT.Sockets is
    Service_Error : exception;
    --  Comment required ???
 
-   --  Errors are described by an enumeration type. There is only one
-   --  exception Socket_Error in this package to deal with an error during a
-   --  socket routine. Once raised, its message contains the error code
-   --  between brackets and a string describing the error code.
+   --  Errors are described by an enumeration type. There is only one exception
+   --  Socket_Error in this package to deal with an error during a socket
+   --  routine. Once raised, its message contains the error code between
+   --  brackets and a string describing the error code.
 
    --  The name of the enumeration constant documents the error condition
 
@@ -595,16 +635,6 @@ package GNAT.Sockets is
       Unknown_Server_Error,
       Cannot_Resolve_Error);
 
-   --  Timeval_Duration is a subtype of Standard.Duration because the full
-   --  range of Standard.Duration cannot be represented in the equivalent C
-   --  structure. Moreover, negative values are not allowed to avoid system
-   --  incompatibilities.
-
-   Immediate : constant := 0.0;
-   Forever   : constant := Duration (Integer'Last) * 1.0;
-
-   subtype Timeval_Duration is Duration range Immediate .. Forever;
-
    --  Get_Socket_Options and Set_Socket_Options manipulate options associated
    --  with a socket. Options may exist at multiple protocol levels in the
    --  communication stack. Socket_Level is the uppermost socket level.
@@ -620,30 +650,32 @@ package GNAT.Sockets is
    --  a boolean to enable or disable this option.
 
    type Option_Name is (
-     Keep_Alive,       -- Enable sending of keep-alive messages
-     Reuse_Address,    -- Allow bind to reuse local address
-     Broadcast,        -- Enable datagram sockets to recv/send broadcasts
-     Send_Buffer,      -- Set/get the maximum socket send buffer in bytes
-     Receive_Buffer,   -- Set/get the maximum socket recv buffer in bytes
-     Linger,           -- Shutdown wait for msg to be sent or timeout occur
-     Error,            -- Get and clear the pending socket error
-     No_Delay,         -- Do not delay send to coalesce packets (TCP_NODELAY)
-     Add_Membership,   -- Join a multicast group
-     Drop_Membership,  -- Leave a multicast group
-     Multicast_If,     -- Set default outgoing interface for multicast packets
-     Multicast_TTL,    -- Indicate the time-to-live of sent multicast packets
-     Multicast_Loop,   -- Sent multicast packets are looped to local socket
-     Send_Timeout,     -- Set timeout value for output
-     Receive_Timeout); -- Set timeout value for input
+     Keep_Alive,          -- Enable sending of keep-alive messages
+     Reuse_Address,       -- Allow bind to reuse local address
+     Broadcast,           -- Enable datagram sockets to recv/send broadcasts
+     Send_Buffer,         -- Set/get the maximum socket send buffer in bytes
+     Receive_Buffer,      -- Set/get the maximum socket recv buffer in bytes
+     Linger,              -- Shutdown wait for msg to be sent or timeout occur
+     Error,               -- Get and clear the pending socket error
+     No_Delay,            -- Do not delay send to coalesce data (TCP_NODELAY)
+     Add_Membership,      -- Join a multicast group
+     Drop_Membership,     -- Leave a multicast group
+     Multicast_If,        -- Set default out interface for multicast packets
+     Multicast_TTL,       -- Set the time-to-live of sent multicast packets
+     Multicast_Loop,      -- Sent multicast packets are looped to local socket
+     Receive_Packet_Info, -- Receive low level packet info as ancillary data
+     Send_Timeout,        -- Set timeout value for output
+     Receive_Timeout);    -- Set timeout value for input
 
    type Option_Type (Name : Option_Name := Keep_Alive) is record
       case Name is
-         when Keep_Alive      |
-              Reuse_Address   |
-              Broadcast       |
-              Linger          |
-              No_Delay        |
-              Multicast_Loop  =>
+         when Keep_Alive          |
+              Reuse_Address       |
+              Broadcast           |
+              Linger              |
+              No_Delay            |
+              Receive_Packet_Info |
+              Multicast_Loop      =>
             Enabled : Boolean;
 
             case Name is
@@ -713,9 +745,9 @@ package GNAT.Sockets is
    --  Socket_Stream).
 
    Peek_At_Incoming_Data : constant Request_Flag_Type;
-   --  This flag causes the receive operation to return data from the
-   --  beginning of the receive queue without removing that data from the
-   --  queue. A subsequent receive call will return the same data.
+   --  This flag causes the receive operation to return data from the beginning
+   --  of the receive queue without removing that data from the queue. A
+   --  subsequent receive call will return the same data.
 
    Wait_For_A_Full_Reception : constant Request_Flag_Type;
    --  This flag requests that the operation block until the full request is
@@ -757,6 +789,20 @@ package GNAT.Sockets is
    --  is filled in with the address of the connection. Raises Socket_Error on
    --  error.
 
+   procedure Accept_Socket
+     (Server   : Socket_Type;
+      Socket   : out Socket_Type;
+      Address  : out Sock_Addr_Type;
+      Timeout  : Selector_Duration;
+      Selector : access Selector_Type := null;
+      Status   : out Selector_Status);
+   --  Accept a new connection on Server using Accept_Socket, waiting no longer
+   --  than the given timeout duration. Status is set to indicate whether the
+   --  operation completed successfully, timed out, or was aborted. If Selector
+   --  is not null, the designated selector is used to wait for the socket to
+   --  become available, else a private selector object is created by this
+   --  procedure and destroyed before it returns.
+
    procedure Bind_Socket
      (Socket  : Socket_Type;
       Address : Sock_Addr_Type);
@@ -768,16 +814,29 @@ package GNAT.Sockets is
 
    procedure Connect_Socket
      (Socket : Socket_Type;
-      Server : in out Sock_Addr_Type);
-   --  Make a connection to another socket which has the address of
-   --  Server. Raises Socket_Error on error.
+      Server : Sock_Addr_Type);
+   --  Make a connection to another socket which has the address of Server.
+   --  Raises Socket_Error on error.
+
+   procedure Connect_Socket
+     (Socket   : Socket_Type;
+      Server   : Sock_Addr_Type;
+      Timeout  : Selector_Duration;
+      Selector : access Selector_Type := null;
+      Status   : out Selector_Status);
+   --  Connect Socket to the given Server address using Connect_Socket, waiting
+   --  no longer than the given timeout duration. Status is set to indicate
+   --  whether the operation completed successfully, timed out, or was aborted.
+   --  If Selector is not null, the designated selector is used to wait for the
+   --  socket to become available, else a private selector object is created
+   --  by this procedure and destroyed before it returns.
 
    procedure Control_Socket
      (Socket  : Socket_Type;
       Request : in out Request_Type);
    --  Obtain or set parameter values that control the socket. This control
-   --  differs from the socket options in that they are not specific to
-   --  sockets but are available for any device.
+   --  differs from the socket options in that they are not specific to sockets
+   --  but are available for any device.
 
    function Get_Peer_Name (Socket : Socket_Type) return Sock_Addr_Type;
    --  Return the peer or remote socket address of a socket. Raise
@@ -785,22 +844,23 @@ package GNAT.Sockets is
 
    function Get_Socket_Name (Socket : Socket_Type) return Sock_Addr_Type;
    --  Return the local or current socket address of a socket. Return
-   --  No_Sock_Addr on error (for instance, socket closed or not locally
-   --  bound).
+   --  No_Sock_Addr on error (e.g. socket closed or not locally bound).
 
    function Get_Socket_Option
      (Socket : Socket_Type;
       Level  : Level_Type := Socket_Level;
       Name   : Option_Name) return Option_Type;
-   --  Get the options associated with a socket. Raises Socket_Error
-   --  on error.
+   --  Get the options associated with a socket. Raises Socket_Error on error
 
    procedure Listen_Socket
      (Socket : Socket_Type;
-      Length : Positive := 15);
+      Length : Natural := 15);
    --  To accept connections, a socket is first created with Create_Socket,
    --  a willingness to accept incoming connections and a queue Length for
    --  incoming connections are specified. Raise Socket_Error on error.
+   --  The queue length of 15 is an example value that should be appropriate
+   --  in usual cases. It can be adjusted according to each application's
+   --  particular requirements.
 
    procedure Receive_Socket
      (Socket : Socket_Type;
@@ -891,7 +951,8 @@ package GNAT.Sockets is
    --  Create a stream associated with a datagram-based socket that is already
    --  bound. Send_To is the socket address to which messages are being sent.
 
-   function Get_Address (Stream : Stream_Access) return Sock_Addr_Type;
+   function Get_Address
+     (Stream : not null Stream_Access) return Sock_Addr_Type;
    --  Return the socket address from which the last message was received
 
    procedure Free is new Ada.Unchecked_Deallocation
@@ -949,11 +1010,6 @@ package GNAT.Sockets is
    --  operation is typically to add a socket in one of the socket sets when
    --  the timeout is set to forever.
 
-   type Selector_Type is limited private;
-   type Selector_Access is access all Selector_Type;
-
-   subtype Selector_Duration is Timeval_Duration;
-
    procedure Create_Selector (Selector : out Selector_Type);
    --  Create a new selector
 
@@ -963,8 +1019,6 @@ package GNAT.Sockets is
    --  no other task still using Selector (i.e. still executing Check_Selector
    --  or Abort_Selector on this Selector).
 
-   type Selector_Status is (Completed, Expired, Aborted);
-
    procedure Check_Selector
      (Selector     : in out Selector_Type;
       R_Socket_Set : in out Socket_Set_Type;
@@ -999,6 +1053,16 @@ package GNAT.Sockets is
    procedure Abort_Selector (Selector : Selector_Type);
    --  Send an abort signal to the selector
 
+   type Fd_Set_Access is private;
+   No_Fd_Set_Access : constant Fd_Set_Access;
+   --  ??? This type must not be used directly, it needs to be visible because
+   --  it is used in the visible part of GNAT.Sockets.Thin_Common. This is
+   --  really an inversion of abstraction. The private part of GNAT.Sockets
+   --  needs to have visibility on this type, but since Thin_Common is a child
+   --  of Sockets, the type can't be declared there. The correct fix would
+   --  be to move the thin sockets binding outside of GNAT.Sockets altogether,
+   --  e.g. by renaming it to GNAT.Sockets_Thin.
+
 private
 
    type Socket_Type is new Integer;
@@ -1007,18 +1071,19 @@ private
    type Selector_Type is limited record
       R_Sig_Socket : Socket_Type := No_Socket;
       W_Sig_Socket : Socket_Type := No_Socket;
+      --  Signalling sockets used to abort a select operation
    end record;
 
    pragma Volatile (Selector_Type);
 
-   --  The two signalling sockets are used to abort a select operation
-
-   subtype Socket_Set_Access is System.Address;
-   No_Socket_Set : constant Socket_Set_Access := System.Null_Address;
+   type Fd_Set is null record;
+   type Fd_Set_Access is access all Fd_Set;
+   pragma Convention (C, Fd_Set_Access);
+   No_Fd_Set_Access : constant Fd_Set_Access := null;
 
    type Socket_Set_Type is record
       Last : Socket_Type       := No_Socket;
-      Set  : Socket_Set_Access := No_Socket_Set;
+      Set  : Fd_Set_Access;
    end record;
 
    subtype Inet_Addr_Comp_Type is Natural range 0 .. 255;