#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <math.h>
#include <time.h>
#define MAX_BUF 128

int print_ms()
{
    long ms;
    time_t s;
    struct timespec spec;

    clock_gettime(CLOCK_REALTIME, &spec);

    s  = spec.tv_sec;
    ms = round(spec.tv_nsec / 1.0e6);
    if (ms > 999) {
        s++;
        ms = 0;
    }
    return ms;
}


int main()
{
    int s, new_s;
    unsigned char mip_str[INET_ADDRSTRLEN];
    struct addrinfo h, *r;

    printf("[%d ms] Server started\nWaiting for connection\n", print_ms());
    memset(&h, 0, sizeof(struct addrinfo));
    h.ai_family=PF_INET;
    h.ai_socktype=SOCK_STREAM;
    h.ai_flags=AI_PASSIVE;

    if(getaddrinfo(NULL, "11630", &h, &r)!=0){
        printf("[%d ms] ERROR: %s\n", print_ms(), strerror(errno));
        exit(-1);
    }

    if((s=socket(r->ai_family, r->ai_socktype, r->ai_protocol))==-1){
        printf("[%d ms] ERROR: %s\n", print_ms(), strerror(errno));
        exit(-1);
    }
    if(bind(s, r->ai_addr, r->ai_addrlen)!=0){
        printf("[%d ms] ERROR: %s\n", print_ms(), strerror(errno));
        exit(-1);
    }

    if(listen(s, 1)!=0){
        printf("[%d ms] ERROR: %s\n", print_ms(), strerror(errno));
        exit(-1);
    }
    struct sockaddr_in their_addr;
    socklen_t addr_size=sizeof(their_addr);
    if((new_s=accept(s, (struct sockaddr *)&their_addr, &addr_size))==-1){
        printf("[%d ms] ERROR: %s\n", print_ms(), strerror(errno));
        exit(-1);
    }
    else{
        printf("[%d ms] Peer connected\n", print_ms());
    }

    ssize_t bytes_received;
    for(;;){
        char message[MAX_BUF];
        bytes_received = recv(new_s, message, MAX_BUF, 0);
        
        if(bytes_received == 0){
            printf("[%d ms] Peer was disconnected\n", print_ms());
            break;
        } else if(bytes_received < 0){
            printf("[%d ms] ERROR: Failed to receive message: '%s'\n", print_ms(), strerror(errno));
            exit(-4);
        } else {
            message[bytes_received]='\0';
            printf("[%d ms] Recv() (%zd bytes): %s\n", print_ms(), bytes_received, message);
        }
    }

    freeaddrinfo(r);
    close(new_s);
    close(s);
    return 0;
}
