summaryrefslogtreecommitdiff
path: root/backend/server.cpp
diff options
context:
space:
mode:
authorMatthew Kosarek <mattkae@protonmail.com>2021-05-16 19:49:37 -0400
committerMatthew Kosarek <mattkae@protonmail.com>2021-05-16 19:49:37 -0400
commit4941a1874b6ca9d142d94df70b2aec5e0b35b94e (patch)
tree64e0d585420230213bb9eee57f2be0a3325e766d /backend/server.cpp
parent61128756e24e88d84bd77cd4993b5f14284791f0 (diff)
Removed the entirety of the backend
Diffstat (limited to 'backend/server.cpp')
-rw-r--r--backend/server.cpp407
1 files changed, 0 insertions, 407 deletions
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 <stdio.h>
-#include <wS2tcpip.h>
-#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,
- 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