#include #include #include #include #include #include #include #include #include "socket.h" static int socket_nonblock(const psocket *psock) { int flags; flags = fcntl(psock->fd, F_GETFL, 0); if (flags < 0) return 1; flags |= O_NONBLOCK; if (fcntl(psock->fd, F_SETFL, flags) == -1) return 1; return 0; } int socket_init_in(const char *listen_addr, const char *listen_port, struct addrinfo **results) { struct addrinfo hints; assert(listen_addr || listen_port); /* getaddrinfo wants either node or service */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* IPV4 && IPV6 */ hints.ai_socktype = SOCK_STREAM; /* TCP */ hints.ai_flags = AI_PASSIVE; /* all interfaces */ return getaddrinfo(listen_addr, listen_port, &hints, results); } int socket_bind_in(psocket *psock, struct addrinfo *results) { int fd = -1, rv, reuse_enable = 1; struct addrinfo *rp = NULL; assert(psock && results); for (rp = results; rp != NULL; rp = rp->ai_next) { fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (fd < 0) continue; rv = bind(fd, rp->ai_addr, rp->ai_addrlen); if (!rv) break; close(fd); } if (!rp) return -1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int)) < 0) return -2; psock->fd = fd; psock->addr_len = rp->ai_addrlen; psock->addr = *rp->ai_addr; freeaddrinfo(results); return socket_nonblock(psock); } int socket_listen_in(psocket *psock) { assert(psock); return listen(psock->fd, POTD_BACKLOG); } int socket_accept_in(const psocket *psock, psocket *client_psock) { int fd; assert(psock && client_psock); client_psock->addr_len = psock->addr_len; fd = accept(psock->fd, &client_psock->addr, &client_psock->addr_len); if (fd < 0) return -1; if (socket_nonblock(psock)) return -2; client_psock->fd = fd; return 0; } int socket_addrtostr_in(const psocket *psock, char hbuf[NI_MAXHOST], char sbuf[NI_MAXSERV]) { int s; assert(psock); s = getnameinfo(&psock->addr, psock->addr_len, &hbuf[0], NI_MAXHOST, &sbuf[0], NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); return s; }