/* Fileserver-Programm
 * Dieser Server wartet auf einen Connect vom zugehoerigen Client.
 * Der Client sendet einen Dateinamen und der Server schickt diese
 * Datei (sofern vorhanden) dann an den Client
 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* Port fuer die Requests */
#define PORT 7777

/* Puffergroesse */
#define BUFSIZE 4096

/* Fehlermeldung ausgeben und exit */
void err_exit(char *message)
  {
  perror(message);
  exit(1);
  }

int main()
  {
  int sockd,sockd2;
  int addrlen;
  struct sockaddr_in my_name, peer_name;
  int status;
  int fd, i, count_r, count_w;
  char* bufptr;
  char buf[BUFSIZE];
  char filename[BUFSIZE];

  /* create a socket */
  sockd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockd == -1)
  err_exit("Socket creation");

  /* socket binding */
  memset( &my_name, 0, sizeof (my_name));
  my_name.sin_family = AF_INET;
  my_name.sin_addr.s_addr = INADDR_ANY;
  my_name.sin_port = htons(PORT);

  status = bind(sockd, (struct sockaddr*)&my_name, sizeof(my_name));
  if (status == -1)
  err_exit("Binding");

  status = listen(sockd, 5);
  if (status == -1)
    err_exit("Listening");

  printf("File server ready ...\n");
  for(;;)
    {
    /* wait for an incoming connection */
    addrlen = sizeof(peer_name);
    sockd2 = accept(sockd, (struct sockaddr*)&peer_name, (socklen_t *)&addrlen);
    if (sockd2 == -1)
      err_exit("Connection accept");

    i = 0;
    if ((count_r = read(sockd2, filename + i, BUFSIZE)) > 0)
      i += count_r;
    filename[i-1] = '\0';
    if (count_r == -1)
      err_exit("Read error");

    printf("Trying to read file %s\n", filename);
    fd = open(filename, O_RDONLY);
    if (fd == -1)
      {
      perror("File open error");
      close(fd);
      close(sockd2);
      continue;
      }
    while((count_r = read(fd, buf, BUFSIZE)) > 0)
      {
      count_w = 0;
      bufptr = buf;
      while (count_w < count_r)
        {
        count_r -= count_w;
        bufptr += count_w;
        count_w = write(sockd2, bufptr, count_r);
        if (count_w == -1)
          err_exit("Socket write error");
        }
      }
    close(fd);
    close(sockd2);
    }
  return 0;
  }

