Browse Source

protocol completely changed to fit the specification, clean up, multiline messages

Kajetan Johannes Hammerle 5 years ago
parent
commit
84c87248e0
22 changed files with 347 additions and 635 deletions
  1. 4 50
      Client.c
  2. 1 3
      Client.h
  3. 35 96
      ClientMain.c
  4. 2 2
      Makefile
  5. 5 51
      Server.c
  6. 1 3
      Server.h
  7. 203 299
      ServerMain.c
  8. 22 25
      SocketUtils.c
  9. 29 93
      Stream.c
  10. 5 9
      Stream.h
  11. 18 0
      String.c
  12. 5 0
      String.h
  13. 0 2
      mails/b/b/10
  14. 5 0
      mails/b/b/11
  15. 0 2
      mails/b/b/6
  16. BIN
      mails/b/mailcounter
  17. 3 0
      mails/dfg/a/1
  18. BIN
      mails/dfg/mailcounter
  19. 3 0
      mails/dfg/s/0
  20. 3 0
      mails/gdf/a/0
  21. BIN
      mails/gdf/mailcounter
  22. 3 0
      todo

+ 4 - 50
Client.c

@@ -20,9 +20,7 @@ void clientInitDefaults(Client* c)
     
     c->thread = -1;
     
-    c->hAmount = -1;
-    c->hIndex = -1;
-    c->handlers = NULL;
+    c->handler = NULL;
 }
 
 static void* serverHandler(void* data)
@@ -36,23 +34,7 @@ static void* serverHandler(void* data)
         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);
-                }
-            }
+            c->handler(&in);
         }
         else if(size == 0)
         {
@@ -76,8 +58,6 @@ static void* serverHandler(void* data)
 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)
@@ -191,13 +171,7 @@ void clientRemove(Client* c)
         c->thread = -1;
     }
     
-    c->hAmount = -1;
-    c->hIndex = -1;
-    if(c->handlers != NULL)
-    {
-        free(c->handlers);
-        c->handlers = NULL;
-    }
+    c->handler = NULL;
 }
 
 int clientSendData(Client* c, Stream* out)
@@ -213,25 +187,5 @@ int clientSendData(Client* c, Stream* out)
 
 void clientRegisterHandler(Client* c, ClientStreamFunction f)
 {
-    if(c->hAmount == c->hIndex)
-    {
-        if(c->hAmount == 0)
-        {
-            c->handlers = malloc(sizeof(ClientStreamFunction));
-            c->hAmount = 1;
-        }
-        else
-        {
-            c->hAmount *= 2;
-            ClientStreamFunction* functions = malloc(sizeof(ClientStreamFunction) * c->hAmount);
-            for(int i = 0; i < c->hIndex; i++)
-            {
-                functions[i] = c->handlers[i];
-            }
-            free(c->handlers);
-            c->handlers = functions;
-        }
-    }
-    c->handlers[c->hIndex] = f;
-    c->hIndex++;
+    c->handler = f;
 }

+ 1 - 3
Client.h

@@ -11,9 +11,7 @@ typedef struct Client
     
     pthread_t thread;
     
-    int hAmount;
-    int hIndex;
-    ClientStreamFunction* handlers;
+    ClientStreamFunction handler;
 } Client;
 
 void clientInitDefaults(Client* c);

+ 35 - 96
ClientMain.c

@@ -14,39 +14,24 @@ void interruptHandler(int signal)
     exit(EXIT_SUCCESS);
 }
 
-int isSpecialFolder(char* folder)
+void writeMessageNumber(Stream* out)
 {
-    return strcmp(folder, ".") == 0 || strcmp(folder, "..") == 0;
-}
-
-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;
+    String number;
+    stringInit(&number);
+    printf("Type a message identifier: ");
+    stringRead(&number);
+    streamWriteChars(out, number.data);
+    streamWriteChar(out, '\n');
+    stringRemove(&number);
 }
 
 void waitForData()
 {
+    String s;
+    stringInit(&s);
     while(1)
     {
         printf("Type a command:\n");
-        String s;
-        stringInit(&s);
         stringRead(&s);
         
         if(stringCompareNoCase(&s, "SEND"))
@@ -56,7 +41,7 @@ void waitForData()
             //outgoing stream
             Stream out;
             streamInit(&out, 128);
-            streamWriteInt(&out, 0);
+            streamWriteChars(&out, "SEND\n");
             
             // receiver
             printf("Type a receiver with at most 8 characters: ");
@@ -64,11 +49,9 @@ void waitForData()
             stringInit(&receiver);
             stringRead(&receiver);
             int l = stringGetLength(&receiver);
-            while(l < 1 || l > 8 || isSpecialFolder(receiver.data))
+            while(l < 1 || l > 8 || stringCompare(&receiver, ".") || stringCompare(&receiver, ".."))
             {
                 printf("Please type a valid receiver: ");
-                stringRemove(&receiver);
-                stringInit(&receiver);
                 stringRead(&receiver);
                 l = stringGetLength(&receiver);
             }
@@ -85,8 +68,6 @@ void waitForData()
             while(l < 1 || l > 80)
             {
                 printf("Please type a valid subject: ");
-                stringRemove(&subject);
-                stringInit(&subject);
                 stringRead(&subject);
                 l = stringGetLength(&subject);
             }
@@ -95,12 +76,20 @@ void waitForData()
             stringRemove(&subject);
             
             // message
-            printf("Type a message: ");
             String message;
             stringInit(&message);
-            stringRead(&message);
-            streamWriteChars(&out, message.data);
-            streamWriteChars(&out, "\n.\n");
+            while(1)
+            {
+                printf("Type a message: ");
+                stringRead(&message);
+                if(stringCompare(&message, "."))
+                {
+                    streamWriteChars(&out, ".\n");
+                    break;
+                }
+                streamWriteChars(&out, message.data);
+                streamWriteChar(&out, '\n');
+            }
             stringRemove(&message);
             
             // send and clear stream
@@ -112,7 +101,7 @@ void waitForData()
             //outgoing stream
             Stream out;
             streamInit(&out, 16);
-            streamWriteInt(&out, 1);
+            streamWriteChars(&out, "LIST\n");
             
             // send and clear stream
             clientSendData(&client, &out);
@@ -123,12 +112,10 @@ void waitForData()
             //outgoing stream
             Stream out;
             streamInit(&out, 16);
-            streamWriteInt(&out, 2);
+            streamWriteChars(&out, "READ\n");
             
             // message number
-            int number = readNumber("Type a message number: ");
-            streamWriteInt(&out, number);
-            streamWriteChar(&out, '\n');
+            writeMessageNumber(&out);
             
             // send and clear stream
             clientSendData(&client, &out);
@@ -139,12 +126,10 @@ void waitForData()
             //outgoing stream
             Stream out;
             streamInit(&out, 16);
-            streamWriteInt(&out, 3);
+            streamWriteChars(&out, "DEL\n");
             
             // message number
-            int number = readNumber("Type a message number: ");
-            streamWriteInt(&out, number);
-            streamWriteChar(&out, '\n');
+            writeMessageNumber(&out);
             
             // send and clear stream
             clientSendData(&client, &out);
@@ -152,11 +137,7 @@ void waitForData()
         }
         else if(stringCompareNoCase(&s, "QUIT"))
         {
-            Stream out;
-            streamInit(&out, 16);
-            streamWriteInt(&out, 4);
-            clientSendData(&client, &out);
-            streamRemove(&out);
+            break;
         }
         else if(stringCompareNoCase(&s, "HELP"))
         {
@@ -165,14 +146,14 @@ void waitForData()
             printf("- LIST: shows all your mails\n");
             printf("- READ: read a mail\n");
             printf("- DEL: delete a mail\n");
-            printf("- QUIT: disconnects your from the server\n");
+            printf("- QUIT: close this program\n");
         }
         else if(stringCompareNoCase(&s, "LOGIN"))
         {
             //outgoing stream
             Stream out;
             streamInit(&out, 16);
-            streamWriteInt(&out, 5);
+            streamWriteChars(&out, "LOGIN\n");
             
             // user
             printf("Type a user with at most 8 characters: ");
@@ -183,8 +164,6 @@ void waitForData()
             while(l < 1 || l > 8)
             {
                 printf("Please type a valid user: ");
-                stringRemove(&sender);
-                stringInit(&sender);
                 stringRead(&sender);
                 l = stringGetLength(&sender);
             }
@@ -201,8 +180,6 @@ void waitForData()
             while(l == 0)
             {
                 printf("Please type a valid password: ");
-                stringRemove(&password);
-                stringInit(&password);
                 stringRead(&password);
                 l = stringGetLength(&password);
             }
@@ -214,47 +191,11 @@ void waitForData()
             clientSendData(&client, &out);
             streamRemove(&out);
         }
-        
-        stringRemove(&s);
-    }
-}
-
-void packageAnswer(Stream* in)
-{
-    char buffer[32];
-    streamGetChars(in, buffer, 32);
-    printf("%s\n", buffer);
-    
-    printf("Type a command:\n");
-}
-
-void packageList(Stream* in)
-{
-    int number;
-    if(streamGetInt(in, &number) == -1)
-    {
-        return;
-    }
-    if(number == 1)
-    {
-        printf("\nYou have %d mail.\n", number);
     }
-    else
-    {
-        printf("\nYou have %d mails.\n", number);
-    }
-    
-    char c;
-    while(streamGetChar(in, &c) != -1)
-    {
-        fputc(c, stdout);
-    }
-    fputc('\n', stdout);
-    
-    printf("Type a command: \n");
+    stringRemove(&s);
 }
 
-void packageReadDel(Stream* in)
+void package(Stream* in)
 {
     char c;
     while(streamGetChar(in, &c) != -1)
@@ -291,9 +232,7 @@ int main(int argc, char** argv)
         return EXIT_FAILURE;
     }
     
-    clientRegisterHandler(&client, packageAnswer);
-    clientRegisterHandler(&client, packageList);
-    clientRegisterHandler(&client, packageReadDel);
+    clientRegisterHandler(&client, package);
 
     waitForData();
 

+ 2 - 2
Makefile

@@ -8,8 +8,8 @@ run_all: all
 	./server
 	./client 127.0.0.1
 
-server: ServerMain.c Server.c Server.h Stream.c Stream.h SocketUtils.c SocketUtils.h
-	gcc $(FLAGS) -o $@ ServerMain.c Server.c Stream.c SocketUtils.c $(SERVER_LINKER)
+server: ServerMain.c Server.c Server.h Stream.c Stream.h SocketUtils.c SocketUtils.h String.c String.h
+	gcc $(FLAGS) -o $@ ServerMain.c Server.c Stream.c SocketUtils.c String.c $(SERVER_LINKER)
 
 run_server: server
 	./server

+ 5 - 51
Server.c

@@ -19,9 +19,7 @@ void serverInitDefaults(Server* s)
     s->clientUser = NULL;
     s->connectSocket = -1;
     
-    s->hAmount = -1;
-    s->hIndex = -1;
-    s->handlers = NULL;
+    s->handler = NULL;
     
     s->directory = NULL;
 }
@@ -30,8 +28,6 @@ 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)
@@ -167,13 +163,7 @@ void serverRemove(Server* s)
         s->connectSocket = -1;
     }
     
-    s->hAmount = -1;
-    s->hIndex = -1;
-    if(s->handlers != NULL)
-    {
-        free(s->handlers);
-        s->handlers = NULL;
-    }
+    s->handler = NULL;
 }
 
 static void* clientHandler(void* data)
@@ -188,25 +178,9 @@ static void* clientHandler(void* data)
         int size = receiveAll(s->clientSockets[id], &in);
         if(size > 0)
         {
-            int package;
-            if(streamGetInt(&in, &package) == -1)
+            if(s->handler(id, s->clientSockets[id], &in))
             {
-                printf("Invalid package %d from %d\n", package, id);
-            }
-            else
-            {
-                if(package >= 0 && package < s->hIndex)
-                {
-                    //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", package, id);
-                }
+                break;
             }
         }
         else if(size == 0)
@@ -332,27 +306,7 @@ void serverWaitForConnection(Server* s)
 
 void serverRegisterHandler(Server* s, ServerStreamFunction f)
 {
-    if(s->hAmount == s->hIndex)
-    {
-        if(s->hAmount == 0)
-        {
-            s->handlers = malloc(sizeof(ServerStreamFunction));
-            s->hAmount = 1;
-        }
-        else
-        {
-            s->hAmount *= 2;
-            ServerStreamFunction* functions = malloc(sizeof(ServerStreamFunction) * s->hAmount);
-            for(int i = 0; i < s->hIndex; i++)
-            {
-                functions[i] = s->handlers[i];
-            }
-            free(s->handlers);
-            s->handlers = functions;
-        }
-    }
-    s->handlers[s->hIndex] = f;
-    s->hIndex++;
+    s->handler = f;
 }
 
 int serverSetUser(Server* s, int clientId, char* name)

+ 1 - 3
Server.h

@@ -13,9 +13,7 @@ typedef struct Server
     char** clientUser;
     int connectSocket;
     
-    int hAmount;
-    int hIndex;
-    ServerStreamFunction* handlers;
+    ServerStreamFunction handler;
     
     char* directory;
 } Server;

+ 203 - 299
ServerMain.c

@@ -12,11 +12,12 @@
 #include <dirent.h>
 #include <assert.h>
 #include "Server.h"
+#include "String.h"
+#include <string.h>
 
 int getMailCounter()
 {
     FILE* test = fopen("mailcounter", "r+");
-    flock(fileno(test), LOCK_EX);
     if(test == NULL)
     {
         if(creat("mailcounter", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
@@ -29,6 +30,7 @@ int getMailCounter()
             return 0;
         }
     }
+    flock(fileno(test), LOCK_EX);
     
     int counter;
     if(fread(&counter, sizeof(int), 1, test) == 0)
@@ -69,18 +71,16 @@ void interruptHandler(int signal)
     exit(EXIT_SUCCESS);
 }
 
-void ensureBufferSize(char** data, int* size, int minSize)
+void ensureBufferIndex(char** data, int* size, int index)
 {
-    if(minSize >= *size)
+    if(index >= *size)
     {
         int newSize = *size;
-        while(newSize <= minSize)
+        while(newSize <= index)
         {
             newSize *= 2;
         }
         
-        //printf("Resize from %d to %d\n", *size, newSize);
-        
         char* newData = malloc(sizeof(char) * newSize);
         memcpy(newData, *data, *size);
         
@@ -94,7 +94,6 @@ void packageSendFailAnswer(int clientSocket)
 {
     Stream out;
     streamInit(&out, 16);
-    streamWriteInt(&out, 0);
     streamWriteChars(&out, "ERR\n");
     serverSend(clientSocket, &out);
     streamRemove(&out);
@@ -104,7 +103,6 @@ void packageSendOkAnswer(int clientSocket)
 {
     Stream out;
     streamInit(&out, 16);
-    streamWriteInt(&out, 0);
     streamWriteChars(&out, "OK\n");
     serverSend(clientSocket, &out);
     streamRemove(&out);
@@ -142,11 +140,6 @@ int createDirectory(char* path)
 
 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;
@@ -165,7 +158,7 @@ void storeMail(char* sender, char* receiver, char* subject, char* message)
     if(creat(buffer, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
     {
         return;
-    }
+    }   
     
     FILE* file = fopen(buffer, "w");
     if(file == NULL)
@@ -173,6 +166,26 @@ void storeMail(char* sender, char* receiver, char* subject, char* message)
         perror("cant open file");
         return;
     }
+    if(fputs(sender, file) == EOF)
+    {
+        perror("cant write to file");
+        return;
+    }
+    if(fputc('\n', file) == EOF)
+    {
+        perror("cant write to file");
+        return;
+    }
+    if(fputs(receiver, file) == EOF)
+    {
+        perror("cant write to file");
+        return;
+    }
+    if(fputc('\n', file) == EOF)
+    {
+        perror("cant write to file");
+        return;
+    }
     if(fputs(subject, file) == EOF)
     {
         perror("cant write to file");
@@ -209,151 +222,65 @@ int packageSend(int client, int clientSocket, Stream* in)
         return 0;
     }
     
-    char c;
-    int i;
-    const char* error = "invalid SEND package\n";
-      
+    int length;
+    
     // receiver
-    i = 0;
-    char receiver[9];
-    while(1)
+    String receiver;
+    stringInit(&receiver);
+    stringReadStreamLine(&receiver, in);
+    length = stringGetLength(&receiver);
+    if(length == 0 || length > 8)
     {
-        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 || isSpecialFolder(receiver))
-    {
-        printf("%s", error);
         packageSendFailAnswer(clientSocket);
+        stringRemove(&receiver);
         return 0;
     }
     
     // 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)
+    String subject;
+    stringInit(&subject);
+    stringReadStreamLine(&subject, in);
+    length = stringGetLength(&subject);
+    if(length == 0 || length > 80)
     {
-        printf("%s", error);
         packageSendFailAnswer(clientSocket);
+        stringRemove(&subject);
         return 0;
     }
     
     // message
-    i = 0;
+    int index = 0;
     int buffer = 16;
     char* message = malloc(sizeof(char) * buffer);
-    while(1)
+    
+    String sMessage;
+    stringInit(&sMessage);
+    while(streamHasData(in))
     {
-        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
+        stringReadStreamLine(&sMessage, in);
+        if(stringCompare(&sMessage, ".") || buffer > 60)
         {
-            printf("%s", error);
-            packageSendFailAnswer(clientSocket);
-            free(message);
-            return 0;
+            break;
         }
+        int length = stringGetLength(&sMessage);
+        // "i + length" is one too much but right for "length + \n"
+        ensureBufferIndex(&message, &buffer, index + length);
+        memcpy(message + index, sMessage.data, length);
+        index += length;
+        message[index] = '\n';
+        index++;
     }
+    stringRemove(&sMessage);
     
     char workingPath[256];
     if(getcwd(workingPath, 256) != NULL)
     {
-        storeMail(user, receiver, subject, message);
+        storeMail(user, receiver.data, subject.data, message);
         assert(chdir(workingPath) == 0);
     }
             
+    stringRemove(&receiver);
+    stringRemove(&subject);
     free(message);
 
     packageSendOkAnswer(clientSocket);
@@ -365,15 +292,13 @@ void sendMailList(char* user, Stream* out)
     DIR* receiverDir = opendir(user);
     if(receiverDir == NULL)
     {
-        streamWriteInt(out, 0);
+        streamWriteChars(out, "0\n");
         return;
     }
     assert(chdir(user) == 0);
     
-    int counterPos = streamGetPosition(out);
-    streamWriteInt(out, 0);
+    // count mails first, this is easier than buffering everything else
     int counter = 0;
-    
     struct dirent* receiverIterator = readdir(receiverDir);
     while(receiverIterator != NULL)
     {
@@ -391,32 +316,80 @@ void sendMailList(char* user, Stream* out)
                     {
                         // mails found
                         counter++;
+                    }
+                    senderIterator = readdir(senderDir);
+                }
+                
+                assert(chdir("../") == 0);
+                closedir(senderDir);
+            }
+        }
+        receiverIterator = readdir(receiverDir);
+    }
+    
+    // write the number of mails
+    char buffer[12];
+    snprintf(buffer, 12, "%d", counter);
+    streamWriteChars(out, buffer);
+    streamWriteChar(out, '\n');
+    
+    // add the mail subjects
+    assert(chdir("../") == 0);
+    closedir(receiverDir);
+    receiverDir = opendir(user);
+    if(receiverDir == NULL)
+    {
+        return;
+    }
+    assert(chdir(user) == 0);
+    
+    receiverIterator = readdir(receiverDir);
+    while(receiverIterator != NULL)
+    {
+        if(!isSpecialFolder(receiverIterator->d_name))
+        {
+            DIR* senderDir = opendir(receiverIterator->d_name);
+            if(senderDir != NULL)
+            {
+                assert(chdir(receiverIterator->d_name) == 0);
+                
+                struct dirent* senderIterator = readdir(senderDir);
+                while(senderIterator != NULL)
+                {
+                    if(!isSpecialFolder(senderIterator->d_name))
+                    {
                         // reading subject from first line
                         FILE* file = fopen(senderIterator->d_name, "r");
                         if(file != NULL)
                         {
-                            int size = 16;
-                            int pos = 0;
-                            char* buffer = malloc(sizeof(char) * size);
+                            streamWriteChars(out, senderIterator->d_name);
+                            streamWriteChars(out, " - ");
+                            
+                            //skip first 2 lines (receiver, sender)
+                            int skip = 0;
                             int data;
                             while(1)
                             {
                                 data = fgetc(file);
                                 if(data == '\n' || data == EOF)
                                 {
-                                    ensureBufferSize(&buffer, &size, pos);
-                                    buffer[pos] = '\0';
-                                    break;
+                                    skip++;
+                                    if(skip == 2)
+                                    {
+                                        break;
+                                    }
                                 }
-                                ensureBufferSize(&buffer, &size, pos);
-                                buffer[pos] = data;
-                                pos++;
                             }
                             
-                            streamWriteChars(out, senderIterator->d_name);
-                            streamWriteChars(out, " - ");
-                            streamWriteChars(out, buffer);
-                            free(buffer);
+                            while(1)
+                            {
+                                data = fgetc(file);
+                                if(data == '\n' || data == EOF)
+                                {
+                                    break;
+                                }
+                                streamWriteChar(out, data);
+                            }
                             streamWriteChar(out, '\n');                           
                             
                             if(fclose(file) == EOF)
@@ -438,12 +411,7 @@ void sendMailList(char* user, Stream* out)
         }
         receiverIterator = readdir(receiverDir);
     }
-    
-    int current = streamGetPosition(out);
-    streamSetPosition(out, counterPos);
-    streamWriteInt(out, counter);
-    streamSetPosition(out, current);
-    
+
     closedir(receiverDir);
 }
 
@@ -458,7 +426,6 @@ int packageList(int client, int clientSocket, Stream* in)
     
     Stream out;
     streamInit(&out, 16);
-    streamWriteInt(&out, 1);
     char workingPath[256];
     if(getcwd(workingPath, 256) != NULL)
     {
@@ -470,7 +437,7 @@ int packageList(int client, int clientSocket, Stream* in)
     return 0;
 }
 
-void readMail(char* user, int number, Stream* out)
+void readMail(char* user, char* number, Stream* out)
 {
     DIR* receiverDir = opendir(user);
     if(receiverDir == NULL)
@@ -480,9 +447,6 @@ void readMail(char* user, int number, Stream* out)
     }
     assert(chdir(user) == 0);
     
-    char buffer[12];
-    snprintf(buffer, 12, "%d", number);
-    
     struct dirent* receiverIterator;
     receiverIterator = readdir(receiverDir);
     while(receiverIterator != NULL)
@@ -491,20 +455,12 @@ void readMail(char* user, int number, Stream* out)
         {
             if(chdir(receiverIterator->d_name) == 0)
             {
-                FILE* file = fopen(buffer, "r");
+                FILE* file = fopen(number, "r");
                 if(file != NULL)
                 {
-                    // skip subject heading
-                    int data;
-                    while(1)
-                    {
-                        data = fgetc(file);
-                        if(data == '\n' || data == EOF)
-                        {
-                            break;
-                        }
-                    }
+                    streamWriteChars(out, "OK\n");
                     // write data to stream
+                    int data;
                     while(1)
                     {
                         data = fgetc(file);
@@ -548,50 +504,36 @@ int packageRead(int client, int clientSocket, Stream* in)
         return 0;
     }
     
-    char c;
-    const char* error = "invalid READ package\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')
+    // number
+    String number;
+    stringInit(&number);
+    stringReadStreamLine(&number, in);
+    if(stringGetLength(&number) == 0)
     {
-        printf("%s", error);
         packageSendFailAnswer(clientSocket);
+        stringRemove(&number);
         return 0;
     }
     
     Stream out;
     streamInit(&out, 16);
-    streamWriteInt(&out, 2);
     char workingPath[256];
     if(getcwd(workingPath, 256) != NULL)
     {
-        readMail(user, number, &out);
+        readMail(user, number.data, &out);
         assert(chdir(workingPath) == 0);
     }
     else
     {
         streamWriteChars(&out, "ERR\n");
     }
+    stringRemove(&number);
     serverSend(clientSocket, &out);
     streamRemove(&out);
-    
     return 0;
 }
 
-int deleteMail(char* user, int number)
+int deleteMail(char* user, char* number)
 {
     DIR* receiverDir = opendir(user);
     if(receiverDir == NULL)
@@ -600,9 +542,6 @@ int deleteMail(char* user, int number)
     }
     assert(chdir(user) == 0);
     
-    char buffer[12];
-    snprintf(buffer, 12, "%d", number);
-    
     int rValue = 0;
     
     struct dirent* receiverIterator;
@@ -613,7 +552,7 @@ int deleteMail(char* user, int number)
         {
             if(chdir(receiverIterator->d_name) == 0)
             {
-                if(remove(buffer) == 0)
+                if(remove(number) == 0)
                 {
                     rValue = 1;
                     break;
@@ -640,37 +579,23 @@ int packageDelete(int client, int clientSocket, Stream* in)
         return 0;
     }
     
-    char c;
-    const char* error = "invalid DELETE package\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')
+    // number
+    String number;
+    stringInit(&number);
+    stringReadStreamLine(&number, in);
+    if(stringGetLength(&number) == 0)
     {
-        printf("%s", error);
         packageSendFailAnswer(clientSocket);
+        stringRemove(&number);
         return 0;
     }
     
     Stream out;
     streamInit(&out, 16);
-    streamWriteInt(&out, 2);
     char workingPath[256];
     if(getcwd(workingPath, 256) != NULL)
     {
-        if(deleteMail(user, number))
+        if(deleteMail(user, number.data))
         {
             streamWriteChars(&out, "OK\n");
         }
@@ -684,101 +609,85 @@ int packageDelete(int client, int clientSocket, Stream* in)
     {
         streamWriteChars(&out, "ERR\n");
     }
+    stringRemove(&number);
     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 packageLogin(int client, int clientSocket, Stream* in)
 {
-    printf("%d wants to login ...\n", client);
-    
-    char c;
-    int i;
-    const char* error = "invalid DELETE package\n";
+    int length;
     
-    // 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)
+    // receiver
+    String user;
+    stringInit(&user);
+    stringReadStreamLine(&user, in);
+    length = stringGetLength(&user);
+    if(length == 0 || length > 8)
     {
-        printf("%s", error);
         packageSendFailAnswer(clientSocket);
+        stringRemove(&user);
         return 0;
     }
     
     // password
-    i = 0;
-    int buffer = 16;
-    char* password = malloc(sizeof(char) * buffer);
-    while(1)
-    {
-        if(streamGetChar(in, &c) != -1)
-        {
-            if(c == '\n')
-            {
-                ensureBufferSize(&password, &buffer, i);
-                password[i] = '\0';
-                break;
-            }
-            ensureBufferSize(&password, &buffer, i);
-            password[i] = c;
-            i++;
-        }
-        else
-        {
-            printf("%s", error);
-            packageSendFailAnswer(clientSocket);
-            free(password);
-            return 0;
-        }
-    }
+    String password;
+    stringInit(&password);
+    stringReadStreamLine(&password, in);
     
-    printf("%s %s\n", user, password);
+    printf("%s %s\n", user.data, password.data);
     // insert LDAP check here
     
-    if(serverSetUser(&server, client, user))
+    stringRemove(&password);
+    
+    if(serverSetUser(&server, client, user.data))
     {
         packageSendFailAnswer(clientSocket);
-        free(password);
+        stringRemove(&user);
         return 0;
     }
-    free(password);
     packageSendOkAnswer(clientSocket);
+    stringRemove(&user);
+    return 0;
+}
+
+int package(int client, int clientSocket, Stream* in)
+{
+    if(streamHasData(in))
+    {
+        String s;
+        stringInit(&s);
+        stringReadStreamLine(&s, in);
+        int r = 0;
+        if(stringCompare(&s, "SEND"))
+        {
+            r = packageSend(client, clientSocket, in);
+        }
+        else if(stringCompare(&s, "LIST"))
+        {
+            r = packageList(client, clientSocket, in);
+        }
+        else if(stringCompare(&s, "READ"))
+        {
+            r = packageRead(client, clientSocket, in);
+        }
+        else if(stringCompare(&s, "DEL"))
+        {
+            r = packageDelete(client, clientSocket, in);
+        }
+        else if(stringCompare(&s, "LOGIN"))
+        {
+            r = packageLogin(client, clientSocket, in);
+        }
+        else
+        {
+            printf("Invalid package from %d\n", client);
+            r = 1;
+        }
+        stringRemove(&s);
+        return r;
+    }
     return 0;
 }
 
@@ -807,12 +716,7 @@ int main(int argc, char** argv)
         return EXIT_FAILURE;
     }
     
-    serverRegisterHandler(&server, packageSend);
-    serverRegisterHandler(&server, packageList);
-    serverRegisterHandler(&server, packageRead);
-    serverRegisterHandler(&server, packageDelete);
-    serverRegisterHandler(&server, packageQuit);
-    serverRegisterHandler(&server, packageLogin);
+    serverRegisterHandler(&server, package);
     
     serverWaitForConnection(&server);
     

+ 22 - 25
SocketUtils.c

@@ -8,7 +8,6 @@ int sendAll(int socket, Stream* out)
 {
     char* data = out->data;
     int left = out->index;
-    streamUpdateIndex(out);
     while(left > 0)
     {
         int bytes = send(socket, data, left, MSG_NOSIGNAL);
@@ -25,40 +24,38 @@ int sendAll(int socket, Stream* out)
 
 int receiveAll(int socket, Stream* in)
 {   
-    int size = recv(socket, in->data, in->size, 0);
+    int pos = in->index;
+    int capacity = in->capacity - pos;
+    int size = recv(socket, in->data + pos, capacity, 0);
     if(size > 0)
     {
-        int dataLength = streamGetIndex(in);
-        if(size == dataLength)
+        in->size = pos + size;
+        if(size < capacity)
         {
-            in->size = dataLength;
-            return dataLength;
+            return size;
         }
-        streamEnsureCapacity(in, dataLength);
-        in->size = dataLength;
-        
-        char* data = in->data + size;
-        int left = dataLength - size;
-        while(left > 0)
+        while(size == capacity)
         {
-            size = recv(socket, data, left, 0);
-            if(size > 0)
+            // more data must be read
+            streamEnsureIndex(in, in->capacity * 2 - 1);
+            
+            pos += size;
+            capacity = in->capacity - pos;
+
+            size = recv(socket, in->data + pos, capacity, MSG_DONTWAIT);
+            if(size <= 0)
             {
-                data += size;
-                left -= size;
+                size = 0;
+                break;
             }
-            else if(size == 0)
-            {
-                printf("Remote Socket closed\n");
-                return -1;
-            }   
-            else
+            in->size += size;
+            if(size < capacity)
             {
-                perror("recv error");
-                return -1;
+                break;
             }
         }
-        return dataLength;
+        pos += size;
+        return pos - in->index;
     }
     else if(size == 0)
     {

+ 29 - 93
Stream.c

@@ -5,14 +5,16 @@
 
 void streamInit(Stream* s, int size)
 {
-    s->index = 4;
-    s->size = size;
+    s->index = 0;
+    s->size = 0;
     if(size > 0)
     {
+        s->capacity = size;
         s->data = malloc(sizeof(char) * size);
     }
     else
     {
+        s->capacity = 0;
         s->data = NULL;
     }
 }
@@ -21,48 +23,16 @@ void streamRemove(Stream* s)
 {
     s->index = 0;
     s->size = 0;
+    s->capacity = 0;
     free(s->data);
     s->data = NULL;
 }
 
-void streamUpdateIndex(Stream* s)
-{
-    if(s->size >= 4)
-    {
-        s->data[0] = s->index & 0xFF;
-        s->data[1] = (s->index >> 8) & 0xFF;
-        s->data[2] = (s->index >> 16) & 0xFF;
-        s->data[3] = (s->index >> 24) & 0xFF;
-    }    
-}
-
-int streamGetIndex(Stream* s)
-{
-    if(s->size >= 4)
-    {
-        return (s->data[0] & 0xFF) | ((s->data[1] & 0xFF) << 8) | ((s->data[2] & 0xFF) << 16) | ((s->data[3] & 0xFF) << 24);
-    }
-    return -1;
-}
-
-int streamGetPosition(Stream* s)
-{
-    return s->index;
-}
-
-void streamSetPosition(Stream* s, int pos)
+void streamEnsureIndex(Stream* s, int length)
 {
-    if(pos >= 4 && pos < s->size)
+    if(length >= s->capacity)
     {
-        s->index = pos;
-    }
-}
-
-void streamEnsureCapacity(Stream* s, int length)
-{
-    if(length >= s->size)
-    {
-        int newSize = s->size;
+        int newSize = s->capacity;
         if(newSize >= 0)
         {
             newSize = 1;
@@ -75,9 +45,25 @@ void streamEnsureCapacity(Stream* s, int length)
         memcpy(newData, s->data, s->size);
         free(s->data);
         s->data = newData;
-        //printf("RESIZE FROM %d to %d\n", s->size, newSize);
-        s->size = newSize;
+        s->capacity = newSize;
+    }
+}
+
+int streamSeekNewLine(Stream* in)
+{
+    for(int i = in->index; i < in->size; i++)
+    {
+        if(in->data[i] == '\n')
+        {
+            return i - in->index;
+        }
     }
+    return in->size - in->index;
+}
+
+int streamHasData(Stream* in)
+{
+    return in->index < in->size;
 }
 
 int streamGetChar(Stream* in, char* c)
@@ -113,36 +99,14 @@ int streamGetChars(Stream* in, char* buffer, int length)
     return index;
 }
 
-int streamGetShort(Stream* in, short* s)
-{
-    if(in->index + 1 < in->size)
-    {
-        *s = (in->data[in->index] & 0xFF) | ((in->data[in->index + 1] & 0xFF) << 8);
-        in->index += 2;
-        return 0;
-    }
-    return -1;
-}
-
-int streamGetInt(Stream* in, int* i)
-{
-    if(in->index + 3 < in->size)
-    {
-        *i = (in->data[in->index] & 0xFF) | ((in->data[in->index + 1] & 0xFF) << 8) | 
-                ((in->data[in->index + 2] & 0xFF) << 16) | ((in->data[in->index + 3] & 0xFF) << 24);
-        in->index += 4;
-        return 0;
-    }
-    return -1;
-}
-
 int streamWriteChar(Stream* out, char c)
 {
-    streamEnsureCapacity(out, out->index);
-    if(out->index < out->size)
+    streamEnsureIndex(out, out->index);
+    if(out->index < out->capacity)
     {
         out->data[out->index] = c;
         out->index++;
+        out->size++;
         return 0;
     }
     return -1;
@@ -160,32 +124,4 @@ int streamWriteChars(Stream* out, char* c)
         i++;
     }
     return 0;
-}
-
-int streamWriteShort(Stream* out, short s)
-{
-    streamEnsureCapacity(out, out->index + 1);
-    if(out->index + 1 < out->size)
-    {
-        out->data[out->index] = s & 0xFF;
-        out->data[out->index + 1] = (s >> 8) & 0xFF;
-        out->index += 2;
-        return 0;
-    }
-    return -1;
-}
-
-int streamWriteInt(Stream* out, int i)
-{
-    streamEnsureCapacity(out, out->index + 3);
-    if(out->index + 3 < out->size)
-    {
-        out->data[out->index] = i & 0xFF;
-        out->data[out->index + 1] = (i >> 8) & 0xFF;
-        out->data[out->index + 2] = (i >> 16) & 0xFF;
-        out->data[out->index + 3] = (i >> 24) & 0xFF;
-        out->index += 4;
-        return 0;
-    }
-    return -1;
 }

+ 5 - 9
Stream.h

@@ -3,6 +3,7 @@
 
 typedef struct Stream
 {
+    int capacity;
     int size;
     int index;
     char* data;
@@ -10,24 +11,19 @@ typedef struct Stream
 
 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);
+void streamEnsureIndex(Stream* s, int length);
 
 typedef void (*ClientStreamFunction) (Stream*);
 typedef int (*ServerStreamFunction) (int, int, Stream*);
 
+int streamSeekNewLine(Stream* in);
+int streamHasData(Stream* in);
+
 int streamGetChar(Stream* in, char* c);
 int streamGetChars(Stream* in, char* buffer, int length);
-int streamGetShort(Stream* in, short* s);
-int streamGetInt(Stream* in, int* i);
 
 int streamWriteChar(Stream* out, char c);
 int streamWriteChars(Stream* out, char* c);
-int streamWriteShort(Stream* out, short s);
-int streamWriteInt(Stream* out, int i);
 
 #endif
 

+ 18 - 0
String.c

@@ -1,8 +1,10 @@
 #include "String.h"
+#include "Stream.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
+#include <limits.h>
 
 void stringInit(String* s)
 {
@@ -25,8 +27,24 @@ int stringGetLength(String* s)
     return s->length;
 }
 
+void stringReadStreamLine(String* s, Stream* in)
+{
+    stringRemove(s);
+    int length = streamSeekNewLine(in);
+    s->data = malloc(sizeof(char) * (length + 1));
+    for(int i = 0; i < length; i++)
+    {
+        streamGetChar(in, &s->data[i]);
+    }
+    char c;
+    streamGetChar(in, &c); // remove \n
+    s->data[length] = '\0';
+    s->length = length;
+}
+
 void stringRead(String* s)
 {
+    stringRemove(s);
     int buffer = 16;
     int index = 0;
     char* chars = malloc(sizeof(char) * buffer);

+ 5 - 0
String.h

@@ -1,6 +1,8 @@
 #ifndef STRING_H
 #define STRING_H
 
+#include "Stream.h"
+
 typedef struct String
 {
     int length;
@@ -12,9 +14,12 @@ void stringRemove(String* s);
 
 int stringGetLength(String* s);
 
+void stringReadStreamLine(String* s, Stream* in);
 void stringRead(String* s);
 int stringCompare(String* s, const char* chars);
 int stringCompareNoCase(String* s, const char* chars);
 
+int stringIsInteger(String* s);
+
 #endif
 

+ 0 - 2
mails/b/b/10

@@ -1,2 +0,0 @@
-ich 
-es geht auch an sich selbst

+ 5 - 0
mails/b/b/11

@@ -0,0 +1,5 @@
+b
+b
+Yay
+Hmm Ok
+Zweite Zeile

+ 0 - 2
mails/b/b/6

@@ -1,2 +0,0 @@
-Das ist ein Test.
-Hi

BIN
mails/b/mailcounter


+ 3 - 0
mails/dfg/a/1

@@ -0,0 +1,3 @@
+df
+
+dfg

BIN
mails/dfg/mailcounter


+ 3 - 0
mails/dfg/s/0

@@ -0,0 +1,3 @@
+dfg
+
+

+ 3 - 0
mails/gdf/a/0

@@ -0,0 +1,3 @@
+df
+df
+

BIN
mails/gdf/mailcounter


+ 3 - 0
todo

@@ -12,3 +12,6 @@ dummy login
 - done
 ldap login
 multiline messages
+- done
+command in protocol
+- protocol completely changed to fit the specification