/*=* Global settings.
 *
 * package: Sockets
 * intro:
 *    The @code{Sockets} package contains all the definitions and
 *    subprograms needed to build a simple unicast client or server.
=*/

/*=type Socket_FD
 *
 * what: Socket object
 * def: tagged private
 * doc:
 *    The @code{Socket_FD} tagged type is the root type of all
 *    sockets. It gets initialized by calling @ref{Socket (procedure)}.
 *    An uninitialized @code{Socket_FD} can be succesfully compared to
 *    @code{Null_Socket_FD}.
=*/

/*=subprogram Socket
 *
 * what: Create a socket of the given mode
 * kind: procedure
 * arg: Socket, out, Socket_FD,, Socket object to initialize
 * arg: Domain, in, Socket_Domain, PF_INET, Protocol family
 * arg: Typ, in, Socket_Type, SOCK_STREAM, Kind of sockets
 * doc:
 * @ctindex PF_INET
 * @ctindex AF_INET
 * @ctindex SOCK_STREAM
 * @ctindex SOCK_DGRAM
 *   This procedure initializes a new socket object by reserving a file
 *   descriptor to the operating system. For backward compatibility with
 *   older versions of this library, @code{AF_INET} is still accepted as
 *   a value but should be replaced as soon as possible with the proper
 *   @code{PF_INET}. Using @code{SOCK_STREAM} for the @var{Typ}
 *   argument will create a TCP socket while a @code{SOCK_DGRAM} will
 *   create a UDP one.
 * concept: Creating a socket
 * example:
 * $ declare
 * $    Sock : Socket_FD;
 * $ begin
 * $    -- Create a TCP socket
 * $    Socket (Sock, PF_INET, SOCK_STREAM);
 * $    -- Perform some operations on socket
 * $    [...]
 * $    -- Shutdown the socket in both directions
 * $    Shutdown (Sock, Both);
 * $ end;
 * see: Shutdown (procedure)
=*/

/*=subprogram Connect
 *
 * what: Connect a socket on a given host/port
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized socket object
 * arg: Host, in, String,, Host to connect to
 * arg: Port, in, Positive,, Port to connect to
 * exc: Connection_Refused, The connection has been refused by the server
 * exc: Socket_Error, Another error occurred during the connection
 * doc:
 *   This procedure connects an initialized socket to a given host on
 *   a given port. In the case of a TCP socket, a real connection is
 *   attempted. In the case of a UDP socket, no connection takes place
 *   but the endpoint coordinates are recorded.
 * concept: Connecting a socket
 * example:
 * $ declare
 * $    Sock : Socket_FD;
 * $ begin
 * $    -- Create a TCP socket
 * $    Socket (Sock, PF_INET, SOCK_STREAM);
 * $    -- Connect it to rfc1149.net's mail server
 * $    Connect (Sock, "mail.rfc1149.net", 25);
 * $    -- Do a mail transaction then close the socket
 * $    [...]
 * $ end;
 * see: Socket (procedure)
=*/

/*=subprogram Bind
 *
 * what: Associate a local port to a socket
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized socket object
 * arg: Port, in, Natural,, Local port to bind to
 * arg: Host, in, String, @w{}"", Local interface to bind to
 * exc: Socket_Error, Requested port or interface not available
 * doc:
 *    This procedure requests a local port from the operating
 *    system. If 0 is given in @var{Port}, the system will assign a
 *    free port whose number can later be retrieved using
 *    @ref{Get_Sock_Port (function)}. Also, most operating systems require
 *    special privileges if you want to bind to ports below 1024.
 *
 *    If @var{Host} is not the empty string, it must contain the
 *    IP address of a local interface to bind to, or a name which
 *    resolves into such an address. If an empty string is given (the
 *    default), the socket will be bound to all the available
 *    interfaces.
 * concept: Binding a socket
 * concept: Assigning a local port
 * concept: Creating a server
 * see: Listen (procedure)
 * see: Socket (procedure)
=*/

/*=subprogram Listen
 *
 * what: Establish a listen queue
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized and bound socket object
 * arg: Queue_Size, in, Positive, 5, Requested slots in the listen queue
 * doc:
 *    This procedure establishes a listen queue after a TCP socket as been
 *    initialized and bound. Each slot in the queue can hold one
 *    incoming connection that has not been accepted yet. Note that
 *    most operating systems ignore queue sizes larger than five.
 * concept: Establishing a listen queue
 * concept: Listen queue
 * see: Accept_Socket (procedure)
 * see: Bind (procedure)
 * see: Socket (procedure)
=*/

/*=subprogram Getsockopt
 *
 * what: Retrieve a socket option
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized and bound socket object
 * arg: Level, in, Socket_Level, SOL_SOCKET, Protocol level
 * arg: Optname, in, Socket_Option,, Option name
 * arg: Optval, out, Integer,, Option value
 * doc:
 * @ctindex Sockets.SOL_SOCKET
 * @ctindex Sockets.IPPROTO_IP
 * @ctindex Sockets.SO_REUSEADDR
 * @ctindex Sockets.SO_REUSEPORT
 * @ctindex Sockets.IP_MULTICAST_TTL
 * @ctindex Sockets.IP_ADD_MEMBERSHIP
 * @ctindex Sockets.IP_DROP_MEMBERSHIP
 * @ctindex Sockets.IP_MULTICAST_LOOP
 * @ctindex Sockets.SO_SNDBUF
 * @ctindex Sockets.SO_RCVBUF
 * @ctindex SOL_SOCKET
 * @ctindex IPPROTO_IP
 * @ctindex SO_REUSEADDR
 * @ctindex SO_REUSEPORT
 * @ctindex IP_MULTICAST_TTL
 * @ctindex IP_ADD_MEMBERSHIP
 * @ctindex IP_DROP_MEMBERSHIP
 * @ctindex IP_MULTICAST_LOOP
 * @ctindex SO_SNDBUF
 * @ctindex SO_RCVBUF
 *    This procedure retrieves options applicable to a socket. Please
 *    see your operating system manual for usable levels and options.
 *
 *    Two levels are defined: @code{SOL_SOCKET} (the default) and
 *    @code{IPPROTO_IP}. The options are @code{SO_REUSEADDR},
 *    @code{SO_REUSEPORT}, @code{IP_MULTICAST_TTL},
 *    @code{IP_ADD_MEMBERSHIP}, @code{IP_DROP_MEMBERSHIP},
 *    @code{IP_MULTICAST_LOOP}, @code{SO_SNDBUF} and
 *    @code{IP_RCVBUF}.
 *
 *    Note that unlike their C language counterpart, @code{Getsockopt}
 *    and @code{Setsockopt} do not require an extra parameter
 *    representing the length in bytes of the option value. AdaSockets
 *    nows the right size for every option.
 * concept: Manipulating socket options
 * concept: Retrieving socket options
 * see: Setsockopt (procedure)
=*/

/*=subprogram Setsockopt
 *
 * what: Set a socket option
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized and bound socket object
 * arg: Level, in, Socket_Level, SOL_SOCKET, Protocol level
 * arg: Optname, in, Socket_Option,, Option name
 * arg: Optval, in, Integer,, Option value
 * doc:
 * @ctindex Sockets.SOL_SOCKET
 * @ctindex Sockets.IPPROTO_IP
 * @ctindex Sockets.SO_REUSEADDR
 * @ctindex Sockets.SO_REUSEPORT
 * @ctindex Sockets.IP_MULTICAST_TTL
 * @ctindex Sockets.IP_ADD_MEMBERSHIP
 * @ctindex Sockets.IP_DROP_MEMBERSHIP
 * @ctindex Sockets.IP_MULTICAST_LOOP
 * @ctindex Sockets.SO_SNDBUF
 * @ctindex Sockets.SO_RCVBUF
 * @ctindex SOL_SOCKET
 * @ctindex IPPROTO_IP
 * @ctindex SO_REUSEADDR
 * @ctindex SO_REUSEPORT
 * @ctindex IP_MULTICAST_TTL
 * @ctindex IP_ADD_MEMBERSHIP
 * @ctindex IP_DROP_MEMBERSHIP
 * @ctindex IP_MULTICAST_LOOP
 * @ctindex SO_SNDBUF
 * @ctindex SO_RCVBUF
 *    This procedure sets options applicable to a socket. Please
 *    see your operating system manual for usable levels and options.
 *
 *    Two levels are defined: @code{SOL_SOCKET} (the default) and
 *    @code{IPPROTO_IP}. The options are @code{SO_REUSEADDR},
 *    @code{SO_REUSEPORT}, @code{IP_MULTICAST_TTL},
 *    @code{IP_ADD_MEMBERSHIP}, @code{IP_DROP_MEMBERSHIP},
 *    @code{IP_MULTICAST_LOOP}, @code{SO_SNDBUF} and
 *    @code{IP_RCVBUF}.
 *
 *    Note that unlike their C language counterpart, @code{Getsockopt}
 *    and @code{Setsockopt} do not require an extra parameter
 *    representing the length in bytes of the option value. AdaSockets
 *    nows the right size for every option.
 * concept: Manipulating socket options
 * concept: Setting socket options
 * see: Getsockopt (procedure)
=*/

/*=subprogram Accept_Socket
 *
 * what: Accept an incoming connection
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized, bound and listening socket object
 * arg: New_Socket, out, Socket_FD,, Incoming socket object
 * doc:
 *    This procedure creates a new socket corresponding to an incoming
 *    connection on TCP socket @var{Socket}. All the communications
 *    with the peer will take place on @var{New_Socket}, while the
 *    program can accept another connection on @var{Socket}.
 *
 *    @var{New_Socket} must not be initialized before calling this
 *    procedure, or must have been cleaned up by calling
 *    @code{Shutdown}, in order to avoid a file descriptors leak.
 *
 *    @code{Accept_Socket} will block until an incoming connection is
 *    ready to be accepted.
 * concept: Accepting a new connection
 * concept: Handling a new connection
 * example:
 * $ declare
 * $    Sock     : Socket_FD;
 * $    Incoming : Socket_FD;
 * $ begin
 * $    -- Create a TCP socket listening on local port 4161
 * $    Socket (Sock, PF_INET, SOCK_STREAM);
 * $    Bind (Sock, 4161);
 * $    Listen (Sock, 3);
 * $    -- One-connection-at-a-time server (3 may be pending)
 * $    loop
 * $       -- Wait for a new connection and accept it
 * $       Accept_Socket (Sock, Incoming);
 * $       -- Do some dialog with the remote host
 * $       Do_Some_Dialog (Incoming);
 * $       -- Close incoming socket and wait for next connection
 * $       Shutdown (Incoming);
 * $    end loop;
 * $ end;
 * see: Bind (procedure)
 * see: Listen (procedure)
 * see: Shutdown (procedure)
 * see: Socket (procedure)
=*/

/*=subprogram Send
 *
 * what: Send raw data over a socket
 * kind: procedure
 * arg: Socket, in, Socket_FD,, Initialized and connected socket object
 * arg: Data, out, Ada.Streams.Stream_Element_Array,, Data to be sent
 * doc:
 * @tindex Ada.Streams.Stream_Element_Array
 * @tindex Stream_Element_Array
 *    This procedure sends data over a connected outgoing socket or
 *    over an incoming socket.
 * concept: Sending data
 * exc: Connection_Closed, Peer has prematurely closed the connection
 * see: Put (procedure)
 * see: Put_Line (procedure)
=*/

/*=subprogram Receive
 *
 * what: Receive raw data over a socket
 * kind: function
 * arg:
 *    Socket, in, Socket_FD,, Initialized and bound or connected socket object
 * arg: Max, in, Ada.Streams.Stream_Element_Count, 4096, Maximum data length
 * ret: Ada.Streams.Stream_Element_Array, Received raw data
 * doc:
 * @tindex Ada.Streams.Stream_Element_Count
 * @tindex Ada.Streams.Stream_Element_Array
 * @tindex Stream_Element_Count
 * @tindex Stream_Element_Array
 *    This procedure receives data from a bound UDP socket or a connected
 *    TCP socket. Only one system call will be performed; this
 *    function will return whatever data has arrived. Note that in
 *    GNAT the secondary stack may be used to store  the data and may
 *    result in stack storage exhaustion. 
 * concept: Receiving data
 * exc:
 *   Connection_Closed, Peer has closed the connection before sending any data
 * see: Receive (procedure)
 * see: Receive_Some (procedure)
 * see: Get_Line (function)
 * see: Get_Line (procedure)
=*/

/*=subprogram Receive
 *
 * what: Receive raw data over a socket
 * kind: procedure
 * arg:
 *    Socket, in, Socket_FD'Class,,
 *    Initialized and bound or connected socket object
 * arg: Data, out, Ada.Streams.Stream_Element_Array,, Incoming data buffer
 * doc:
 * @tindex Ada.Streams.Stream_Element_Array
 * @tindex Stream_Element_Array
 *    This procedure receives data from a bound UDP socket or a connected
 *    TCP socket. It will block until the @var{Data} reception buffer
 *    has been totally filled.
 * concept: Receiving data
 * exc:
 *   Connection_Closed,
 *   Peer has closed the connection before @code{Data'Length} bytes@*
 *   were received
 * see: Get_Line (function)
 * see: Get_Line (procedure)
 * see: Receive (function)
 * see: Receive_Some (procedure)
=*/

/*=subprogram Receive_Some
 *
 * what: Receive raw data over a socket
 * kind: procedure
 * arg:
 *    Socket, in, Socket_FD'Class,,
 *    Initialized and bound or connected socket object
 * arg: Data, out, Ada.Streams.Stream_Element_Array,, Incoming data buffer
 * arg:
 *   Last, out, Ada.Streams.Stream_Element_Offset,,
 *   Index of last element placed into @var{Data}
 * doc:
 * @tindex Ada.Streams.Stream_Element_Array
 * @tindex Stream_Element_Array
 * @tindex Ada.Streams.Stream_Element_Count
 * @tindex Stream_Element_Count
 *    This procedure receives data from a bound UDP socket or a connected
 *    TCP socket. As soon as at least one byte has been read, it returns
 *    with @var{Last} set to the index of the latest written element
 *    of @var{Data}.
 * concept: Receiving data
 * exc:
 *   Connection_Closed,
 *   Peer has closed the connection before sending any data
 * see: Get_Line (function)
 * see: Get_Line (procedure)
 * see: Receive (function)
 * see: Receive (procedure)
=*/

/*=subprogram Shutdown
 *
 * what: Shutdown a socket
 * kind: procedure
 * arg: Socket, in out, Socket_FD,, Socket object to shutdown
 * arg: How, in, Shutdown_Type, Both, Direction to shutdown
 * doc:
 * @ctindex Send
 * @ctindex Receive
 * @ctindex Both
 *   This procedure shutdowns either direction of the socket. @var{How}
 *   can take the value @samp{Send}, @samp{Receive} or @samp{Both}.
 * concept: Closing a socket
 * concept: Socket shutdown
 * see: Socket (procedure)
=*/

/*=subprogram Put
 *
 * what: Send a string to a remote host
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Str, in, String,, String to send
 * doc:
 *    This procedure sends the content of @var{Str} over an outgoing
 *    or incoming socket.
 * concept: Sending data
 * exc: Connection_Closed, Peer has prematurely closed the connection
 * see: New_Line (procedure)
 * see: Put_Line (procedure)
 * see: Send (procedure)
=*/

/*=subprogram New_Line
 *
 * what: Send a CR/LF to a remote host
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Count, in, Natural, 1, Number of CR/LF sequences to send
 * doc:
 * @ctindex CR
 * @ctindex LF
 *    This procedure sends one or more CR/LF combinations to the peer.
 * concept: Sending data
 * exc: Connection_Closed, Peer has prematurely closed the connection
 * see: Put (procedure)
 * see: Put_Line (procedure)
=*/

/*=subprogram Put_Line
 *
 * what: Send a CR/LF terminated string to a remote host
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Str, in, String,, String to send
 * doc:
 *    This procedure sends the content of @var{Str} plus a CR/LF combination
 *    over an outgoing or incoming socket.
 * concept: Sending data
 * exc: Connection_Closed, Peer has prematurely closed the connection
 * see: New_Line (procedure)
 * see: Put (procedure)
 * see: Send (procedure)
=*/

/*=subprogram Get
 *
 * what: Get a string from a remote host
 * kind: function
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * ret: String, Some characters that have been received
 * doc:
 *    This function receives some characters from a remote host.
 *    As soon that at least one character is available, the current
 *    reception buffer is returned.
 *
 *    There is usually little gain in using this function whose behaviour is
 *    comparable to the one of @ref{Receive (function)}. Other
 *    functions such as @ref{Get_Char (function)}, or
 *    @ref{Get_Line (function)}, allow more structured programming.
 *
 *    However, this function may be used to avoid loosing characters
 *    when calling @ref{Unset_Buffer (procedure)}, if, for some reason,
 *    the remote host may have sent some.
 * concept: Receiving data
 * exc:
 *    Connection_Closed,
 *    Peer has closed the connection before sending any data
=*/

/*=subprogram Get_Char
 *
 * what: Get a character from a remote host
 * kind: function
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * ret: Character, One character sent by the remote host
 * doc:
 *    This function receives exactly one character from the remote host.
 * concept: Receiving data
 * exc:
 *    Connection_Closed,
 *    Peer has closed the connection before sending the character
 * see: Get (function)
 * see: Get_Line (function)
 * see: Get_Line (procedure)
 * see: Receive (procedure)
 * see: Set_Buffer (procedure)
=*/

/*=subprogram Get_Line
 *
 * what: Get a whole line from a remote host
 * kind: function
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Max_Length, in, Positive, 2048, Maximum returned line length
 * ret: String, A line without the CR and LF separators
 * doc:
 * @ctindex CR
 * @ctindex LF
 *    This function receives one line from the remote host. A line
 *    consists into zero or more characters followed by an optional CR
 *    and by a LF. Those terminators are stripped before the line is
 *    returned.
 *
 *    This function blocks until one full line has been received. The line
 *    length is limited with the value of the Max_Length argument, to avoid
 *    exhaustion of the secondary stack.
 * concept: Receiving data
 * exc:
 *    Connection_Closed,
 *    Peer has closed the connection before sending a whole line
 * see: Get (function)
 * see: Get_Char (function)
 * see: Get_Line (procedure)
 * see: Receive (procedure)
 * see: Set_Buffer (procedure)
=*/

/*=subprogram Get_Line
 *
 * what: Get a whole line from a remote host
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Str, in out, String,, String to fill
 * arg: Last, out, Natural,, Last index used in the string
 * doc:
 * @ctindex CR
 * @ctindex LF
 *    This procedure receives one line from the remote host. A line
 *    consists into zero or more characters followed by an optional CR
 *    and by a LF. Those terminators are stripped before the line is
 *    returned.
 *
 *    This procedure blocks until one full line has been received.
 * concept: Receiving data
 * exc:
 *    Connection_Closed,
 *    Peer has closed the connection before sending a whole line
 * see: Get (function)
 * see: Get_Char (function)
 * see: Get_Line (function)
 * see: Receive (procedure)
 * see: Set_Buffer (procedure)
=*/

/*=subprogram Set_Buffer
 *
 * what: Install a line-oriented buffer of the socket object
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * arg: Length, in, Positive, 1500, Size in bytes of the newly installed buffer
 * doc:
 *    This procedure puts the socket object in buffered mode. If the
 *    socket was already buffered, the content of the previous buffer
 *    will be lost. The buffered mode only affects character- and
 *    line-oriented read operation such as @ref{Get (function)},
 *    @ref{Get_Char (function)}, and @ref{Get_Line (function)}. Other
 *    reception subprograms will not function properly if buffered mode
 *    is used at the same time.
 *
 *    The size of the buffer has to be greater than the biggest
 *    possible packet sent by the remote host, otherwise data loss may
 *    occur.
 * concept: Receiving data
 * see: Unset_Buffer (procedure)
=*/

/*=subprogram Unset_Buffer
 *
 * what: Deinstall the line-oriented buffer of the socket object
 * kind: procedure
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * doc:
 *    This procedure deinstalls the buffer previously installed by
 *    @ref{Set_Buffer (procedure)}. If any data is still present in
 *    the buffer, it will be lost. To avoid this situation, the buffer
 *    can be flushed by calling @ref{Get (function)}.
 * concept: Receiving data
=*/

/*=subprogram Get_Send_Queue_Size
 *
 * what: Return the size of the unsent data in the output queue
 * kind: function
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * ret: Integer, The non-negative size in bytes of the output queue, or a negative value in case of error
 * doc:
 *    This function is only available on Linux platforms. On other operating
 *    systems, it will return -2 to indicate that the necessary mechanisms to
 *    retrieve the information are not available.
 * concept: Sending data
 * see: Send (procedure)
=*/

/*=subprogram Get_Receive_Queue_Size
 *
 * what: Return the size of the unread data in the input queue
 * kind: function
 * arg: Socket, in, Socket_FD'Class,, Initialized and connected socket object
 * ret: Integer, The non-negative size in bytes of the input queue, or a negative value in case of error
 * doc:
 *    This function is only available on Linux platforms. On other operating
 *    systems, it will return -2 to indicate that the necessary mechanisms to
 *    retrieve the information are not available.
 * concept: Receiving data
 * see: Receive (procedure)
=*/
