#define _GNU_SOURCE #include "socket.hfa" #include #include extern "C" { #include #include } #include #include #include #include "options.hfa" int prepaddr(struct sockaddr_in & address) { int addrlen = sizeof(address); memset( (char *)&address, '\0', addrlen ); address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = htons( options.socket.port ); return addrlen; } int listener(struct sockaddr_in & address, int addrlen) { int type = SOCK_STREAM; if(options.socket.reuseport) type |= SOCK_NONBLOCK; int sockfd = socket(AF_INET, type, 0); if(sockfd < 0) { abort( "socket error: (%d) %s\n", (int)errno, strerror(errno) ); } if(options.socket.reuseport) { int value = 1; // if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*)&on, sizeof(on))) // abort( "setsockopt SO_REUSEADDR error: (%d) %s\n", (int)errno, strerror(errno) ); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(int)) < 0) abort( "setsockopt SO_REUSEPORT error: (%d) %s\n", (int)errno, strerror(errno) ); } int ret = 0; int waited = 0; for() { __CONST_SOCKADDR_ARG addr; addr.__sockaddr__ = (struct sockaddr *)&address; socklen_t addrlen = sizeof(address); ret = bind( sockfd, addr, addrlen ); if(ret < 0) { if(errno == EADDRINUSE) { if(waited == 0) { if(!options.interactive) abort | "Port already in use in non-interactive mode. Aborting"; sout | "Waiting for port"; } else { sout | "\r" | waited | nonl; flush( sout ); } waited ++; sleep( 1`s ); continue; } abort( "bind error: (%d) %s\n", (int)errno, strerror(errno) ); } break; } ret = listen( sockfd, options.socket.backlog ); if(ret < 0) { abort( "listen error: (%d) %s\n", (int)errno, strerror(errno) ); } return sockfd; }