#include #include #include #include #include #include #include #include #include "log.h" #include "server.h" struct sock_t { int sockfd; char ip[INET6_ADDRSTRLEN]; }; static void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } int server_start(char *port, sock_t *sock) { struct addrinfo hints, *servinfo; int rv; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // use my IP if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) { err("getaddrinfo: %s", gai_strerror(rv)); return 1; } // loop through all the results and bind to the first we can struct addrinfo *p = NULL; for(p = servinfo; p != NULL; p = p->ai_next) { if ((sock->sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { err("socker: %s", strerror(errno)); continue; } int yes=1; if (setsockopt(sock->sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { err("setsockopt: %s", strerror(errno)); return 1; } if (bind(sock->sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sock->sockfd); err("bind: %s", strerror(errno)); continue; } break; } if (p == NULL) { err("server: failed to bind"); return 1; } freeaddrinfo(servinfo); if(listen(sock->sockfd, 10) == -1) { err("listen: %s", strerror(errno)); return 1; } return 0; } int server_accept(sock_t *sock, sock_t *conn) { struct sockaddr_storage conn_addr; socklen_t sz = sizeof(conn_addr); conn->sockfd = accept(sock->sockfd, (struct sockaddr *)&conn_addr, &sz); if(conn->sockfd == -1) { err("accept: %s", strerror(errno)); return 1; } inet_ntop(conn_addr.ss_family, get_in_addr((struct sockaddr *)&conn_addr), conn->ip, sizeof(conn->ip)); return 0; } ssize_t server_send(sock_t *sock, char *buf, size_t sz) { return send(sock->sockfd, buf, sz, 0); } ssize_t server_recv(sock_t *sock, char *buf, size_t sz) { return recv(sock->sockfd, buf, sz, 0); } char *server_connection_ip(sock_t *conn) { return conn->ip; } sock_t *server_sock_create() { return (sock_t *)malloc(sizeof(sock_t)); } void server_sock_close(sock_t *s) { close(s->sockfd); free(s); }