From cfd2411e45547f9acf5f159bd7cfda742ca710fe Mon Sep 17 00:00:00 2001 From: frekky Date: Thu, 4 Feb 2016 20:44:57 +0800 Subject: [PATCH] Add utility functions for TCP sockets --- src/common.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/common.h | 3 +++ 2 files changed, 71 insertions(+) diff --git a/src/common.c b/src/common.c index 19b4461..459c063 100644 --- a/src/common.c +++ b/src/common.c @@ -397,6 +397,74 @@ check_topdomain(char *str, char **errormsg) return 0; } +int +socket_set_blocking(int fd, int blocking) +{ + /* Set non-blocking socket mode */ +#ifdef WINDOWS32 + if (ioctlsocket(fd, FIONBIO, &blocking) != 0) { + return WSAGetLastError(); + } +#else + int flags; + if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { + return flags; + } + + if (fcntl(fd, F_SETFL, blocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK))) == -1) + return errno; + +#endif + return 0; +} + +int +open_tcp_nonblocking(struct sockaddr_storage *addr, char **errormsg) +/* Open TCP connection to given address without blocking */ +{ + int fd, ret; + if ((fd = socket(addr->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { + if (errormsg) + *errormsg = strerror(errno); + return -1; + } + + if ((ret = socket_set_blocking(fd, 0)) != 0) { + if (errormsg) + *errormsg = strerror(ret); + return -1; + } + + if ((ret = connect(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_storage))) + == -1 && errno != EINPROGRESS) { + if (errormsg) + *errormsg = strerror(errno); + return -1; + } + + return fd; +} + +int +check_tcp_status(int fd, char **error) +/* checks connected status of given socket. + * returns error code. 0 if connected or EINPROGRESS if connecting */ +{ + int errornum = 0; + socklen_t len = sizeof(int); + + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errornum, &len) != 0) { + if (error) + *error = "getsockopt failed."; + return -1; + } + + if (error) + *error = strerror(errornum); + + return errornum; +} + #if defined(WINDOWS32) || defined(ANDROID) #ifndef ANDROID int diff --git a/src/common.h b/src/common.h index 56c6078..3064357 100644 --- a/src/common.h +++ b/src/common.h @@ -161,6 +161,9 @@ int open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6o int open_dns_from_host(char *host, int port, int addr_family, int flags); void close_dns(int); +int open_tcp_nonblocking(struct sockaddr_storage *addr, char **error); +int check_tcp_status(int fd, char **error); + void do_chroot(char *); void do_setcon(char *); void do_detach();