diff options
Diffstat (limited to 'backend/server.cpp')
-rw-r--r-- | backend/server.cpp | 274 |
1 files changed, 157 insertions, 117 deletions
diff --git a/backend/server.cpp b/backend/server.cpp index eb371d3..a58eed1 100644 --- a/backend/server.cpp +++ b/backend/server.cpp @@ -3,11 +3,127 @@ #include <string.h> #include <assert.h> #include <time.h> +#include "stringmanip.h" #pragma comment (lib, "ws2_32.lib") #define WIN32_LEAN_AND_MEAN #define PORT 80 +#define NUM_CLIENT_THREADS 8 + +void handleClient(SOCKET clientSocket); +DWORD WINAPI runConnection(LPVOID lpParam); + +struct ClientConnection { + bool isActive = false; + SOCKET clientSocket; +}; + +struct ClientConnectionThreadArray { + ClientConnection connectionList[NUM_CLIENT_THREADS]; + DWORD threadIdArray[NUM_CLIENT_THREADS]; + HANDLE threadArray[NUM_CLIENT_THREADS]; + + void start() { + for (int tIdx = 0; tIdx < NUM_CLIENT_THREADS; tIdx++) { + threadArray[tIdx] = CreateThread( + NULL, + 0, + runConnection, + &connectionList[tIdx], + 0, + &threadIdArray[tIdx] + ); + } + } + + void run(SOCKET clientSocket) { + bool found = false; + while (!found) { + for (int connIdx = 0; connIdx < NUM_CLIENT_THREADS; connIdx++) { + if (!connectionList[connIdx].isActive) { + connectionList[connIdx].clientSocket = clientSocket; + connectionList[connIdx].isActive = true; + found = true; + break; + } + } + + if (!found) { + Sleep(50); + } + } + } +}; + +int main() { + // Initializing Winsock + WSADATA wsaData; + WORD version = MAKEWORD(2, 2); + + int wsOK = WSAStartup(version, &wsaData); + if (wsOK != 0) { + printf("Cannot initialize winsock: %d\n", wsOK); + return EXIT_FAILURE; + } + + // Creating a socket + SOCKET listeningSocket = socket(AF_INET, SOCK_STREAM, 0); + if (listeningSocket == INVALID_SOCKET) { + printf("Cannot create socket\n"); + return EXIT_FAILURE; + } + + // Bind an IP address and port to a socket + sockaddr_in hint = { 0 }; + hint.sin_family = AF_INET; + hint.sin_port = htons(PORT); // Networking is big endian, while PCs are little endian + hint.sin_addr.S_un.S_addr = htonl(INADDR_ANY); + + bind(listeningSocket, (sockaddr*)&hint, sizeof(hint)); + + // Tell Winsock the socket is for listening + listen(listeningSocket, SOMAXCONN); + + ClientConnectionThreadArray threadManager; + threadManager.start(); + + while (true) { + + // Wait for a connection + sockaddr_in client; + int clientSize = sizeof(client); + + SOCKET clientSocket = accept(listeningSocket, (sockaddr*)&client, &clientSize); + if (clientSocket == INVALID_SOCKET) { + printf("Cannot create the client socket\n"); + return EXIT_FAILURE; + } + + char host[NI_MAXHOST]; // Client's remote name + char service[NI_MAXSERV]; // Service (i.e. port) the client is connected on + + ZeroMemory(host, NI_MAXHOST); + ZeroMemory(service, NI_MAXSERV); + + if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) { + printf("Host %s connected on port %s\n", host, service); + } else { + inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST); + printf("Host %s connected on port %d\n", host, ntohs(client.sin_port)); + } + + threadManager.run(clientSocket); + } + + // Close listening socket + closesocket(listeningSocket); + + // Cleanup winsock + WSACleanup(); + + return EXIT_SUCCESS; +} enum HttpRequestType { HttpRequestType_None, @@ -27,26 +143,6 @@ struct HeaderParseResult { HttpRequestError error = HttpRequestError_None; }; -void copyUntilStr(char* destination, char* source, const char* cmpstr) { - int index = 0; - char* ptr = source; - int cmpStrLen = strlen(cmpstr); - while (strncmp(ptr, cmpstr, cmpStrLen) != 0) { - destination[index++] = *ptr; - ptr++; - } - - destination[index] = '\0'; -} - -int endsWith(const char *str, const char *suffix) { - size_t str_len = strlen(str); - size_t suffix_len = strlen(suffix); - - return (str_len >= suffix_len) && - (!memcmp(str + str_len - suffix_len, suffix, suffix_len)); -} - int fixNewLines(char* str, int strSize) { int removed = 0; for(int i = 0; i < strSize; i++) { @@ -136,11 +232,6 @@ struct HeaderParser { } }; -void getCurrentDateStr(char* text) { - time_t now = time(NULL); - sprintf(text, "%s GMT", ctime(&now)); -} - enum FileType { FileType_None, FileType_HTML, @@ -253,108 +344,57 @@ bool trySendFile(SOCKET clientSocket, char* filename) { return true; } - -int main() { - // Initializing Winsock - WSADATA wsaData; - WORD version = MAKEWORD(2, 2); - - int wsOK = WSAStartup(version, &wsaData); - if (wsOK != 0) { - printf("Cannot initialize winsock: %d\n", wsOK); - return EXIT_FAILURE; - } - - // Creating a socket - SOCKET listeningSocket = socket(AF_INET, SOCK_STREAM, 0); - if (listeningSocket == INVALID_SOCKET) { - printf("Cannot create socket\n"); - return EXIT_FAILURE; - } - - // Bind an IP address and port to a socket - sockaddr_in hint = { 0 }; - hint.sin_family = AF_INET; - hint.sin_port = htons(PORT); // Networking is big endian, while PCs are little endian - hint.sin_addr.S_un.S_addr = htonl(INADDR_ANY); - - bind(listeningSocket, (sockaddr*)&hint, sizeof(hint)); - - // Tell Winsock the socket is for listening - listen(listeningSocket, SOMAXCONN); - +void handleClient(SOCKET clientSocket) { while (true) { - - // Wait for a connection - sockaddr_in client; - int clientSize = sizeof(client); - - SOCKET clientSocket = accept(listeningSocket, (sockaddr*)&client, &clientSize); - if (clientSocket == INVALID_SOCKET) { - printf("Cannot create the client socket\n"); - return EXIT_FAILURE; + HeaderParser parser; + HeaderParseResult parseResult = parser.readHeader(clientSocket); + bool shouldBreak = false; + + switch (parseResult.error) { + case HttpRequestError_ClientDisconnect: { + shouldBreak = true; + break; + } + case HttpRequestError_UnsupportedRequest: { + shouldBreak = true; + break; } - - char host[NI_MAXHOST]; // Client's remote name - char service[NI_MAXSERV]; // Service (i.e. port) the client is connected on - - ZeroMemory(host, NI_MAXHOST); - ZeroMemory(service, NI_MAXSERV); - - if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) { - printf("Host %s connected on port %s\n", host, service); - } else { - inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST); - printf("Host %s connected on port %d\n", host, ntohs(client.sin_port)); } - // Accept and echo message back to client - while (true) { - HeaderParser parser; - HeaderParseResult parseResult = parser.readHeader(clientSocket); - bool shouldBreak = false; - - switch (parseResult.error) { - case HttpRequestError_ClientDisconnect: { - shouldBreak = true; - break; - } - case HttpRequestError_UnsupportedRequest: { - shouldBreak = true; - break; - } - } - - if (shouldBreak) { - break; - } - - switch (parseResult.requestType) { - case HttpRequestType_Get: { - if (strcmp(parseResult.resource, "/") == 0) { - trySendFile(clientSocket, (char*)"/index.html"); - } else { - trySendFile(clientSocket, parseResult.resource); - } - shouldBreak = true; - break; - } - } + if (shouldBreak) { + break; + } - if (shouldBreak) { - break; + switch (parseResult.requestType) { + case HttpRequestType_Get: { + if (strcmp(parseResult.resource, "/") == 0) { + trySendFile(clientSocket, (char*)"/index.html"); + } else { + trySendFile(clientSocket, parseResult.resource); } + shouldBreak = true; + break; + } } - // Close the socket - closesocket(clientSocket); + if (shouldBreak) { + break; + } } - // Close listening socket - closesocket(listeningSocket); + // Close the socket + closesocket(clientSocket); +} - // Cleanup winsock - WSACleanup(); +DWORD WINAPI runConnection(LPVOID lpParam) { + ClientConnection* connection = (ClientConnection*)lpParam; - return EXIT_SUCCESS; + while (true) { + Sleep(100); + + if (connection->isActive) { + handleClient(connection->clientSocket); + connection->isActive = false; + } + } }
\ No newline at end of file |