Преглед на файлове

client side package receiving, quit-, send- and list command, testdata

Kajetan Johannes Hammerle преди 5 години
родител
ревизия
61eacffa4c
променени са 22 файла, в които са добавени 1187 реда и са изтрити 124 реда
  1. 103 74
      Client.c
  2. 12 2
      Client.h
  3. 295 5
      ClientMain.c
  4. 3 2
      Makefile
  5. 27 14
      Server.c
  6. 5 3
      Server.h
  7. 636 23
      ServerMain.c
  8. 13 0
      Stream.c
  9. 4 1
      Stream.h
  10. 62 0
      String.c
  11. 19 0
      String.h
  12. 1 0
      mails/Wusler/Gusi/0/gdfgdf
  13. 1 0
      mails/Wusler/Wusi/1/ddddd
  14. BIN
      mails/Wusler/mailcounter
  15. 1 0
      mails/b/a/0/c
  16. 1 0
      mails/b/a/1/c
  17. 1 0
      mails/b/a/2/c
  18. 1 0
      mails/b/b/3/fdfg
  19. 1 0
      mails/b/b/4/sgdh
  20. BIN
      mails/b/mailcounter
  21. BIN
      mails/heinz/mailcounter
  22. 1 0
      mails/heinz/wusler/0/Hallo Heinz

+ 103 - 74
Client.c

@@ -1,3 +1,4 @@
+#include "Client.h"
 #include <sys/socket.h>
 #include <stdio.h>
 #include <sys/socket.h>
@@ -6,19 +7,77 @@
 #include <arpa/inet.h>
 #include <string.h>
 #include <unistd.h>
-#include "Stream.h"
-#include "Client.h"
+#include <stdlib.h>
+#define __USE_POSIX
+#include <sys/types.h>
+#include <signal.h>
 #include "SocketUtils.h"
 
 void clientInitDefaults(Client* c)
 {
     c->port = -1;
     c->socket = -1;
+    
+    c->thread = -1;
+    
+    c->hAmount = -1;
+    c->hIndex = -1;
+    c->handlers = NULL;
+}
+
+static void* serverHandler(void* data)
+{
+    Client* c = (Client*) data;
+    
+    Stream in;
+    while(1)
+    {
+        streamInit(&in, 1024);
+        int size = receiveAll(c->socket, &in);
+        if(size > 0)
+        {
+            int package;
+            if(streamGetInt(&in, &package) == -1)
+            {
+                printf("Invalid package %d from server\n", package);
+            }
+            else
+            {
+                if(package >= 0 && package < c->hIndex)
+                {
+                    printf("Received package %d from server\n", package);
+                    c->handlers[package](&in);
+                }
+                else
+                {
+                    printf("Invalid package %d from server\n", package);
+                }
+            }
+        }
+        else if(size == 0)
+        {
+            printf("Server closed remote socket\n");
+            streamRemove(&in);
+            break;
+        }   
+        else
+        {
+            streamRemove(&in);
+            break;
+        }
+        streamRemove(&in);
+    }
+    
+    __pid_t pid = getpid();
+    kill(pid, SIGINT);
+    return NULL;
 }
 
 int clientInit(Client* c, char* ip, short port)
 {
     c->port = port;
+    c->hAmount = 0;
+    c->hIndex = 0;
     
     c->socket = socket(AF_INET, SOCK_STREAM, 0);
     if(c->socket == -1)
@@ -67,6 +126,14 @@ int clientInit(Client* c, char* ip, short port)
                 char welcome[100];
                 streamGetChars(&in, welcome, 100);
                 printf("%s\n", welcome);
+                
+                if(pthread_create(&c->thread, NULL, serverHandler, (void*) c) != 0)
+                {
+                    perror("Cannot create thread");  
+                    streamRemove(&in);
+                    clientRemove(c);
+                    return -1;
+                }
             }
             else
             {
@@ -115,94 +182,56 @@ void clientRemove(Client* c)
             printf("socket closed\n");
         }
     }
-}
-
-void clearInput()
-{
-    int c = getchar();  
-    while(c != EOF && c != '\n')
+    
+    if(c->thread != -1)
+    {
+        pthread_cancel(c->thread);
+        pthread_join(c->thread, NULL);
+        printf("thread cancel\n");
+        c->thread = -1;
+    }
+    
+    c->hAmount = -1;
+    c->hIndex = -1;
+    if(c->handlers != NULL)
     {
-        c = getchar(); 
+        free(c->handlers);
+        c->handlers = NULL;
     }
 }
 
-int readInt()
+int clientSendData(Client* c, Stream* out)
 {
-    int type;
-    while(scanf("%d", &type) == 0)
+    int bytes = sendAll(c->socket, out);
+    if(bytes == -1)
     {
-        printf("Not a number\n");
-        clearInput();
+        return -1;
     }
-    clearInput();
-    return type;
+    //printf("%d Bytes from %d sent\n", bytes, s->index);
+    return 0;
 }
 
-void clientWaitForData(Client* c)
+void clientRegisterHandler(Client* c, ClientStreamFunction f)
 {
-    while(1)
+    if(c->hAmount == c->hIndex)
     {
-        printf("Choose a package: ");
-        int type = readInt();
-        
-        if(type == -1)
+        if(c->hAmount == 0)
         {
-            break;
+            c->handlers = malloc(sizeof(ClientStreamFunction));
+            c->hAmount = 1;
         }
-        else if(type >= 0 && type < 4)
+        else
         {
-            Stream out;
-            streamInit(&out, 16);
-            streamWriteChar(&out, type);
-            
-            switch(type)
+            c->hAmount *= 2;
+            ClientStreamFunction* functions = malloc(sizeof(ClientStreamFunction) * c->hAmount);
+            for(int i = 0; i < c->hIndex; i++)
             {
-                case 0:
-                    printf("first number: ");
-                    streamWriteInt(&out, readInt());
-                    printf("second number: ");
-                    streamWriteInt(&out, readInt());
-                    break;
-                case 1:
-                    printf("text: ");
-                    char buffer[128];
-                    fgets(buffer, 128, stdin);
-                    if(strlen(buffer) == 127 && buffer[126] != '\n')
-                    {
-                        clearInput();
-                    }
-                    streamWriteChars(&out, buffer);
-                    break;
-                case 2:
-                    for(int i = 0; i < 260; i++)
-                    {
-                        streamWriteInt(&out, i);
-                    }
-                    break;
+                functions[i] = c->handlers[i];
             }
-            
-            if(clientSendData(c, &out) == -1)
-            {
-                streamRemove(&out);
-                break;
-            }
-            streamRemove(&out);
+            free(c->handlers);
+            c->handlers = functions;
         }
-        else
-        {
-            printf("%d is not a valid package number\n", type);
-        }
-    }
-}
-
-int clientSendData(Client* c, Stream* s)
-{
-    int bytes = sendAll(c->socket, s);
-    if(bytes == -1)
-    {
-        perror("Cannot send data");
-        return -1;
     }
-    //printf("%d Bytes from %d sent\n", bytes, s->index);
-    return 0;
+    c->handlers[c->hIndex] = f;
+    c->hIndex++;
 }

+ 12 - 2
Client.h

@@ -1,10 +1,19 @@
 #ifndef CLIENT_H
 #define CLIENT_H
 
+#include <pthread.h>
+#include "Stream.h"
+
 typedef struct Client
 {
     short port;
     int socket;
+    
+    pthread_t thread;
+    
+    int hAmount;
+    int hIndex;
+    ClientStreamFunction* handlers;
 } Client;
 
 void clientInitDefaults(Client* c);
@@ -12,9 +21,10 @@ int clientInit(Client* c, char* ip, short port);
 void clientRemove(Client* c);
 
 int clientReceive(Client* c, Stream* in); 
-void clientWaitForData(Client* c);
 
-int clientSendData(Client* c, Stream* s);
+int clientSendData(Client* c, Stream* out);
+
+void clientRegisterHandler(Client* c, ClientStreamFunction f);
 
 #endif
 

+ 295 - 5
ClientMain.c

@@ -1,10 +1,10 @@
 #include <stdio.h>
-#include <signal.h>
 #include <unistd.h>
 #include <stdlib.h>
-
-#include "Stream.h"
+#include <signal.h>
+#include <string.h>
 #include "Client.h"
+#include "String.h"
 
 Client client;
 
@@ -14,7 +14,294 @@ void interruptHandler(int signal)
     exit(EXIT_SUCCESS);
 }
 
-int main(int argc, char **argv)
+int readNumber(const char* text)
+{
+    while(1)
+    {
+        int number;
+        printf("%s", text);
+        int result = scanf("%d", &number);
+        char c = getchar();
+        while(c != EOF && c != '\n')
+        {
+            c = getchar();
+        }
+        
+        if(result != 0)
+        {
+            return number;
+        }
+    }
+    return -1;
+}
+
+void waitForData()
+{
+    while(1)
+    {
+        printf("Type a command: ");
+        String s;
+        stringInit(&s);
+        stringRead(&s);
+        
+        if(stringCompare(&s, "SEND"))
+        {
+            printf("Sending a mail to the server...\n");
+            
+            //outgoing stream
+            Stream out;
+            streamInit(&out, 128);
+            streamWriteInt(&out, 0);
+            
+            // sender
+            printf("Type a sender with at most 8 characters: ");
+            String sender;
+            stringInit(&sender);
+            stringRead(&sender);
+            int l = stringGetLength(&sender);
+            while(l < 1 || l > 8)
+            {
+                printf("Please type a valid sender: ");
+                stringRemove(&sender);
+                stringInit(&sender);
+                stringRead(&sender);
+                l = stringGetLength(&sender);
+            }
+            streamWriteChars(&out, sender.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&sender);
+            
+            // receiver
+            printf("Type a receiver with at most 8 characters: ");
+            String receiver;
+            stringInit(&receiver);
+            stringRead(&receiver);
+            l = stringGetLength(&receiver);
+            while(l < 1 || l > 8)
+            {
+                printf("Please type a valid receiver: ");
+                stringRemove(&receiver);
+                stringInit(&receiver);
+                stringRead(&receiver);
+                l = stringGetLength(&receiver);
+            }
+            streamWriteChars(&out, receiver.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&receiver);
+            
+            // subject
+            printf("Type a subject with at most 80 characters: ");
+            String subject;
+            stringInit(&subject);
+            stringRead(&subject);
+            l = stringGetLength(&subject);
+            while(l < 1 || l > 80)
+            {
+                printf("Please type a valid receiver: ");
+                stringRemove(&subject);
+                stringInit(&subject);
+                stringRead(&subject);
+                l = stringGetLength(&subject);
+            }
+            streamWriteChars(&out, subject.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&subject);
+            
+            // message
+            printf("Type a message: ");
+            String message;
+            stringInit(&message);
+            stringRead(&message);
+            streamWriteChars(&out, message.data);
+            streamWriteChars(&out, "\n.\n");
+            stringRemove(&message);
+            
+            // send and clear stream
+            clientSendData(&client, &out);
+            streamRemove(&out);
+        }
+        else if(stringCompare(&s, "LIST"))
+        {
+            //outgoing stream
+            Stream out;
+            streamInit(&out, 16);
+            streamWriteInt(&out, 1);
+            
+            // user
+            printf("Type a user with at most 8 characters: ");
+            String sender;
+            stringInit(&sender);
+            stringRead(&sender);
+            int l = stringGetLength(&sender);
+            while(l < 1 || l > 8)
+            {
+                printf("Please type a valid user: ");
+                stringRemove(&sender);
+                stringInit(&sender);
+                stringRead(&sender);
+                l = stringGetLength(&sender);
+            }
+            streamWriteChars(&out, sender.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&sender);
+            
+            // send and clear stream
+            clientSendData(&client, &out);
+            streamRemove(&out);
+        }
+        else if(stringCompare(&s, "READ"))
+        {
+            //outgoing stream
+            Stream out;
+            streamInit(&out, 16);
+            streamWriteInt(&out, 2);
+            
+            // user
+            printf("Type a user with at most 8 characters: ");
+            String sender;
+            stringInit(&sender);
+            stringRead(&sender);
+            int l = stringGetLength(&sender);
+            while(l < 1 || l > 8)
+            {
+                printf("Please type a valid user: ");
+                stringRemove(&sender);
+                stringInit(&sender);
+                stringRead(&sender);
+                l = stringGetLength(&sender);
+            }
+            streamWriteChars(&out, sender.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&sender);
+            
+            // message number
+            int number = readNumber("Type a message number: ");
+            streamWriteInt(&out, number);
+            streamWriteChar(&out, '\n');
+            
+            // send and clear stream
+            clientSendData(&client, &out);
+            streamRemove(&out);
+        }
+        else if(stringCompare(&s, "DEL"))
+        {
+            //outgoing stream
+            Stream out;
+            streamInit(&out, 16);
+            streamWriteInt(&out, 3);
+            
+            // user
+            printf("Type a user with at most 8 characters: ");
+            String sender;
+            stringInit(&sender);
+            stringRead(&sender);
+            int l = stringGetLength(&sender);
+            while(l < 1 || l > 8)
+            {
+                printf("Please type a valid user: ");
+                stringRemove(&sender);
+                stringInit(&sender);
+                stringRead(&sender);
+                l = stringGetLength(&sender);
+            }
+            streamWriteChars(&out, sender.data);
+            streamWriteChar(&out, '\n');
+            stringRemove(&sender);
+            
+            // message number
+            int number = readNumber("Type a message number: ");
+            streamWriteInt(&out, number);
+            streamWriteChar(&out, '\n');
+            
+            // send and clear stream
+            clientSendData(&client, &out);
+            streamRemove(&out);
+        }
+        else if(stringCompare(&s, "QUIT"))
+        {
+            Stream out;
+            streamInit(&out, 16);
+            streamWriteInt(&out, 4);
+            clientSendData(&client, &out);
+            streamRemove(&out);
+        }
+        
+        stringRemove(&s);
+        
+        /*if(type == -1)
+        {
+            break;
+        }
+        else if(type >= 0 && type < 4)
+        {
+            Stream out;
+            streamInit(&out, 16);
+            streamWriteInt(&out, type);
+            
+            switch(type)
+            {
+                case 0:
+                    printf("first number: ");
+                    streamWriteInt(&out, readInt());
+                    printf("second number: ");
+                    streamWriteInt(&out, readInt());
+                    break;
+                case 1:
+                    printf("text: ");
+                    char buffer[128];
+                    fgets(buffer, 128, stdin);
+                    if(strlen(buffer) == 127 && buffer[126] != '\n')
+                    {
+                        clearInput();
+                    }
+                    streamWriteChars(&out, buffer);
+                    break;
+                case 2:
+                    for(int i = 0; i < 260; i++)
+                    {
+                        streamWriteInt(&out, i);
+                    }
+                    break;
+            }
+            
+            if(clientSendData(&client, &out) == -1)
+            {
+                streamRemove(&out);
+                break;
+            }
+            streamRemove(&out);
+        }
+        else
+        {
+            printf("%d is not a valid package number\n", type);
+        }*/
+    }
+}
+
+void packageAnswer(Stream* in)
+{
+    char buffer[32];
+    streamGetChars(in, buffer, 32);
+    printf("%s\n", buffer);
+}
+
+void packageList(Stream* in)
+{
+    int number;
+    if(streamGetInt(in, &number) == -1)
+    {
+        return;
+    }
+    
+    char c;
+    while(streamGetChar(in, &c) != -1)
+    {
+        printf("%c", c);
+    }
+    printf("\n");
+}
+
+int main(int argc, char** argv)
 {
     if(argc < 2)
     {
@@ -31,8 +318,11 @@ int main(int argc, char **argv)
     {
         return EXIT_FAILURE;
     }
+    
+    clientRegisterHandler(&client, packageAnswer);
+    clientRegisterHandler(&client, packageList);
 
-    clientWaitForData(&client);
+    waitForData();
 
     clientRemove(&client);
     return EXIT_SUCCESS;

+ 3 - 2
Makefile

@@ -1,5 +1,6 @@
 FLAGS = -std=c11 -Wall
 SERVER_LINKER = -lpthread
+CLIENT_LINKER = -lpthread
 
 all: server client
 	
@@ -14,8 +15,8 @@ run_server: server
 	./server
 
 
-client: ClientMain.c Client.c Client.h Stream.c Stream.h SocketUtils.c SocketUtils.h
-	gcc $(FLAGS) -o $@ ClientMain.c Client.c Stream.c SocketUtils.c
+client: ClientMain.c Client.c Client.h Stream.c Stream.h SocketUtils.c SocketUtils.h String.c String.h
+	gcc $(FLAGS) -o $@ ClientMain.c Client.c Stream.c SocketUtils.c String.c $(CLIENT_LINKER)
 
 run_client: client
 	./client 127.0.0.1

+ 27 - 14
Server.c

@@ -6,8 +6,9 @@
 #include <string.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <sys/types.h>  
-#include "Stream.h" 
+#include <sys/types.h>
+#define __USE_POSIX199506
+#include <signal.h>  
 #include "SocketUtils.h"
 
 void serverInitDefaults(Server* s)
@@ -21,14 +22,24 @@ void serverInitDefaults(Server* s)
     s->hAmount = -1;
     s->hIndex = -1;
     s->handlers = NULL;
+    
+    s->directory = NULL;
 }
 
-int serverInit(Server* s, int maxClients, short port)
+int serverInit(Server* s, int maxClients, short port, char* directory)
 {
     s->maxClients = maxClients;
     s->port = port;
     s->hAmount = 0;
     s->hIndex = 0;
+    s->directory = directory;
+    
+    if(chdir(directory) == -1)
+    {
+        perror("cannot change directory");
+        serverRemove(s);
+        return -1;
+    }
     
     // initialize storage for clients
     s->threads = malloc(sizeof(pthread_t) * maxClients);
@@ -149,7 +160,7 @@ void serverRemove(Server* s)
     }
 }
 
-void* clientHandler(void* data)
+static void* clientHandler(void* data)
 {
     int id = ((ThreadData*) data)->id;
     Server* s = ((ThreadData*) data)->server;
@@ -161,21 +172,24 @@ void* clientHandler(void* data)
         int size = receiveAll(s->clientSockets[id], &in);
         if(size > 0)
         {
-            char package;
-            if(streamGetChar(&in, &package) == -1)
+            int package;
+            if(streamGetInt(&in, &package) == -1)
             {
-                printf("Invalid package %d from %d\n", (int) package, id);
+                printf("Invalid package %d from %d\n", package, id);
             }
             else
             {
                 if(package >= 0 && package < s->hIndex)
                 {
-                    printf("Received package %d from %d\n", (int) package, id);
-                    s->handlers[(int) package](&in);
+                    printf("Received package %d from %d\n", package, id);
+                    if(s->handlers[package](id, s->clientSockets[id], &in))
+                    {
+                        break;
+                    }
                 }
                 else
                 {
-                    printf("Invalid package %d from %d\n", (int) package, id);
+                    printf("Invalid package %d from %d\n", package, id);
                 }
             }
         }
@@ -212,7 +226,6 @@ int serverSend(int clientSocket, Stream* out)
 {
     if(sendAll(clientSocket, out) == -1)
     {
-        perror("Cannot send data");
         return -1;
     }
     return 0;
@@ -294,19 +307,19 @@ void serverWaitForConnection(Server* s)
     }
 }
 
-void serverRegisterHandler(Server* s, StreamFunction f)
+void serverRegisterHandler(Server* s, ServerStreamFunction f)
 {
     if(s->hAmount == s->hIndex)
     {
         if(s->hAmount == 0)
         {
-            s->handlers = malloc(sizeof(StreamFunction));
+            s->handlers = malloc(sizeof(ServerStreamFunction));
             s->hAmount = 1;
         }
         else
         {
             s->hAmount *= 2;
-            StreamFunction* functions = malloc(sizeof(StreamFunction) * s->hAmount);
+            ServerStreamFunction* functions = malloc(sizeof(ServerStreamFunction) * s->hAmount);
             for(int i = 0; i < s->hIndex; i++)
             {
                 functions[i] = s->handlers[i];

+ 5 - 3
Server.h

@@ -14,7 +14,9 @@ typedef struct Server
     
     int hAmount;
     int hIndex;
-    StreamFunction* handlers;
+    ServerStreamFunction* handlers;
+    
+    char* directory;
 } Server;
 
 typedef struct ThreadData
@@ -24,13 +26,13 @@ typedef struct ThreadData
 } ThreadData;
 
 void serverInitDefaults(Server* s);
-int serverInit(Server* s, int maxClients, short port);
+int serverInit(Server* s, int maxClients, short port, char* directory);
 void serverRemove(Server* s);
 
 int serverSend(int clientSocket, Stream* out); 
 void serverWaitForConnection(Server* s);
 
-void serverRegisterHandler(Server* s, StreamFunction f);
+void serverRegisterHandler(Server* s, ServerStreamFunction f);
 
 #endif
 

+ 636 - 23
ServerMain.c

@@ -2,8 +2,56 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <assert.h>
 #include "Server.h"
 
+int getMailCounter()
+{
+    FILE* test = fopen("mailcounter", "r+");
+    if(test == NULL)
+    {
+        if(creat("mailcounter", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
+        {
+            return 0;
+        }
+        test = fopen("mailcounter", "r+");
+        if(test == NULL)
+        {
+            return 0;
+        }
+    }
+    
+    int counter;
+    if(fread(&counter, sizeof(int), 1, test) == 0)
+    {
+        counter = -1;
+    }
+    counter++;
+    
+    rewind(test);
+    if(fwrite(&counter, sizeof(int), 1, test) == 0)
+    {
+        return 0;
+    }
+    
+    if(fflush(test) == EOF)
+    {
+        return 0;
+    }
+    if(fclose(test) == EOF)
+    {
+        return 0;
+    }
+    
+    return counter;
+}
+
 Server server;
 
 void interruptHandler(int signal)
@@ -12,60 +60,625 @@ void interruptHandler(int signal)
     exit(EXIT_SUCCESS);
 }
 
-void package0(Stream* in)
+void ensureBufferSize(char** data, int* size, int minSize)
+{
+    if(minSize >= *size)
+    {
+        int newSize = *size;
+        while(newSize <= minSize)
+        {
+            newSize *= 2;
+        }
+        
+        printf("Resize from %d to %d\n", *size, newSize);
+        
+        char* newData = malloc(sizeof(char) * newSize);
+        memcpy(newData, *data, *size);
+        
+        *size = newSize;
+        free(*data);
+        *data = newData;
+    }
+}
+
+void packageSendFailAnswer(int clientSocket)
+{
+    Stream out;
+    streamInit(&out, 16);
+    streamWriteInt(&out, 0);
+    streamWriteChars(&out, "ERR\n");
+    serverSend(clientSocket, &out);
+    streamRemove(&out);
+}
+
+int createDirectory(char* path)
+{
+    DIR* dir = opendir(path);
+    if(dir == NULL)
+    {
+        if(mkdir(path, S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
+        {
+            perror("create dir fail");
+            return -1;
+        }
+        dir = opendir(path);
+        if(dir == NULL)
+        {
+            perror("open dir fail");
+            return -1;
+        }
+    }
+    if(closedir(dir))
+    {
+        perror("close dir fail");
+        return -1;
+    }   
+    if(chdir(path) == -1)
+    {
+        perror("change dir fail");
+        return -1;
+    }
+    return 0;
+}
+
+void storeMail(char* sender, char* receiver, char* subject, char* message)
 {
+    printf("sender: %s\n", sender);
+    printf("receiver: %s\n", receiver);
+    printf("subject: %s\n", subject);
+    printf("message: %s\n", message);
+    
+    if(createDirectory(receiver) == -1)
+    {
+        return;
+    }
+    
+    int id = getMailCounter();
+    
+    if(createDirectory(sender) == -1)
+    {
+        return;
+    }
+    
+    char buffer[12];
+    snprintf(buffer, 12, "%d", id);
+    
+    if(createDirectory(buffer) == -1)
+    {
+        return;
+    }
+    
+    if(creat(subject, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
+    {
+        return;
+    }
+    FILE* file = fopen(subject, "w");
+    if(file == NULL)
+    {
+        perror("cant open file");
+        return;
+    }
+    if(fputs(message, file) == EOF)
+    {
+        perror("cant write to file");
+        return;
+    }
+    if(fflush(file) == EOF)
+    {
+        perror("cant flush the file");
+        return;
+    }
+    if(fclose(file) == EOF)
+    {
+        perror("cant close");
+        return;
+    }
+}
+
+int packageSend(int client, int clientSocket, Stream* in)
+{
+    char c;
     int i;
-    if(streamGetInt(in, &i) != -1)
+    const char* error = "invalid SEND package\n";
+    
+    // sender
+    i = 0;
+    char sender[9];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                sender[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 8)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                sender[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(sender) == 0)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    // receiver
+    i = 0;
+    char receiver[9];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                receiver[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 8)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                receiver[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(receiver) == 0)
     {
-        printf("first number: %d\n", i);
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
     }
-    else
+    
+    // subject
+    i = 0;
+    char subject[81];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                subject[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 80)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                subject[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(subject) == 0)
     {
-        printf("first number: ---\n");
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
     }
     
-    if(streamGetInt(in, &i) != -1)
+    // message
+    i = 0;
+    int buffer = 16;
+    char* message = malloc(sizeof(char) * buffer);
+    while(1)
     {
-       printf("second number: %d\n", i);
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                char n1;
+                if(streamGetChar(in, &n1) == -1)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    free(message);
+                    return 0;
+                }
+                char n2;
+                if(streamGetChar(in, &n2) == -1)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    free(message);
+                    return 0;
+                }
+                
+                if(n1 == '.' && n2 == '\n')
+                {
+                    ensureBufferSize(&message, &buffer, i);
+                    message[i] = '\0';
+                    break;
+                }
+                else
+                {
+                    ensureBufferSize(&message, &buffer, i + 2);
+                    message[i] = c;
+                    i++;
+                    message[i] = n1;
+                    i++;
+                    message[i] = n2;
+                    i++;
+                    continue;
+                }
+            }
+            ensureBufferSize(&message, &buffer, i);
+            message[i] = c;
+            i++;
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            free(message);
+            return 0;
+        }
     }
-    else
+    
+    char workingPath[256];
+    if(getcwd(workingPath, 256) != NULL)
     {
-        printf("second number: ---\n");
+        storeMail(sender, receiver, subject, message);
+        assert(chdir(workingPath) == 0);
     }
+            
+    free(message);
+
+    Stream out;
+    streamInit(&out, 16);
+    streamWriteInt(&out, 0);
+    streamWriteChars(&out, "OK\n");
+    serverSend(clientSocket, &out);
+    streamRemove(&out);
+    return 0;
 }
 
-void package1(Stream* in)
+void sendMailList(char* user, Stream* out)
 {
-    char buffer[128];
-    streamGetChars(in, buffer, 128);
-    printf("%s\n", buffer);
+    DIR* dir = opendir(user);
+    if(dir == NULL)
+    {
+        streamWriteInt(out, 0);
+        return;
+    }
+    assert(chdir(user) == 0);
+    
+    int counterPos = streamGetPosition(out);
+    streamWriteInt(out, 0);
+    int counter = 0;
+    
+    struct dirent* pDir = readdir(dir);
+    while(pDir != NULL)
+    {
+        if(strcmp(pDir->d_name, ".") != 0 && strcmp(pDir->d_name, "..") != 0)
+        {
+            DIR* innerdir = opendir(pDir->d_name);
+            if(innerdir != NULL)
+            {
+                assert(chdir(pDir->d_name) == 0);
+                
+                struct dirent* idDir = readdir(innerdir);
+                while(idDir != NULL)
+                {
+                    if(strcmp(idDir->d_name, ".") != 0 && strcmp(idDir->d_name, "..") != 0)
+                    {
+                        counter++;
+                        DIR* innerIdDir = opendir(idDir->d_name);
+                        if(innerIdDir != NULL)
+                        {
+                            struct dirent* mails = readdir(innerIdDir);
+                            while(mails != NULL)
+                            {
+                                if(strcmp(mails->d_name, ".") != 0 && strcmp(mails->d_name, "..") != 0)
+                                {
+                                    streamWriteChars(out, idDir->d_name);
+                                    streamWriteChars(out, " - ");
+                                    streamWriteChars(out, mails->d_name);
+                                    streamWriteChar(out, '\n');
+                                }
+                                mails = readdir(innerIdDir);
+                            }
+                            closedir(innerIdDir);
+                        }
+                    }
+                    idDir = readdir(innerdir);
+                }
+                
+                assert(chdir("../") == 0);
+                closedir(innerdir);
+            }
+        }
+        pDir = readdir(dir);
+    }
+    
+    int current = streamGetPosition(out);
+    streamSetPosition(out, counterPos);
+    streamWriteInt(out, counter);
+    streamSetPosition(out, current);
+    
+    closedir(dir);
+}
+
+int packageList(int client, int clientSocket, Stream* in)
+{
+    char c;
+    int i;
+    const char* error = "invalid LIST package\n";
+    
+    // user
+    i = 0;
+    char user[9];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                user[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 8)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                user[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(user) == 0)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    Stream out;
+    streamInit(&out, 16);
+    streamWriteInt(&out, 1);
+    char workingPath[256];
+    if(getcwd(workingPath, 256) != NULL)
+    {
+        sendMailList(user, &out);
+        assert(chdir(workingPath) == 0);
+    }
+    serverSend(clientSocket, &out);
+    streamRemove(&out);
+    return 0;
+}
+
+int packageRead(int client, int clientSocket, Stream* in)
+{
+    char c;
+    int i;
+    const char* error = "invalid READ package\n";
+    
+    // user
+    i = 0;
+    char user[9];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                user[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 8)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                user[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(user) == 0)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    int number;
+    if(streamGetInt(in, &number) == -1)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    if(streamGetChar(in, &c) == -1)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    else if(c != '\n')
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    printf("user: %s\n", user);
+    printf("number: %d\n", number);
+
+    Stream out;
+    streamInit(&out, 16);
+    streamWriteInt(&out, 0);
+    streamWriteChars(&out, "OK\n");
+    serverSend(clientSocket, &out);
+    streamRemove(&out);
+    
+    return 0;
 }
 
-void package2(Stream* in)
+int packageDelete(int client, int clientSocket, Stream* in)
 {
-    int data;
-    while(streamGetInt(in, &data) != -1)
+    char c;
+    int i;
+    const char* error = "invalid DELETE package\n";
+    
+    // user
+    i = 0;
+    char user[9];
+    while(1)
+    {
+        if(streamGetChar(in, &c) != -1)
+        {
+            if(c == '\n')
+            {
+                user[i] = '\0';
+                break;
+            }
+            else
+            {
+                if(i == 8)
+                {
+                    printf("%s", error);
+                    packageSendFailAnswer(clientSocket);
+                    return 0;
+                }
+                user[i] = c;
+                i++;
+            }
+        }
+        else
+        {
+            printf("%s", error);
+            packageSendFailAnswer(clientSocket);
+            return 0;
+        }
+    }
+    if(strlen(user) == 0)
     {
-        printf("%d ", data);
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
     }
-    printf("\n");
+    
+    int number;
+    if(streamGetInt(in, &number) == -1)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    if(streamGetChar(in, &c) == -1)
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    else if(c != '\n')
+    {
+        printf("%s", error);
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
+    
+    printf("user: %s\n", user);
+    printf("number: %d\n", number);
+
+    Stream out;
+    streamInit(&out, 16);
+    streamWriteInt(&out, 0);
+    streamWriteChars(&out, "OK\n");
+    serverSend(clientSocket, &out);
+    streamRemove(&out);
+    return 0;
+}
+
+int packageQuit(int client, int clientSocket, Stream* in)
+{
+    printf("%d wants to disconnect ...\n", client);
+    return 1;
 }
 
-int main()
+int main(int argc, char** argv)
 {
+    if(argc < 2)
+    {
+        printf("Usage: %s directory\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
     serverInitDefaults(&server);
     
     signal(SIGINT, interruptHandler);
     signal(SIGKILL, interruptHandler);
     
-    if(serverInit(&server, 3, 6543) == -1)
+    if(serverInit(&server, 3, 6543, argv[1]) == -1)
     {
         return EXIT_FAILURE;
     }
     
-    serverRegisterHandler(&server, package0);
-    serverRegisterHandler(&server, package1);
-    serverRegisterHandler(&server, package2);
+    serverRegisterHandler(&server, packageSend);
+    serverRegisterHandler(&server, packageList);
+    serverRegisterHandler(&server, packageRead);
+    serverRegisterHandler(&server, packageDelete);
+    serverRegisterHandler(&server, packageQuit);
     
     serverWaitForConnection(&server);
     

+ 13 - 0
Stream.c

@@ -45,6 +45,19 @@ int streamGetIndex(Stream* s)
     return -1;
 }
 
+int streamGetPosition(Stream* s)
+{
+    return s->index;
+}
+
+void streamSetPosition(Stream* s, int pos)
+{
+    if(pos >= 4 && pos < s->size)
+    {
+        s->index = pos;
+    }
+}
+
 void streamEnsureCapacity(Stream* s, int length)
 {
     if(length >= s->size)

+ 4 - 1
Stream.h

@@ -12,9 +12,12 @@ void streamInit(Stream* s, int size);
 void streamRemove(Stream* s);
 void streamUpdateIndex(Stream* s);
 int streamGetIndex(Stream* s);
+int streamGetPosition(Stream* s);
+void streamSetPosition(Stream* s, int pos);
 void streamEnsureCapacity(Stream* s, int length);
 
-typedef void (*StreamFunction) (Stream*);
+typedef void (*ClientStreamFunction) (Stream*);
+typedef int (*ServerStreamFunction) (int, int, Stream*);
 
 int streamGetChar(Stream* in, char* c);
 int streamGetChars(Stream* in, char* buffer, int length);

+ 62 - 0
String.c

@@ -0,0 +1,62 @@
+#include "String.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void stringInit(String* s)
+{
+    s->length = 0;
+    s->data = NULL;
+}
+
+void stringRemove(String* s)
+{
+    s->length = 0;
+    if(s->data != NULL)
+    {
+        free(s->data);
+        s->data = NULL;
+    }
+}
+
+int stringGetLength(String* s)
+{
+    return s->length;
+}
+
+void stringRead(String* s)
+{
+    int buffer = 16;
+    int index = 0;
+    char* chars = malloc(sizeof(char) * buffer);
+    while(1)
+    {
+        int c = fgetc(stdin);
+        if(c == EOF || c == '\n')
+        {
+            break;
+        }
+        
+        if(index == buffer)
+        {
+            char* newBuffer = malloc(sizeof(char) * buffer * 2);
+            memcpy(newBuffer, chars, buffer);
+            free(chars);
+            chars = newBuffer;
+            buffer *= 2;
+        }
+        chars[index] = c;
+        index++;
+    }
+    
+    s->length = index;
+    s->data = malloc(sizeof(char) * (index + 1));
+    memcpy(s->data, chars, index);
+    free(chars);
+    s->data[index] = '\0';
+}
+
+int stringCompare(String* s, const char* chars)
+{
+    return strcmp(s->data, chars) == 0;
+}

+ 19 - 0
String.h

@@ -0,0 +1,19 @@
+#ifndef STRING_H
+#define STRING_H
+
+typedef struct String
+{
+    int length;
+    char* data;
+} String;
+
+void stringInit(String* s);
+void stringRemove(String* s);
+
+int stringGetLength(String* s);
+
+void stringRead(String* s);
+int stringCompare(String* s, const char* chars);
+
+#endif
+

+ 1 - 0
mails/Wusler/Gusi/0/gdfgdf

@@ -0,0 +1 @@
+gfdhfghfghhfgg

+ 1 - 0
mails/Wusler/Wusi/1/ddddd

@@ -0,0 +1 @@
+bbbbbbbbbbb

BIN
mails/Wusler/mailcounter


+ 1 - 0
mails/b/a/0/c

@@ -0,0 +1 @@
+d

+ 1 - 0
mails/b/a/1/c

@@ -0,0 +1 @@
+wusi

+ 1 - 0
mails/b/a/2/c

@@ -0,0 +1 @@
+dgdfg

+ 1 - 0
mails/b/b/3/fdfg

@@ -0,0 +1 @@
+dfgdfg

+ 1 - 0
mails/b/b/4/sgdh

@@ -0,0 +1 @@
+dfgdf

BIN
mails/b/mailcounter


BIN
mails/heinz/mailcounter


+ 1 - 0
mails/heinz/wusler/0/Hallo Heinz

@@ -0,0 +1 @@
+Hallo Heinz wie geht es dir?