| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 | #include "Server.h"#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <unistd.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/types.h>  #include "Stream.h" void serverInitDefaults(Server* s){    s->maxClients = -1;    s->port = -1;    s->threads = NULL;    s->clientSockets = NULL;    s->connectSocket = -1;        s->hAmount = -1;    s->hIndex = -1;    s->handlers = NULL;}int serverInit(Server* s, int maxClients, short port){    s->maxClients = maxClients;    s->port = port;    s->hAmount = 0;    s->hIndex = 0;        // initialize storage for clients    s->threads = malloc(sizeof(pthread_t) * maxClients);    s->clientSockets = malloc(sizeof(int) * maxClients);        for(int i = 0; i < maxClients; i++)    {        s->threads[i] = -1;        s->clientSockets[i] = -1;    }        // create the socket for clients to connect    s->connectSocket = socket(AF_INET, SOCK_STREAM, 0);    if(s->connectSocket == -1)    {        perror("Cannot create socket");        serverRemove(s);        return -1;    }        // prevents clients from blocking the port if the server exits    struct linger sl;    sl.l_onoff = 1;    sl.l_linger = 0;    if(setsockopt(s->connectSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(struct linger)) == -1)    {        perror("Cannot set non lingering");        serverRemove(s);        return -1;    }        // specifies data of the port and binds it    struct sockaddr_in connectSocketData;    memset(&connectSocketData, 0, sizeof(struct sockaddr_in));    connectSocketData.sin_family = AF_INET;    connectSocketData.sin_addr.s_addr = INADDR_ANY;    connectSocketData.sin_port = htons(port);    if(bind(s->connectSocket, (struct sockaddr*) &connectSocketData, sizeof(struct sockaddr_in)) != 0)    {        perror("Cannot bind socket");        serverRemove(s);        return -1;    }        // mark this socket as handler for connection requests    if(listen(s->connectSocket, 5) != 0)    {        perror("Cannot start listening");        serverRemove(s);        return -1;    }        return 0;}void serverRemove(Server* s){    s->port = -1;        if(s->threads != NULL)    {        for(int i = 0; i < s->maxClients; i++)        {            if(s->threads[i] != -1)            {                printf("%d thread\n", i);                pthread_cancel(s->threads[i]);                pthread_join(s->threads[i], NULL);            }        }        free(s->threads);        s->threads = NULL;    }        if(s->clientSockets != NULL)    {        for(int i = 0; i < s->maxClients; i++)        {            if(s->clientSockets[i] != -1)            {                if(close(s->clientSockets[i]) == -1)                {                    printf("%d", i);                    perror(" cannot close client socket");                }                else                {                    printf("%d closed\n", i);                }            }        }        free(s->clientSockets);        s->clientSockets = NULL;    }        s->maxClients = -1;        if(s->connectSocket != -1)    {        if(close(s->connectSocket) != 0)        {            perror("Cannot close server socket");        }        else        {            printf("connection listener closed\n");        }        s->connectSocket = -1;    }        s->hAmount = -1;    s->hIndex = -1;    if(s->handlers != NULL)    {        free(s->handlers);        s->handlers = NULL;    }}void* clientHandler(void* data){    int id = ((ThreadData*) data)->id;    Server* s = ((ThreadData*) data)->server;        Stream in;    while(strcmp(in.data, "quit") != 0)    {        int size = recv(s->clientSockets[id], in.data, BUFFER_SIZE - 1, 0);        if(size > 0)        {            in.data[size] = '\0';            int package = ((int) in.data[0]);            if(package >= 0 && package < s->hIndex)            {                printf("Received package %d from %d: %s\n", package, id, in.data);                in.index = 1;                in.size = size;                s->handlers[package](&in);            }            else            {                printf("Invalid package %d from %d\n", package, id);            }        }        else if(size == 0)        {            printf("Client %d closed remote socket\n", id);            break;        }           else        {            perror("recv error");            break;        }    }        if(close(s->clientSockets[id]) != 0)    {        printf("%d", id);        perror(" cannot close client socket");    }    else    {        printf("%d closed\n", id);    }        s->clientSockets[id] = -1;    return NULL;}void serverWaitForConnection(Server* s){    socklen_t addrlen = sizeof(struct sockaddr_in);    char buffer[BUFFER_SIZE];        while(1)    {        printf("Waiting for connections...\n");        struct sockaddr_in clientSocketData;        int clientSocket = accept(s->connectSocket, (struct sockaddr*) &clientSocketData, &addrlen);        if(clientSocket >= 0)        {            printf("Client connected from %s:%d...\n", inet_ntoa(clientSocketData.sin_addr), (int) ntohs(clientSocketData.sin_port));                        int i = 0;            while(1)            {                if(s->clientSockets[i] == -1)                {                    if(s->threads[i] != -1)                    {                        pthread_cancel(s->threads[i]);                        pthread_join(s->threads[i], NULL);                    }                                        ThreadData data;                    data.id = i;                    data.server = s;                    if(pthread_create(&s->threads[i], NULL, clientHandler, (void*) &data) != 0)                    {                        perror("Cannot create thread");                                                  strcpy(buffer, "error: cannot create thread\n");                        if(send(clientSocket, buffer, strlen(buffer), 0) == -1)                        {                            perror("Cannot send error");                        }                        close(clientSocket);                    }                    else                    {                        s->clientSockets[i] = clientSocket;                                                strcpy(buffer, "Welcome to server, please enter your command:\n");                        if(send(clientSocket, buffer, strlen(buffer), 0) == -1)                        {                            perror("Cannot send welcome message");                            close(clientSocket);                            s->clientSockets[i] = -1;                        }                    }                    break;                }                                i++;                if(i >= s->maxClients)                {                    printf("max clients reached\n");                                            strcpy(buffer, "error: max clients reached\n");                    if(send(clientSocket, buffer, strlen(buffer), 0) == -1)                    {                        perror("Cannot send error");                    }                    close(clientSocket);                    break;                }            }        }    }}void serverRegisterHandler(Server* s, StreamFunction f){    if(s->hAmount == s->hIndex)    {        if(s->hAmount == 0)        {            s->handlers = malloc(sizeof(StreamFunction));            s->hAmount = 1;        }        else        {            s->hAmount *= 2;            StreamFunction* functions = malloc(sizeof(StreamFunction) * 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++;}
 |