From 4941a1874b6ca9d142d94df70b2aec5e0b35b94e Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Sun, 16 May 2021 19:49:37 -0400 Subject: Removed the entirety of the backend --- backend/server.cpp | 407 ----------------------------------------------------- 1 file changed, 407 deletions(-) delete mode 100644 backend/server.cpp (limited to 'backend/server.cpp') diff --git a/backend/server.cpp b/backend/server.cpp deleted file mode 100644 index b9d6f1c..0000000 --- a/backend/server.cpp +++ /dev/null @@ -1,407 +0,0 @@ -#include -#include -#include -#include -#include -#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, - HttpRequestType_Get -}; - -enum HttpRequestError { - HttpRequestError_None, - HttpRequestError_UnsupportedRequest, - HttpRequestError_NoBuffer, - HttpRequestError_ClientDisconnect -}; - -struct HeaderParseResult { - HttpRequestType requestType; - char resource[512]; - HttpRequestError error = HttpRequestError_None; -}; - - -struct HeaderParser { - char buffer[4096]; - int bufferPtr = 0; - int bufferSize = 0; - char line[512]; - int lineIndex = 0 ; - - bool tryReadLine() { - int startIndex = bufferPtr; - int endIndex = startIndex; - while (true) { - if (bufferPtr >= bufferSize) { - endIndex = bufferPtr; - break; - } - - if (strncmp(&buffer[bufferPtr], "\r\n", 2) == 0) { - endIndex = bufferPtr; - bufferPtr += 2; // Move past the new line character - break; - } - - bufferPtr++; - } - - int lineLength = endIndex - startIndex; - if (lineLength == 0) { - return false; - } - - assert(lineLength < 512 && lineLength > 0); - strncpy_s(line, &buffer[startIndex], lineLength); - line[lineLength] = '\0'; - return true; - } - - HeaderParseResult readHeader(SOCKET clientSocket) { - HeaderParseResult retval; - ZeroMemory(buffer, 4096); - - // Wait for client to send data - bufferSize = recv(clientSocket, buffer, 4096, 0); - if (bufferSize == SOCKET_ERROR) { - printf("Error in receive. Quitting\n"); - retval.error = HttpRequestError_NoBuffer; - return retval; - } else if (bufferSize == 0) { - printf("Client disconnected\n"); - retval.error = HttpRequestError_ClientDisconnect; - return retval; - } - - printf("Received message (%d bytes): %s", bufferSize, buffer); - - while (tryReadLine()) { - if (lineIndex == 0) { - // Parse request, only supporting GETs for now - int linePtr = 0; - if (strncmp(line, "GET ", 3) == 0) { - retval.requestType = HttpRequestType_Get; - linePtr += 4; // Move past teh get - } else { - retval.error = HttpRequestError_UnsupportedRequest; - return retval; - } - - copyUntilStr(retval.resource, &line[linePtr], " "); - printf("Get request on resource: %s\n", retval.resource); - } - - lineIndex++; - } - - return retval; - } -}; - -enum FileType { - FileType_None, - FileType_HTML, - FileType_CSS, - FileType_JS -}; - -enum HttpStatusCode { - HttpStatusCode_OK = 200, - HttpStatusCode_BADREQUEST = 400, - HttpStatusCode_NOTFOUND = 404 -}; - -void sendErrorMessage(SOCKET socket, HttpStatusCode status, const char* errorHtml) { - char timeStr[100]; - char header[512]; - - ZeroMemory(timeStr, 100); - ZeroMemory(header, 100); - - const char* errorMessage; - switch (status) { - case HttpStatusCode_BADREQUEST: - errorMessage = "Bad Request"; - break; - case HttpStatusCode_NOTFOUND: - errorMessage = "Not found"; - break; - default: - errorMessage = "Unknown"; - break; - } - - getCurrentDateStr(timeStr); - int contentLen = strlen(errorHtml); - sprintf(header, "HTTP/1.1 %d %s\r\nDate: %s\r\nContent-Type: text/html; charset=utf-8\r\nConnection: keep-alive\r\nContent-Length: %d\r\n\r\n", status, errorMessage, timeStr, contentLen); - send(socket, header, strlen(header), 0); - - send(socket, errorHtml, contentLen, 0); -} - -#define MAXBUFLEN 1000000 - -int readFileToMemory(char* filepath, char source[MAXBUFLEN + 1], bool isBinary) { - FILE* file; - fopen_s(&file, filepath, isBinary ? "rb" : "r+"); - - if(file == NULL) { - printf("Failed to read the file\n"); - return -1; - } - - size_t newLen = fread(source, sizeof(char), MAXBUFLEN, file); - if ( ferror( file ) != 0 ) { - fputs("Error reading file", stderr); - return -1; - } - - fclose(file); - return newLen; -} - - -int fixNewLines(char* str, int strSize) { - int removed = 0; - for(int i = 0; i < strSize; i++) { - if(str[i] == '\n') { - str[i] = '\r\n'; - removed++; - } - } - - return removed; -} - - -bool trySendFile(SOCKET clientSocket, char* filename) { - char filePath[128]; - sprintf(filePath, "../../frontend%s", filename); - - bool isBinary = false; - if (endsWith(filename, ".ico") || endsWith(filename, ".wasm")) { - isBinary = true; - } - - char source[MAXBUFLEN + 1]; - int fileSizeBytes = readFileToMemory(filePath, source, isBinary); - - if (fileSizeBytes <= 0) { - return false; - } - - const char* contentType; - if (endsWith(filename, ".html")) { - contentType = "text/html"; - } else if (endsWith(filename, ".js")) { - contentType = "application/javascript"; - } else if (endsWith(filename, ".css")) { - contentType = "text/css"; - } else if (endsWith(filename, ".ico")) { - contentType = "image/x-icon"; - } else if (endsWith(filename, ".wasm")) { - contentType = "application/wasm"; - } else { - contentType = "text/plain"; - } - - char timeStr[100]; - char header[512]; - - ZeroMemory(timeStr, 100); - ZeroMemory(header, 100); - - getCurrentDateStr(timeStr); - sprintf(header, "HTTP/1.1 200 OK\r\nDate: %s\r\nContent-Type: %s; charset=utf-8\r\nConnection: keep-alive\r\nContent-Length: %d\r\n\r\n", timeStr, contentType, fileSizeBytes); - send(clientSocket, header, strlen(header), 0); - - - int bytesSent = 0; - int bytesRemaining = fileSizeBytes; - while (bytesSent < fileSizeBytes) { - int amountToSend = bytesRemaining >= 4096 ? 4096 : bytesRemaining; // Send 4K bytes at a time max - send(clientSocket, &source[bytesSent], amountToSend, 0); - bytesRemaining -= amountToSend; - bytesSent += amountToSend; - } - - return true; -} - -void handleClient(SOCKET clientSocket) { - 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; - } - } - - // Close the socket - closesocket(clientSocket); -} - -DWORD WINAPI runConnection(LPVOID lpParam) { - ClientConnection* connection = (ClientConnection*)lpParam; - - while (true) { - Sleep(100); - - if (connection->isActive) { - handleClient(connection->clientSocket); - connection->isActive = false; - } - } -} \ No newline at end of file -- cgit v1.2.1