/**
 * @file
 * @brief Support socket routines
 * @copyright (C) 2012-2019, Samsung Electronics Co., Ltd.
 * @addtogroup socket
 * @{
 */

#ifndef _TZSL_SYS_SOCKET_H_
#define _TZSL_SYS_SOCKET_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <compiler.h>
#include <core/socket.h>
#include <stdint.h>
#include <sys/types.h>

/** @brief A type of width of at least 32 bits representing lengths in socket subsystem. */
typedef int32_t socklen_t;

/**
 * @brief Accept a connection on a socket
 * @param[in] sockfd listening socket descriptor
 * @param[in] addr pointer to a sockaddr structure
 * @param[inout] addrlen size of structure pointed to by addr
 * @return nonnegative file descriptor for the accepted socket on success
 * @return -1 with errno on error
 */
int __must_check accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

/**
 * @brief Bind a name to a socket
 * @param[in] sockfd socket descriptor
 * @param[in] addr address to the socket
 * @param[in] addrlen size of the address structure
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check __attribute__((weak)) bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

/**
 * @brief Initiate a connection on a socket
 * @param[in] sockfd socket descriptor
 * @param[in] addr address to the socket
 * @param[in] addrlen size of the address structure
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

/**
 * @brief Get options on socket
 * @param[in] sockfd socket descriptor
 * @param[in] level socket API level
 * @param[in] optname specified options
 * @param[inout] optval buffer in which the value
 * of the requested options are to be returned
 * @param[inout] optlen the size of the buffer pointed to by optval
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

/**
 * @brief Set options on socket
 * @param[in] sockfd socket descriptor
 * @param[in] level socket API level
 * @param[in] optname specified options
 * @param[in] optval buffer in which the new value
 * of the requested options is stored
 * @param[in] optlen the size of the buffer pointed to by optval
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

/**
 * @brief Listen for connections on a socket
 * @param[in] sockfd socket descriptor
 * @param[in] backlog maximum length to which the queue of pending connections
 * for sockfd may grow
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check listen(int sockfd, int backlog);

/**
 * @brief Create endpoint for communication
 * @param[in] socket_family communication domain
 * @param[in] socket_type communication semantics specifier
 * @param[in] protocol particular protocol to be used with the socket
 * @return nonnegative file descriptor for the new socket on success
 * @return -1 with errno on error
 */
int __must_check socket(int socket_family, int socket_type, int protocol);

/**
 * @brief Receive a message from a socket
 * @param[in] sockfd socket descriptor
 * @param[in] buf pointer to a message buffer
 * @param[in] len message length
 * @param[in] flags type of receiving
 * @return number of bytes received on success
 * @return -1 with errno on error
 */
ssize_t __must_check recv(int sockfd, void *buf, size_t len, int flags);

/**
 * @brief Send a message to a socket
 * @param[in] sockfd socket descriptor
 * @param[inout] buf pointer to a message buffer
 * @param[in] len message length
 * @param[in] flags type of sending
 * @return number of bytes sent on success
 * @return -1 with errno on error
 */
ssize_t __must_check send(int sockfd, const void *buf, size_t len, int flags);

/**
 * @brief Create a pair of connected sockets
 * @param[in] socket_family communication domain
 * @param[in] socket_type communication semantics specifier
 * @param[in] protocol particular protocol to be used with the socket
 * @param[in] sv file descriptors
 * @return 0 on success
 * @return -1 with errno on error
 */
int __must_check socketpair(int socket_family, int socket_type, int protocol, int sv[2]);

/**
 * @brief Receive multipple message on a socket
 * @param[in] sockfd socket descriptor
 * @param[in] msg pointer to an array of msghdr structures
 * @param[in] flags type of receiving
 * @return number of messages received in msg on success
 * @return -1 with errno on error
 */
ssize_t __must_check recvmsg(int sockfd, struct msghdr *msg, int flags);

/**
 * @brief Send multipple message on a socket
 * @param[in] sockfd socket descriptor
 * @param[out] msg pointer to an array of msghdr structures
 * @param[in] flags type of sending
 * @return number of messages sent from msg on success
 * @return -1 with errno on error
 */
ssize_t __must_check sendmsg(int sockfd, struct msghdr *msg, int flags);

#ifdef __cplusplus
}
#endif

#endif /* _TZSL_SYS_SOCKET_H_ */
/** @}*/
