P2P-File-Sharing / Registry / registry.c
registry.c
Raw
#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
            }
        }
    }
}