Add utility functions for TCP sockets

This commit is contained in:
frekky 2016-02-04 20:44:57 +08:00
parent d6b48fe4e1
commit cfd2411e45
2 changed files with 71 additions and 0 deletions

View File

@ -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

View File

@ -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();