/* Server.cpp
   The World's Smallest Web Server web server object */

#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "logging.h"
#include "Connection.h"
#include "Server.h"

void Server::run(int port)
{
    listen(create_server_socket(port));
}

int Server::create_server_socket(int port)
{
    log("Connecting server socket to port %d", port);
    int sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        abort("socket failed");
    }
    struct sockaddr_in name;
    name.sin_family = AF_INET;
    name.sin_port = htons(port);
    name.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
        abort("bind failed");
    }
    log("Listening...");
    if (::listen(sock, 0) == -1) {
        abort("listen failed");
    } 
    return sock;
}

void Server::listen(int server_socket) {
    // Ignore broken pipes.  This happens when a client connection disconnects
    // before the Connection has finished sending data.
    signal(SIGPIPE, SIG_IGN);
    while (1) {
        // Accept the incoming connection
        int sock;
        struct sockaddr_in clientname;
        size_t size = sizeof(clientname);
        sock = accept(server_socket, (struct sockaddr *) &clientname, &size);
        if (sock < 0) {
            abort("accept failed");
        }

        // TODO: if (verbose)
        // Output connection info to log
        log("Connection from %s::%hd accepted",
                inet_ntoa(clientname.sin_addr),
                ntohs(clientname.sin_port));

        Connection* c = new Connection(sock);
        c->handle_request();
    }
}