summaryrefslogtreecommitdiff
path: root/src/server/server.c
blob: c8975ee2b4c23a756a9609ed7a65908e62c7e526 (plain)
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
#define _POSIX_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

#include "addr.h"
#include "server.h"
#include "resolver.h"
#include "../io/log.h"

static pid_t udp, tcp;

void server_init(uint16_t port, Server* server) {
    INFO("Server port set to %hu", port);
    create_binding(UDP, port, &server->udp);
    create_binding(TCP, port, &server->tcp);
}

static void server_listen(Binding* binding) {
    while(1) {

        Connection connection;
        if (!accept_connection(binding, &connection)) {
            ERROR("Failed to accept connection");
            continue;
        }

        Packet request;
        if (!read_connection(&connection, &request)) {
            ERROR("Failed to read connection");
            free_connection(&connection);
            continue;
        }
        
        if(fork() != 0) {
            free_packet(&request);
            free_connection(&connection);
            continue;
        }

        INFO("Recieved packet request ID %hu", request.header.id);

        Packet response;
        handle_query(&request, &response, connection.type);

        if (!write_connection(&connection, &response)) {
            ERROR("Failed to respond to connection ID %hu: %s", request.header.id, strerror(errno));
        }

        free_packet(&request);
        free_packet(&response);
        free_connection(&connection);
        exit(EXIT_SUCCESS);
    }
}

static void signal_handler() {
    printf("\n");
    kill(udp, SIGTERM);
    kill(tcp, SIGTERM);
}

void server_run(Server* server) {
    if ((udp = fork()) == 0) {
        INFO("Listening for connections on UDP");
        server_listen(&server->udp);
        exit(EXIT_SUCCESS);
    }

    if ((tcp = fork()) == 0) {
        INFO("Listening for connections on TCP");
        server_listen(&server->tcp);
        exit(EXIT_SUCCESS);
    }

    signal(SIGINT, signal_handler);

    int status;    
    waitpid(udp, &status, 0); 
    if (status == 0) {
        INFO("UDP process closed successfully");
    } else {
        ERROR("UDP process failed with error code %d", status);
    }

    waitpid(tcp, &status, 0);    
    if (status == 0) {
        INFO("TCP process closed successfully");
    } else {
        ERROR("TCP process failed with error code %d", status);
    }
}

void server_free(Server* server) {
    free_binding(&server->udp);
    free_binding(&server->tcp);
}