/** * Copyright (C) Mellanox Technologies Ltd. 2019. ALL RIGHTS RESERVED. * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. * * See file LICENSE for terms. */ #ifndef UCS_SOCKET_H #define UCS_SOCKET_H #include #include #include #include #include #include #include BEGIN_C_DECLS /* A string to hold the IP address and port from a sockaddr */ #define UCS_SOCKADDR_STRING_LEN 60 #define UCS_SOCKET_INET_ADDR(_addr) (((struct sockaddr_in*)(_addr))->sin_addr) #define UCS_SOCKET_INET_PORT(_addr) (((struct sockaddr_in*)(_addr))->sin_port) #define UCS_SOCKET_INET6_ADDR(_addr) (((struct sockaddr_in6*)(_addr))->sin6_addr) #define UCS_SOCKET_INET6_PORT(_addr) (((struct sockaddr_in6*)(_addr))->sin6_port) /* Returns an error if the default error handling should be * done (the error value will be returned to a caller), * otherwise `UCS_OK` */ typedef ucs_status_t (*ucs_socket_io_err_cb_t)(void *arg, int io_errno); /** * Check if the given (interface) flags represent an active interface. * * @param [in] flags Interface flags (Can be obtained using getifaddrs * or from SIOCGIFFLAGS ioctl). * * @return 1 if true, otherwise 0 */ int ucs_netif_flags_is_active(unsigned int flags); /** * Perform an ioctl call on the given interface with the given request. * Set the result in the ifreq struct. * * @param [in] if_name Interface name to test. * @param [in] request The request to fulfill. * @param [out] if_req Filled with the requested information. * * @return UCS_OK on success or an error code on failure. */ ucs_status_t ucs_netif_ioctl(const char *if_name, unsigned long request, struct ifreq *if_req); /** * Check if the given interface is in an active state. * * @param [in] if_name Interface name to check. * * @return 1 if true, otherwise 0 */ int ucs_netif_is_active(const char *if_name); /** * Create a socket. * * @param [in] domain Communication domain (AF_INET/AF_INET6/etc). * @param [in] type Communication semantics (SOCK_STREAM/SOCK_DGRAM/etc). * @param [out] fd_p Pointer to created fd. * * @return UCS_OK on success or UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_create(int domain, int type, int *fd_p); /** * Set options on socket. * * @param [in] fd Socket fd. * @param [in] level The level at which the option is defined. * @param [in] optname The socket option for which the value is to be set. * @param [in] optval A pointer to the buffer in which the value for the * requested option is specified. * @param [in] optlen The size, in bytes, of the buffer pointed to by the * optval and def_optval parameters. * * @return UCS_OK on success or UCS_ERR_IO_ERROR on failure */ ucs_status_t ucs_socket_setopt(int fd, int level, int optname, const void *optval, socklen_t optlen); /** * Connect the socket referred to by the file descriptor `fd` * to the address specified by `dest_addr`. * * @param [in] fd Socket fd. * @param [in] dest_addr Pointer to destination address. * * @return UCS_OK on success or UCS_ERR_UNREACHABLE on failure or * UCS_INPROGRESS if operation is in progress. */ ucs_status_t ucs_socket_connect(int fd, const struct sockaddr *dest_addr); /** * Accept a connection request on the given socket fd. * * @param [in] fd Socket fd. * @param [out] addr Client socket address that initiated the connection * @param [out] length_ptr Client address socket's length * @param [out] accept_fd Upon success, a non-negative file descriptor * of the accepted socket. Otherwise, -1. * * @return UCS_OK on success or UCS_ERR_NO_PROGRESS to indicate that no progress * was made or UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_accept(int fd, struct sockaddr *addr, socklen_t *length_ptr, int *accept_fd); /** * Get the address of the peer's socket that the given fd is connected to * * @param [in] fd Socket fd. * @param [out] peer_addr Address of the remote peer. * @param [out] peer_addr_len Length of the remote peer's address. * * @return UCS_OK on success or UCS_ERR_IO_ERROR on failure */ ucs_status_t ucs_socket_getpeername(int fd, struct sockaddr_storage *peer_addr, socklen_t *peer_addr_len); /** * Check whether the socket referred to by the file descriptor `fd` * is connected to a peer or not. * * @param [in] fd Socket fd. * * @return 1 - connected, 0 - not connected. */ int ucs_socket_is_connected(int fd); /** * Initialize a TCP server. * Open a socket, bind a sockadrr to that socket and start listening on it for * incoming connection requests. * * @param [in] saddr Sockaddr for the server to listen on. * If the port number inside is set to zero - * use a random port. * @param [in] socklen Size of saddr. * @param [in] backlog Length of the queue for pending connections - * for the listen() call. * @param [out] listen_fd The fd that belongs to the server. * * @return UCS_OK on success or an error code on failure. */ ucs_status_t ucs_socket_server_init(const struct sockaddr *saddr, socklen_t socklen, int backlog, int *listen_fd); /** * Returns the maximum possible value for the number of sockets that * are ready to be accepted. It maybe either value from the system path * or SOMAXCONN value. * * @return The queue length for completely established sockets * waiting to be accepted. */ int ucs_socket_max_conn(); /** * Non-blocking send operation sends data on the connected (or bound * connectionless) socket referred to by the file descriptor `fd`. * * @param [in] fd Socket fd. * @param [in] data A pointer to a buffer containing the data to * be transmitted. * @param [in/out] length_p The length, in bytes, of the data in buffer * pointed to by the `data` parameter. The amount of * data transmitted is written to this argument. * @param [in] err_cb Error callback. * @param [in] err_cb_arg User's argument for the error callback. * * @return UCS_OK on success, UCS_ERR_CANCELED if connection closed, * UCS_ERR_NO_PROGRESS if system call was interrupted or * would block, UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_send_nb(int fd, const void *data, size_t *length_p, ucs_socket_io_err_cb_t err_cb, void *err_cb_arg); /** * Non-blocking receive operation receives data from the connected (or bound * connectionless) socket referred to by the file descriptor `fd`. * * @param [in] fd Socket fd. * @param [in] data A pointer to a buffer to receive the incoming * data. * @param [in/out] length_p The length, in bytes, of the data in buffer * pointed to by the `data` parameter. The amount of * data received is written to this argument. * @param [in] err_cb Error callback. * @param [in] err_cb_arg User's argument for the error callback. * * @return UCS_OK on success, UCS_ERR_CANCELED if connection closed, * UCS_ERR_NO_PROGRESS if system call was interrupted or * would block, UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_recv_nb(int fd, void *data, size_t *length_p, ucs_socket_io_err_cb_t err_cb, void *err_cb_arg); /** * Blocking send operation sends data on the connected (or bound connectionless) * socket referred to by the file descriptor `fd`. * * @param [in] fd Socket fd. * @param [in] data A pointer to a buffer containing the data to * be transmitted. * @param [in/out] length The length, in bytes, of the data in buffer * pointed to by the `data` parameter. * @param [in] err_cb Error callback. * @param [in] err_cb_arg User's argument for the error callback. * * @return UCS_OK on success, UCS_ERR_CANCELED if connection closed, * UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_send(int fd, const void *data, size_t length, ucs_socket_io_err_cb_t err_cb, void *err_cb_arg); /** * Non-blocking send operation sends I/O vector on the connected (or bound * connectionless) socket referred to by the file descriptor `fd`. * * @param [in] fd Socket fd. * @param [in] iov A pointer to an array of iovec buffers. * @param [in] iov_cnt The number of buffers pointed to by * the iov parameter. * @param [out] length_p The amount of data transmitted is written to * this argument. * @param [in] err_cb Error callback. * @param [in] err_cb_arg User's argument for the error callback. * * @return UCS_OK on success, UCS_ERR_CANCELED if connection closed, * UCS_ERR_NO_PROGRESS if system call was interrupted or * would block, UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_sendv_nb(int fd, struct iovec *iov, size_t iov_cnt, size_t *length_p, ucs_socket_io_err_cb_t err_cb, void *err_cb_arg); /** * Blocking receive operation receives data from the connected (or bound * connectionless) socket referred to by the file descriptor `fd`. * * @param [in] fd Socket fd. * @param [in] data A pointer to a buffer to receive the incoming * data. * @param [in/out] length The length, in bytes, of the data in buffer * pointed to by the `data` paramete. * @param [in] err_cb Error callback. * @param [in] err_cb_arg User's argument for the error callback. * * @return UCS_OK on success, UCS_ERR_CANCELED if connection closed, * UCS_ERR_IO_ERROR on failure. */ ucs_status_t ucs_socket_recv(int fd, void *data, size_t length, ucs_socket_io_err_cb_t err_cb, void *err_cb_arg); /** * Return size of a given sockaddr structure. * * @param [in] addr Pointer to sockaddr structure. * @param [out] size_p Pointer to variable where size of * sockaddr_in/sockaddr_in6 structure will be written * * @return UCS_OK on success or UCS_ERR_INVALID_PARAM on failure. */ ucs_status_t ucs_sockaddr_sizeof(const struct sockaddr *addr, size_t *size_p); /** * Return port of a given sockaddr structure. * * @param [in] addr Pointer to sockaddr structure. * @param [out] port_p Pointer to variable where port (host notation) * of sockaddr_in/sockaddr_in6 structure will be written * * @return UCS_OK on success or UCS_ERR_INVALID_PARAM on failure. */ ucs_status_t ucs_sockaddr_get_port(const struct sockaddr *addr, uint16_t *port_p); /** * Set port to a given sockaddr structure. * * @param [in] addr Pointer to sockaddr structure. * @param [in] port Port (host notation) that will be written * * @return UCS_OK on success or UCS_ERR_INVALID_PARAM on failure. */ ucs_status_t ucs_sockaddr_set_port(struct sockaddr *addr, uint16_t port); /** * Return IP addr of a given sockaddr structure. * * @param [in] addr Pointer to sockaddr structure. * * @return IP address of sockaddr_in/sockaddr_in6 structure * on success or NULL on failure. */ const void *ucs_sockaddr_get_inet_addr(const struct sockaddr *addr); /** * Extract the IP address from a given sockaddr and return it as a string. * * @param [in] sock_addr Sockaddr to take IP address from. * @param [out] str A string filled with the IP address. * @param [in] max_size Size of a string (considering '\0'-terminated symbol) * * @return ip_str if the sock_addr has a valid IP address or 'Invalid address' * otherwise. */ const char* ucs_sockaddr_str(const struct sockaddr *sock_addr, char *str, size_t max_size); /** * Extract the IP address from a given socket fd and return it as a string. * * @param [in] fd Socket fd. * @param [out] str A string filled with the IP address. * @param [in] max_size Size of a string (considering '\0'-terminated symbol) * * @return ip_str if the sock_addr has a valid IP address or 'Invalid address' * otherwise. */ const char *ucs_socket_getname_str(int fd, char *str, size_t max_size); /** * Return a value indicating the relationships between passed sockaddr structures. * * @param [in] sa1 Pointer to sockaddr structure #1. * @param [in] sa2 Pointer to sockaddr structure #2. * @param [in/out] status_p Pointer (can be NULL) to a status: UCS_OK on success * or UCS_ERR_INVALID_PARAM on failure. * * @return Returns an integral value indicating the relationship between the * socket addresses: * > 0 - the first socket address is greater than the second * socket address; * < 0 - the first socket address is lower than the second * socket address; * = 0 - the socket addresses are equal. * Note: it returns a positive integer value in case of error occured * during comparison. */ int ucs_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, ucs_status_t *status_p); /** * Indicate if given IP addr is INADDR_ANY (IPV4) or in6addr_any (IPV6) * * @param [in] addr Pointer to sockaddr structure. * * @return 1 if input is INADDR_ANY or in6addr_any * 0 if not */ int ucs_sockaddr_is_inaddr_any(struct sockaddr *addr); /** * Copy the src_addr sockaddr to dst_addr sockaddr. The length to copy is * the size of the src_addr sockaddr. * * @param [in] dst_addr Pointer to destination sockaddr (to copy to). * @param [in] src_addr Pointer to source sockaddr (to copy from). * * @return UCS_OK on success or UCS_ERR_INVALID_PARAM on failure. */ ucs_status_t ucs_sockaddr_copy(struct sockaddr *dst_addr, const struct sockaddr *src_addr); /** * Copy into ifname_name the interface associated the IP on which the socket * file descriptor fd is bound on. IPv4 and IPv6 addresses are handled. * * @param [in] fd Socket fd. * @param [out] if_str A string filled with the interface name. * @param [in] max_strlen Maximum length of the if_str. */ ucs_status_t ucs_sockaddr_get_ifname(int fd, char *ifname_str, size_t max_strlen); END_C_DECLS #endif