summaryrefslogtreecommitdiff
path: root/backend/server.cpp
diff options
context:
space:
mode:
authorMatthew Kosarek <matthew.kosarek@vention.cc>2021-02-20 14:24:43 -0500
committerMatthew Kosarek <matthew.kosarek@vention.cc>2021-02-20 14:24:43 -0500
commit61f537c0bc9ff6b73fc7e837e08a5c7867f16832 (patch)
tree10f78a9b684deab67bd133bd7b28c015db40b60c /backend/server.cpp
parent5c409f04470e319f0a57e8791bc96cd724ee601c (diff)
Multithreading requests on the backend, and removing unnecessary files
Diffstat (limited to 'backend/server.cpp')
-rw-r--r--backend/server.cpp274
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