aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <dev@zapb.de>2020-08-12 01:33:38 +0200
committerMarc Schink <dev@zapb.de>2021-01-19 11:59:17 +0100
commit533a29b0096a84fdcfb3e06ddf4a8c16b9e4a809 (patch)
tree8201a4657d4b99893f6e209b5573f19976a5e962
parent22ddb088cdf8b59442d4e6504331644e768b800d (diff)
downloadlibjaylink-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.h2
-rw-r--r--libjaylink/socket.c68
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.