#include <unistd.h> #include <sys/socket.h> #include <sys/select.h> #include <netinet/in.h> #include "server.h" #include "conn_handler.h" // for all-purpose buffer #define MAX_LEN 1200 /* * This program is based on lab6c.c from EECE 446 * with modifications by Chris Gemperle and Sloane Tribble */ int main(int argc, char* argv[]){ const char *port = argv[1]; // an array containing all peers struct peer_entry *peers[MAX_PEERS]; for (int i = 0; i < MAX_PEERS; i++) { peers[i] = NULL; } // all_sockets stores all active sockets // call_set is a temporary used for the select call fd_set all_sockets, call_set; FD_ZERO(&all_sockets); char buf[MAX_LEN]; // listen_socket is the fd on which the program can accept() new connections int listen_socket = bind_and_listen(port); FD_SET(listen_socket, &all_sockets); // max_socket should always contain the socket fd with the largest value int max_socket = listen_socket; setbuf(stdout, NULL); // Disable stdout buffering while(1) { call_set = all_sockets; int num_s = select(max_socket+1, &call_set, NULL, NULL, NULL); if( num_s < 0 ){ perror("ERROR] Failure in select() call\n"); return -1; } // Skip standard IN/OUT/ERROR -> start at 3 for( int s = 3; s <= max_socket; ++s ) { // Skip sockets that aren't ready if( !FD_ISSET(s, &call_set) ) continue; // A new connection is available if( s == listen_socket ) { struct sockaddr_in peer_addr; socklen_t len = sizeof(peer_addr); int new_socket = accept(s, (struct sockaddr*) &peer_addr, &len); int newSlot = find_open_peer(peers); if (newSlot == -1) { perror("ERROR] Too many connections. New peer dropped.\n"); continue; } peers[newSlot]->socket_descriptor = new_socket; peers[newSlot]->address = peer_addr; FD_SET(new_socket, &all_sockets); max_socket = find_max_fd(&all_sockets); } else{ int len = recv( s, buf, sizeof(buf), 0 ); FD_CLR(s, &call_set); if (len > 0) { int result = process_request(buf, peers, s); if (result > 0) { send(s, buf, result, 0); } else if (result < 0) { perror("ERROR] Unexpected argument from remote peer\n"); } buf[0] = '\0'; continue; } if ( len < 0 ) perror( "ERROR] Error in recv. Dropping connection.\n"); FD_CLR(s, &all_sockets); int removed_index = find_peer(peers, s); free(peers[removed_index]); peers[removed_index] = NULL; max_socket = find_max_fd(&all_sockets); buf[0] = '\0'; // Not sure if it's needed, but it's cheap and I'm scared } } } }