diff options
author | Marc Schink <dev@zapb.de> | 2020-08-12 01:33:38 +0200 |
---|---|---|
committer | Marc Schink <dev@zapb.de> | 2021-01-19 11:59:17 +0100 |
commit | 533a29b0096a84fdcfb3e06ddf4a8c16b9e4a809 (patch) | |
tree | 8201a4657d4b99893f6e209b5573f19976a5e962 | |
parent | 22ddb088cdf8b59442d4e6504331644e768b800d (diff) | |
download | libjaylink-533a29b0096a84fdcfb3e06ddf4a8c16b9e4a809.zip libjaylink-533a29b0096a84fdcfb3e06ddf4a8c16b9e4a809.tar.gz libjaylink-533a29b0096a84fdcfb3e06ddf4a8c16b9e4a809.tar.bz2 |
socket: Add function to establish a connection
Signed-off-by: Marc Schink <dev@zapb.de>
-rw-r--r-- | libjaylink/libjaylink-internal.h | 2 | ||||
-rw-r--r-- | libjaylink/socket.c | 68 |
2 files changed, 70 insertions, 0 deletions
diff --git a/libjaylink/libjaylink-internal.h b/libjaylink/libjaylink-internal.h index 0952998..d24ea7c 100644 --- a/libjaylink/libjaylink-internal.h +++ b/libjaylink/libjaylink-internal.h @@ -255,6 +255,8 @@ JAYLINK_PRIV void log_dbgio(const struct jaylink_context *ctx, /*--- socket.c --------------------------------------------------------------*/ +JAYLINK_PRIV int socket_connect(int sock, const struct sockaddr *address, + size_t address_length, size_t timeout); JAYLINK_PRIV bool socket_close(int sock); JAYLINK_PRIV bool socket_bind(int sock, const struct sockaddr *address, size_t length); diff --git a/libjaylink/socket.c b/libjaylink/socket.c index 9586e0c..cb0a5cd 100644 --- a/libjaylink/socket.c +++ b/libjaylink/socket.c @@ -17,6 +17,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> #ifdef _WIN32 #include <winsock2.h> #else @@ -36,6 +37,73 @@ */ /** + * Initiate a connection on a socket. + * + * @param[in] sock Socket descriptor. + * @param[in] address Address to establish the connection. + * @param[in] length Length of the structure pointed to by @p address in bytes. + * @param[in] timeout Connection timeout in milliseconds, 0 for no timeout. + * + * @retval JAYLINK_OK Success. + * @retval JAYLINK_ERR_ARG Invalid arguments. + * @retval JAYLINK_ERR_TIMEOUT A timeout occurred. + * @retval JAYLINK_ERR Other error conditions. + */ +JAYLINK_PRIV int socket_connect(int sock, const struct sockaddr *address, + size_t address_length, size_t timeout) +{ + int ret; + fd_set fds; + struct timeval tv; + int socket_error; + size_t option_length; + + if (!address) + return JAYLINK_ERR_ARG; + + if (!socket_set_blocking(sock, false)) + return JAYLINK_ERR; +#ifdef _WIN32 + ret = connect(sock, address, address_length); + + if (ret != 0 && WSAGetLastError() != WSAEWOULDBLOCK) + return JAYLINK_ERR; +#else + errno = 0; + ret = connect(sock, address, address_length); + + if (ret != 0 && errno != EINPROGRESS) + return JAYLINK_ERR; +#endif + if (!ret) + return JAYLINK_OK; + + FD_ZERO(&fds); + FD_SET(sock, &fds); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + ret = select(sock + 1, NULL, &fds, NULL, &tv); + + socket_set_blocking(sock, true); + + if (!ret) + return JAYLINK_ERR_TIMEOUT; + + option_length = sizeof(socket_error); + + if (!socket_get_option(sock, SOL_SOCKET, SO_ERROR, &socket_error, + &option_length)) + return JAYLINK_ERR; + + if (!socket_error) + return JAYLINK_OK; + + return JAYLINK_ERR; +} + +/** * Close a socket. * * @param[in] sock Socket descriptor. |