/*
 * socket.h - User level <socket> library definition.
 * 
 * Author     Alain Greiner (2016,2017,2018,2019,2020)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _SOCKET_H_
#define _SOCKET_H_

/***************************************************************************************** 
 * This file defines the user level <socket> library.
 * All these functions use the sys_socket() function to access the kernel structures.
 * The user/kernel shared structures and mnemonics are defined in
 * the <kernel/syscalls/shared_include/shared_socket.h> file.
 ****************************************************************************************/

#include <shared_socket.h>

/***************************************************************************************** 
 * This function creates a local socket for communication, register it in the calling
 * process and returns a socket index, that is actally a file descriptor.
 * - The <domain> argument specifies a family of protocols to be used. 
 *   The only supported type is AF_INET : IP V4.
 * - The <type> argument specifies the communication semantic.
 *   The only supported values are SOCK_DGRAM (UDP) & SOC_STREAM (TCP).
 * - The <protocol> argument is not supported, and must be zero. 
 ***************************************************************************************** 
 * @ domain    : [in] must be PF_INET.
 * @ type      : [in] must be SOCK_DGRAM / SOCK_STREAM
 * @ protocol  : [in] must be 0. 
 * @ returns a file descriptor identifier (fdid) / return -1 if error.
 ****************************************************************************************/
int socket( int domain,
            int type,
            int protocol );

/***************************************************************************************** 
 * This function assigns a socket address <local_addr> to an unnamed local socket,
 * identified by the <fdid> argument, and set the socket state to BOUND.
 ***************************************************************************************** 
 * @ fdid        : [in] socket identifier.
 * @ local_addr  : [in] local address in the communication space.
 * @ addr_length : [in] addres length in bytes.
 * @ returns 0 if success / return -1 if error.
 ****************************************************************************************/
int bind( int          fdid,
          sockaddr_t * local_addr,
          int          addr_length );

/****************************************************************************************
 * This function is executed by a TCP server on a socket identified by its <fdid>,
 * after a bind(). It specifies the willingness to accept incoming connections requests 
 * from remote clients, and a max size for the queue of pending connection requests,
 * as defined by the <backlog> argument. It sets the socket state to LISTEN. 
 * It applies only to sockets of type SOCK_STREAM (TCP).
 * It can be called by a thread running in any cluster.
 ****************************************************************************************
 * @ fdid      : [in] file descriptor identifying the socket.
 * @ backlog   : [in] max number of pending connection requests in CRQ queue.
 * @ returns 0 if success / return -1 if error.
 ***************************************************************************************/
int listen( int     fdid,
            int     backlog );

/***************************************************************************************** 
 * This function connects a local socket identified by its <fdid> to a remote socket.
 * The <remote_addr> argument defines the address to which UDP datagrams or TCP segments
 * are to be sent, and the only address from which they are to be received. 
 * - If the socket identified by the <fdid> argument is of type SOCK_DGRAM (UDP), this
 *   function simply updates the local socket descriptor using the <remote_addr> argument,
 *   and updates the socket state to CONNECT.
 * - If the socket is of type SOCK_STREAM (TCP), this function is called by a TCP client 
 *   to start the 3 steps handshake protocol with a TCP server identified by <remote_addr>.
 *   It returns only when the connexion is established, and the local socket state
 *   is set to ESTAB.
 ***************************************************************************************** 
 * @ fdid        : [in] file descriptor identifying the socket.
 * @ remote_addr : [in] remote address in the communication space.
 * @ addr_len    : [in] address length in bytes.
 * @ returns 0 if success / return -1 if error.
 ****************************************************************************************/
int connect( int          fdid,
             sockaddr_t * remote_addr,
             int          addr_length );

/***************************************************************************************** 
 * This function is executed by a TCP server on a socket identified by its <fdid>,
 * after bind() and listen().
 * It extracts the first connection request from the queue of pending connections, 
 * creates a new socket with the same properties as <socket>, and allocates a new file
 * descriptor for the new socket.  If no pending connections are present on the queue,
 * it blocks the call ,er until a connection is present. The new socket cannot accept more
 * connections, but the original socket remains open. It returns in the <client_addr>
 * argument the client address. The inout argument <addr_length> contains initially
 * te size of the <client_addr> buffer, and returns the actual length of the address.
 ***************************************************************************************** 
 * @ fdid         : [in] file descriptor identifying the socket.
 * @ remote_addr  : [in] remote client address in the communication space.
 * @ addr_len     : [inout] address length in bytes.
 * @ returns 0 if success / return -1 if error.
 ****************************************************************************************/
int accept( int          fdid,
            sockaddr_t * remote_addr,
            int        * addr_length );

/***************************************************************************************** 
 * This function send data from a local socket identified by the <fdid> argument,
 * to a remote socket. The payload is defined by the <buffer> and <size> arguments.
 * The local socket must be in "connected" state, as the remote socket is identified
 * by the remote_address and remote_port registered in the local socket.
 * If the packet is too long to pass atomically through the underlying protocols,
 * an error is returned, and the message is not transmitted.
 * This blocking function returns only when all data have been sent (for an UDP socket),
 * or acknowledged (for a TCP socket).
 ***************************************************************************************** 
 * @ fdid      : [in] file descriptor identifying the socket.
 * @ buffer    : [in] local pointer on source buffer.
 * @ length    : [in] number of bytes in source buffer.
 * @ flags     : unused / must be 0.
 * @ returns number of bytes sent if success / return -1 if error.
 ****************************************************************************************/
int send( int          fdid,
          void       * buffer,
          int          length,
          int          flags );

/***************************************************************************************** 
 * This function get data from a local socket identified by the <fdid> index,
 * wether or not it is connected, and stores this data in the buffer identified by the
 * <buffer> argument. The buffer size is defined by the <length> argument.
 * This non blocking function returns as soon as data is available, returning the number
 * of bytes actually moved to <buffer>.
 ***************************************************************************************** 
 * @ fdid      : [in] file descriptor identifying the socket.
 * @ buffer    : [in] local pointer on destination buffer.
 * @ length    : [in] number of bytes in destination buffer.
 * @ flags     : unused / must be 0
 * @ returns number of bytes received if success / return -1 if error.
 ****************************************************************************************/
int recv( int          fdid,
          void       * buffer,
          int          length,
          int          flags );

/***************************************************************************************** 
 * This function send a packet from a local socket identified by the <fdid> argument,
 * to a remote socket. The payload is defined by the <buffer> and <size> arguments.
 * The remote socket is identified by the <server_addr> and <addr_length> arguments.
 * If the packet is too long to pass atomically through the underlying protocols,
 * an error is returned, and the message is not transmitted.
 * This blocking function returns only when all data have been sent (for an UDP socket),
 * or acknowledged (for a TCP socket).
 ***************************************************************************************** 
 * @ fdid        : [in] file descriptor identifying the socket.
 * @ buffer      : [in] local pointer on source buffer.
 * @ length      : [in] number of bytes in source buffer.
 * @ flags       : unused / must be 0.
 * @ remote_addr : [in] remote socket address in communication space.
 * @ addr_length : [in] size of buffer containing this remote address. 
 * @ returns number of bytes sent if success / return -1 if error.
 ****************************************************************************************/
int sendto( int          socket,
            void       * buffer,
            int          length,
            int          flags,
            sockaddr_t * remote_addr,
            int          addr_length );

/***************************************************************************************** 
 * This function get data from a local socket identified by the <fdid> argument,
 * wether or not it is connected, and stores this data in the buffer identified by the
 * <buffer> argument. The buffer size is defined by the <length> argument.
 * This non blocking function returns as soon as data is available, returning the number
 * of bytes actually moved to <buffer>.
 * If the <remote_addr> argument is not NULL, and the local socket is not connected,
 * the remote socket address is stored in the <remote_addr> buffer.
 * The <addr_length> buffer is an in/out argument, that contains initially the size
 * of the <remote_addr> buffer and returns the actual remote address length.
 ***************************************************************************************** 
 * @ socket      : [in] local socket identifier.
 * @ buffer      : [in] local pointer on destination buffer.
 * @ length      : [in] number of bytes in destination buffer.
 * @ flags       : unused / must be 0.
 * @ remote_addr : [out] buffer for remote socket address.
 * @ addr_length : [in/out] size of this remote address buffer. 
 * @ returns number of bytes received if success / return -1 if error.
 ****************************************************************************************/
int recvfrom( int          socket,
              void       * buffer,
              int          length,
              int          flags,
              sockaddr_t * remote_addr,
              int        * addr_length );

#endif  // _SOCKET_H_

