#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #ifndef OPEN_MAX #define OPEN_MAX 1024 #endif #define PORT "3000" #define BUFSIZE 1024 static int create_server(const char *port) { int fd, yes = 1; struct addrinfo *res, *p, hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(NULL, port, &hints, &res) != 0) { perror("getaddrinfo"); return -1; } for (p = res; p != NULL; p = p->ai_next) { if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("socket"); continue; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); close(fd); return -1; } if (ioctl(fd, FIONBIO, &yes) == -1) { perror("ioctl"); close(fd); return -1; } if (bind(fd, p->ai_addr, p->ai_addrlen) == -1) { perror("bind"); continue; } break; } freeaddrinfo(res); if (p == NULL) { fprintf(stderr, "failed to bind\n"); return -1; } if (listen(fd, 32) == -1) { perror("listen"); return -1; } logmsg(LOG_INFO, "listening on %s", port); return fd; } static int accept_connection(int s_fd) { int c_fd; if ((c_fd = accept(s_fd, NULL, NULL)) == -1) { if (errno != EWOULDBLOCK || errno != EAGAIN) { perror("accept"); exit(1); } return -1; } logmsg(LOG_INFO, "connection accepted"); return c_fd; } static void handle_client(int c_fd) { int n; char buf[BUFSIZE]; n = recv(c_fd, &buf, BUFSIZE - 1, 0); switch (n) { case -1: if (errno != EWOULDBLOCK || errno != EAGAIN) { perror("recv"); } case 0: logmsg(LOG_INFO, "connection closed by client"); default: buf[n] = '\0'; if (send(c_fd, buf, n, 0) == -1) { perror("send"); } } close(c_fd); } static void main_loop(int s_fd) { int i, rc, end_server = 0; int c_fd, nfds = 1, curr_size = 0; struct pollfd pfds[OPEN_MAX]; memset(pfds, 0, sizeof(pfds)); pfds[0].fd = s_fd; pfds[0].events = POLLIN; do { rc = poll(pfds, nfds, -1); if (rc == -1) { perror("poll"); break; } if (rc == 0) { fprintf(stderr, "poll timeout\n"); break; } curr_size = nfds; for (i = 0; i < curr_size; i++) { if (pfds[i].revents == 0) continue; if (pfds[i].revents != POLLIN) { logmsg(LOG_INFO, "revents not POLLIN\n"); end_server = 1; break; } if (pfds[i].fd == s_fd) { do { c_fd = accept_connection(s_fd); if (c_fd != -1) { pfds[nfds].fd = c_fd; pfds[nfds].events = POLLIN; nfds++; } } while (c_fd != -1); } else { handle_client(pfds[i].fd); pfds[i].fd = -1; } } } while (end_server == 0); } int main() { int s_fd; s_fd = create_server(PORT); if (s_fd == -1) { fprintf(stderr, "failed to create server\n"); exit(0); } main_loop(s_fd); return 0; }