#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>

#define BLOCK_SIZE 4096
#define BUF_SIZE BLOCK_SIZE
#define MAX_FILENAME_LENGTH 255

int main () {

    int sfd, ffd, cfd;
    struct addrinfo *res;
    char buffer[BUF_SIZE], filename[MAX_FILENAME_LENGTH];
    int count;

    if (getaddrinfo ("0.0.0.0", "4096", NULL, &res) != 0) {
	perror ("getaddrinfo()");
	exit (1);
    }

    //create a socket
    sfd = socket (AF_INET, SOCK_STREAM, 0);
    if (sfd == -1) {
	perror ("socket()");
	exit (1);
    }

    //bind to the port
    if (bind (sfd, res->ai_addr, res->ai_addrlen) == -1) {
	perror ("bind()");
	exit (1);
    }

    //listen on the port now
    if (listen (sfd, 50) == -1) {
	perror ("listen()");
	exit (1);
    }

    //accept a connection.
    cfd = accept (sfd, NULL, 0);
    if (cfd == -1) {
	perror ("accept()");
	exit (1);
    }

    //read filename from cfd
    count = read (cfd, filename, MAX_FILENAME_LENGTH);
    if (count == -1) {
	perror ("read()");
	exit (1);
    }
    filename[count] = '\0';
    
    ffd = open (filename, O_RDONLY);
    if (ffd == -1) {
	//strictly speaking, client must be notified
	perror ("open()");
	exit (1);
    }

    //now read the file and write it to cfd
    while (1) {
	count = read (ffd, buffer, BUF_SIZE);
	if (count == -1) {
	    perror ("read()");
	    exit (1);
	}
	if (write (cfd, buffer, count) < count) {
	    perror ("read()");
	    exit (1);
	}

	if (count < BUF_SIZE)
	    continue;
	else
	    break; // fully read
    }

    close (ffd);
    close (cfd);
    close (sfd);
 
    return 0;
}

