X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=usock.c;h=6748ef3767544862a66b34059dfda073862703cb;hb=682e071ef71f52125793aabb9e060343ea481443;hp=6458151c02f91e2e8bbde46f04b52005b3d5982d;hpb=07dbea00588bf322e16076cf7d818a13f934301f;p=project%2Flibubox.git diff --git a/usock.c b/usock.c index 6458151..6748ef3 100644 --- a/usock.c +++ b/usock.c @@ -1,13 +1,33 @@ +/* + * usock - socket helper functions + * + * Copyright (C) 2010 Steven Barth + * Copyright (C) 2011-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include #include #include #include +#include #include #include #include #include #include #include +#include #include "usock.h" @@ -20,7 +40,7 @@ static void usock_set_flags(int sock, unsigned int type) fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); } -static int usock_connect(struct sockaddr *sa, int sa_len, int family, int socktype, bool server) +static int usock_connect(int type, struct sockaddr *sa, int sa_len, int family, int socktype, bool server) { int sock; @@ -28,6 +48,8 @@ static int usock_connect(struct sockaddr *sa, int sa_len, int family, int sockty if (sock < 0) return -1; + usock_set_flags(sock, type); + if (server) { const int one = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); @@ -44,7 +66,7 @@ static int usock_connect(struct sockaddr *sa, int sa_len, int family, int sockty return -1; } -static int usock_unix(const char *host, int socktype, bool server) +static int usock_unix(int type, const char *host, int socktype, bool server) { struct sockaddr_un sun = {.sun_family = AF_UNIX}; @@ -54,7 +76,7 @@ static int usock_unix(const char *host, int socktype, bool server) } strcpy(sun.sun_path, host); - return usock_connect((struct sockaddr*)&sun, sizeof(sun), AF_UNIX, socktype, server); + return usock_connect(type, (struct sockaddr*)&sun, sizeof(sun), AF_UNIX, socktype, server); } static int usock_inet(int type, const char *host, const char *service, int socktype, bool server) @@ -74,7 +96,7 @@ static int usock_inet(int type, const char *host, const char *service, int sockt return -1; for (rp = result; rp != NULL; rp = rp->ai_next) { - sock = usock_connect(rp->ai_addr, rp->ai_addrlen, rp->ai_family, socktype, server); + sock = usock_connect(type, rp->ai_addr, rp->ai_addrlen, rp->ai_family, socktype, server); if (sock >= 0) break; } @@ -83,19 +105,56 @@ static int usock_inet(int type, const char *host, const char *service, int sockt return sock; } +const char *usock_port(int port) +{ + static char buffer[sizeof("65535\0")]; + + if (port < 0 || port > 65535) + return NULL; + + snprintf(buffer, sizeof(buffer), "%u", port); + + return buffer; +} + int usock(int type, const char *host, const char *service) { int socktype = ((type & 0xff) == USOCK_TCP) ? SOCK_STREAM : SOCK_DGRAM; bool server = !!(type & USOCK_SERVER); int sock; if (type & USOCK_UNIX) - sock = usock_unix(host, socktype, server); + sock = usock_unix(type, host, socktype, server); else sock = usock_inet(type, host, service, socktype, server); if (sock < 0) return -1; - usock_set_flags(sock, type); return sock; } + +int usock_wait_ready(int fd, int msecs) { + struct pollfd fds[1]; + int res; + + fds[0].fd = fd; + fds[0].events = POLLOUT; + + res = poll(fds, 1, msecs); + if (res < 0) { + return errno; + } else if (res == 0) { + return -ETIMEDOUT; + } else { + int err = 0; + socklen_t optlen = sizeof(err); + + res = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen); + if (res) + return errno; + if (err) + return err; + } + + return 0; +}