diff --git a/src/wstationd.c b/src/wstationd.c index 9745780..7f65113 100644 --- a/src/wstationd.c +++ b/src/wstationd.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -37,19 +38,22 @@ int main(int argc, char *argv[]) { NULL, 0, NULL, 0 } }; - int flag = 1; - int sockfd = 0, connfd = 0; - int port = 10800; - uint32_t address = INADDR_ANY; - struct sockaddr_in sock; + fd_set readfds, masterfds; - struct sockaddr_in client; + int port = 10800; // Default port + uint32_t address = INADDR_ANY; // Default listen address + int sockflag = 1, sockfd = 0, connfd = 0; + struct sockaddr_in sock, client; socklen_t client_sz = sizeof(client); char timebuff[15], fnbuff[35]; time_t timeraw; struct tm* timeptr; + // Allocate space for the output fds + int writefds[FD_SETSIZE]; + memset(&writefds, 0, sizeof(int) * FD_SETSIZE); + exec_name = basename(argv[0]); for(int ch; (ch = getopt_long(argc, argv, "b:p:vh0", longopts, NULL)) != -1;){ @@ -107,7 +111,7 @@ int main(int argc, char *argv[]) // This sets REUSE on the socket so it's easily reallocated if // this program dies - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockflag, sizeof(sockflag)); memset(&sock, 0, sizeof(sock)); sock.sin_family = AF_INET; @@ -123,47 +127,79 @@ int main(int argc, char *argv[]) } // Listen on port - if(listen(sockfd, 5) != 0){ + if(listen(sockfd, 10) != 0){ fprintf(stderr, "%s: cannot listen - %s\n", exec_name, strerror(errno) ); goto shutdown_error; } + FD_ZERO(&masterfds); + FD_SET(sockfd, &masterfds); + while(1){ - // Wait for a connection on our bound socket - connfd = accept(sockfd, (struct sockaddr*)&client, &client_sz); - if(connfd == -1){ - fprintf(stderr, "%s: accept failed - %s\n", + readfds = masterfds; + if(select(FD_SETSIZE, &readfds, NULL, NULL, NULL) == -1){ + fprintf(stderr, "%s: socket select error - %s\n", exec_name, strerror(errno) ); goto shutdown_error; } - // Collect the time of the connection, process it into - // a short string - time(&timeraw); - timeptr = localtime(&timeraw); - strftime(&timebuff[0], 15, "%Y%m%d%H%M%S", timeptr); - timeptr = NULL; - - // Take the short date/time connection string and add the client address - // to create a filename - snprintf(&fnbuff[0], 34, "%s-%s.dat", timebuff, inet_ntoa(client.sin_addr)); - - fprintf(stdout, "filename: %s\n", fnbuff); - - // We're done, close the connection - close(connfd); connfd = 0; + for(int i = 0; i < FD_SETSIZE; i++){ + if(FD_ISSET(i, &readfds)){ + // Deal with new connections + if(i == sockfd){ + connfd = accept(sockfd, (struct sockaddr*)&client, &client_sz); + if(connfd == -1){ + fprintf(stderr, "%s: accept failed - %s\n", + exec_name, strerror(errno) + ); + } + + // Collect the time of the connection, process it into + // a short string + time(&timeraw); + timeptr = localtime(&timeraw); + strftime(&timebuff[0], 15, "%Y%m%d%H%M%S", timeptr); + timeptr = NULL; + + // Take the short date/time connection string and add the client address + // to create a filename + snprintf(&fnbuff[0], 34, "%s-%s.dat", + timebuff, inet_ntoa(client.sin_addr) + ); + + if((writefds[i] = open(fnbuff, O_WRONLY | O_CREAT, 0644)) == -1){ + writefds[i] = 0; + fprintf(stderr, "%s: cannot open - %s\n", + exec_name, strerror(errno) + ); + + close(connfd); + } else { + FD_SET(connfd, &masterfds); + } + connfd = 0; + + // Read from existing connections + } else { + if(writefds[i] != 0){ + close(writefds[i]); + writefds[i] = 0; + } + FD_CLR(i, &masterfds); + close(i); + } + } + } } shutdown_clean: - if(connfd > 0) close(connfd); if(sockfd > 0) close(sockfd); return 0; shutdown_error: - if(connfd > 0) close(connfd); if(sockfd > 0) close(sockfd); return 1; }