summaryrefslogtreecommitdiffstats
path: root/hw1/main.c
blob: fb152c55b5af9bbbbe9913aa0f63806dc2f2afa6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "common.h"
#include "server.h"
#include "proc.h"

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>

volatile sig_atomic_t proc_message_request;
volatile sig_atomic_t proc_quit_request;

static void proc_message_request_setter (int signo) {
    proc_message_request = 1;
}

static void proc_quit_request_setter (int signo) {
    proc_quit_request = 1;
}

static void message_cb (server* svr, request* req, int maxfd) {
    putchar ('\n');

    printf (
        "Dump server information ...\n"
        "  Server hostname: %s\n"
        "  Server port: %hu\n"
        "  Server is listening on fd %d\n",
        svr->hostname, svr->port, svr->listen_fd);

    puts ("Dump request table ...");
    for (int i = 0; i < maxfd; i++) {
        if (req[i].active) {
            printf (
                "  Client %d hostname: %s\n"
                "  Client %d filename: %s\n"
                "  Client %d filename done: %s\n"
                "  Client %d transfer started: %s\n",
                i, req[i].host,
                i, req[i].filename,
                i, req[i].header_done ? "true" : "false",
                i, req[i].header_accept ? "true" : "false");
        }
    }

    puts ("Dump file table ...");
    for (int i = 0; i < maxfd; i++) {
        if (svr->file_table->flist[i].active) {
            printf (
                "  Entry %d reference count: %d\n"
                "  Entry %d device: %llu\n"
                "  Entry %d inode: %llu\n"
                "  Entry %d file descriptors:",
                i, svr->file_table->flist[i].ref_count,
                i, (unsigned long long)svr->file_table->flist[i].fdev,
                i, (unsigned long long)svr->file_table->flist[i].fino, i);
            for (int j = 0; j < maxfd; j++) {
                if (FD_ISSET (j, &svr->file_table->flist[i].fset))
                    printf (" %d", j);
            }
            putchar ('\n');
        }
    }

    puts ("Type Ctrl-\\ to terminate the server\n");
    proc_message_request = 0;
}

int main(int argc, char** argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s [port]\n", argv[0]);
        exit(1);
    }

    // Setup signal handlers
    struct sigaction signal_action = {
        .sa_handler = SIG_IGN,
        .sa_flags = 0
    };
    sigemptyset (&signal_action.sa_mask);
    sigaction (SIGPIPE, &signal_action, NULL);
    signal_action.sa_handler = proc_message_request_setter;
    sigaction (SIGINT, &signal_action, NULL);
    signal_action.sa_handler = proc_quit_request_setter;
    sigaction (SIGQUIT, &signal_action, NULL);

    // Get file descripter table size
    int maxfd = getdtablesize();

    // Initialize server
    server svr;  // server
    server_init(&svr, (unsigned short) atoi(argv[1]), maxfd);

    // Initialize request table
    request* requestP = NULL;  // point to a list of requests
    requestP = (request*) e_malloc(sizeof(request) * maxfd);

    for (int i = 0; i < maxfd; i++)
        request_init(&requestP[i]);

    requestP[svr.listen_fd].conn_fd = svr.listen_fd;
    strcpy(requestP[svr.listen_fd].host, svr.hostname);

    // Loop for handling connections
    printf("\nstarting on %.80s, port %d, fd %d, maxfd %d ...\n",
        svr.hostname, svr.port, svr.listen_fd, maxfd);

    while (procconn(&svr, requestP, maxfd,
        (struct timeval) { 1, 0 }, message_cb));

    printf("\nquitting...\n");

    for (int i = 0; i < maxfd; i++) {
        if (requestP[i].filename != NULL) {
            free (requestP[i].filename);
            requestP[i].filename = NULL;
        }
    }

    free(requestP);
    server_free(&svr);

    return 0;
}