summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--backend/.vs/ProjectSettings.json3
-rw-r--r--backend/.vs/VSWorkspaceState.json6
-rw-r--r--backend/.vs/backend/v16/.suobin15872 -> 0 bytes
-rw-r--r--backend/.vs/backend/v16/Browse.VC.dbbin253952 -> 0 bytes
-rw-r--r--backend/.vs/slnx.sqlitebin90112 -> 0 bytes
-rw-r--r--backend/Header.h23
-rw-r--r--backend/Server/.vs/Server/v16/.suobin32768 -> 0 bytes
-rw-r--r--backend/Server/.vs/Server/v16/Browse.VC.dbbin34717696 -> 0 bytes
-rw-r--r--backend/Server/.vs/Server/v16/ipch/AutoPCH/8c0889d90d2b555a/SERVER.ipchbin45285376 -> 0 bytes
-rw-r--r--backend/Server/Debug/Server.exebin49152 -> 0 bytes
-rw-r--r--backend/Server/Debug/Server.ilkbin570180 -> 0 bytes
-rw-r--r--backend/Server/Debug/Server.pdbbin634880 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.exe.recipe11
-rw-r--r--backend/Server/Server/Debug/Server.log5
-rw-r--r--backend/Server/Server/Debug/Server.tlog/CL.command.1.tlogbin884 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/CL.read.1.tlogbin27356 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/CL.write.1.tlogbin560 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/Server.lastbuildstate2
-rw-r--r--backend/Server/Server/Debug/Server.tlog/Server.write.1u.tlogbin26450 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/link.command.1.tlogbin1606 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/link.read.1.tlogbin11262 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/Server.tlog/link.write.1.tlogbin562 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/server.objbin53092 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/vc142.idbbin265216 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/vc142.pdbbin167936 -> 0 bytes
-rw-r--r--backend/Server/Server/Debug/vcpkg.applocal.log1
-rw-r--r--backend/Server/Server/Server.vcxproj4
-rw-r--r--backend/Server/Server/Server.vcxproj.filters8
-rw-r--r--backend/Server/Server/Server.vcxproj.user3
-rw-r--r--backend/server.cpp274
-rw-r--r--backend/stringmanip.h27
32 files changed, 227 insertions, 145 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..84cc797
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+backend/Server/Debug
+backend/Server/Release
+backend/Server/.vs
+.vs/
+backend/Server/Server/Debug \ No newline at end of file
diff --git a/backend/.vs/ProjectSettings.json b/backend/.vs/ProjectSettings.json
deleted file mode 100644
index 0cf5ea5..0000000
--- a/backend/.vs/ProjectSettings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "CurrentProjectSetting": "No Configurations"
-} \ No newline at end of file
diff --git a/backend/.vs/VSWorkspaceState.json b/backend/.vs/VSWorkspaceState.json
deleted file mode 100644
index 6b61141..0000000
--- a/backend/.vs/VSWorkspaceState.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "ExpandedNodes": [
- ""
- ],
- "PreviewInSolutionExplorer": false
-} \ No newline at end of file
diff --git a/backend/.vs/backend/v16/.suo b/backend/.vs/backend/v16/.suo
deleted file mode 100644
index b4714d2..0000000
--- a/backend/.vs/backend/v16/.suo
+++ /dev/null
Binary files differ
diff --git a/backend/.vs/backend/v16/Browse.VC.db b/backend/.vs/backend/v16/Browse.VC.db
deleted file mode 100644
index f98ab3e..0000000
--- a/backend/.vs/backend/v16/Browse.VC.db
+++ /dev/null
Binary files differ
diff --git a/backend/.vs/slnx.sqlite b/backend/.vs/slnx.sqlite
deleted file mode 100644
index 40c8fc4..0000000
--- a/backend/.vs/slnx.sqlite
+++ /dev/null
Binary files differ
diff --git a/backend/Header.h b/backend/Header.h
new file mode 100644
index 0000000..5282066
--- /dev/null
+++ b/backend/Header.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#ifdef WIN32
+
+#include <Windows.h>
+
+#else
+// TODO: Support Linux threads
+#include <pthread.h>
+#endif
+
+struct ThreadInstance {
+ DWORD mThreadId;
+ HANDLE mThreadHandle;
+};
+
+bool initThreadInstance(ThreadInstance* instance) {
+ instance->mThreadHandle = CreateThread(NULL, 0,, NULL, 0, NULL);
+}
+
+struct ThreadPool {
+
+}; \ No newline at end of file
diff --git a/backend/Server/.vs/Server/v16/.suo b/backend/Server/.vs/Server/v16/.suo
deleted file mode 100644
index 5ca583f..0000000
--- a/backend/Server/.vs/Server/v16/.suo
+++ /dev/null
Binary files differ
diff --git a/backend/Server/.vs/Server/v16/Browse.VC.db b/backend/Server/.vs/Server/v16/Browse.VC.db
deleted file mode 100644
index e2d4096..0000000
--- a/backend/Server/.vs/Server/v16/Browse.VC.db
+++ /dev/null
Binary files differ
diff --git a/backend/Server/.vs/Server/v16/ipch/AutoPCH/8c0889d90d2b555a/SERVER.ipch b/backend/Server/.vs/Server/v16/ipch/AutoPCH/8c0889d90d2b555a/SERVER.ipch
deleted file mode 100644
index 5f68daa..0000000
--- a/backend/Server/.vs/Server/v16/ipch/AutoPCH/8c0889d90d2b555a/SERVER.ipch
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Debug/Server.exe b/backend/Server/Debug/Server.exe
deleted file mode 100644
index 7845e21..0000000
--- a/backend/Server/Debug/Server.exe
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Debug/Server.ilk b/backend/Server/Debug/Server.ilk
deleted file mode 100644
index 5f58ea9..0000000
--- a/backend/Server/Debug/Server.ilk
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Debug/Server.pdb b/backend/Server/Debug/Server.pdb
deleted file mode 100644
index 2df8dd6..0000000
--- a/backend/Server/Debug/Server.pdb
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.exe.recipe b/backend/Server/Server/Debug/Server.exe.recipe
deleted file mode 100644
index 22aff66..0000000
--- a/backend/Server/Server/Debug/Server.exe.recipe
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project>
- <ProjectOutputs>
- <ProjectOutput>
- <FullPath>C:\Users\mattykae\Projects\website\backend\Server\Debug\Server.exe</FullPath>
- </ProjectOutput>
- </ProjectOutputs>
- <ContentFiles />
- <SatelliteDlls />
- <NonRecipeFileRefs />
-</Project> \ No newline at end of file
diff --git a/backend/Server/Server/Debug/Server.log b/backend/Server/Server/Debug/Server.log
deleted file mode 100644
index 099ba46..0000000
--- a/backend/Server/Server/Debug/Server.log
+++ /dev/null
@@ -1,5 +0,0 @@
- server.cpp
-C:\Users\mattykae\Projects\website\backend\server.cpp(54,28): warning C4305: '=': truncation from 'int' to 'char'
-C:\Users\mattykae\Projects\website\backend\server.cpp(54,22): warning C4309: '=': truncation of constant value
-C:\Users\mattykae\Projects\website\backend\server.cpp(208,11): warning C4101: 'file': unreferenced local variable
- Server.vcxproj -> C:\Users\mattykae\Projects\website\backend\Server\Debug\Server.exe
diff --git a/backend/Server/Server/Debug/Server.tlog/CL.command.1.tlog b/backend/Server/Server/Debug/Server.tlog/CL.command.1.tlog
deleted file mode 100644
index a695c28..0000000
--- a/backend/Server/Server/Debug/Server.tlog/CL.command.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/CL.read.1.tlog b/backend/Server/Server/Debug/Server.tlog/CL.read.1.tlog
deleted file mode 100644
index 5cbb32c..0000000
--- a/backend/Server/Server/Debug/Server.tlog/CL.read.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/CL.write.1.tlog b/backend/Server/Server/Debug/Server.tlog/CL.write.1.tlog
deleted file mode 100644
index 1a45dfc..0000000
--- a/backend/Server/Server/Debug/Server.tlog/CL.write.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/Server.lastbuildstate b/backend/Server/Server/Debug/Server.tlog/Server.lastbuildstate
deleted file mode 100644
index adc7782..0000000
--- a/backend/Server/Server/Debug/Server.tlog/Server.lastbuildstate
+++ /dev/null
@@ -1,2 +0,0 @@
-PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.18362.0:
-Debug|Win32|C:\Users\mattykae\Projects\website\backend\Server\|
diff --git a/backend/Server/Server/Debug/Server.tlog/Server.write.1u.tlog b/backend/Server/Server/Debug/Server.tlog/Server.write.1u.tlog
deleted file mode 100644
index d14d9c7..0000000
--- a/backend/Server/Server/Debug/Server.tlog/Server.write.1u.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/link.command.1.tlog b/backend/Server/Server/Debug/Server.tlog/link.command.1.tlog
deleted file mode 100644
index 9320e07..0000000
--- a/backend/Server/Server/Debug/Server.tlog/link.command.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/link.read.1.tlog b/backend/Server/Server/Debug/Server.tlog/link.read.1.tlog
deleted file mode 100644
index 5347f94..0000000
--- a/backend/Server/Server/Debug/Server.tlog/link.read.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/Server.tlog/link.write.1.tlog b/backend/Server/Server/Debug/Server.tlog/link.write.1.tlog
deleted file mode 100644
index 8108896..0000000
--- a/backend/Server/Server/Debug/Server.tlog/link.write.1.tlog
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/server.obj b/backend/Server/Server/Debug/server.obj
deleted file mode 100644
index 5b7c6c9..0000000
--- a/backend/Server/Server/Debug/server.obj
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/vc142.idb b/backend/Server/Server/Debug/vc142.idb
deleted file mode 100644
index 7f41488..0000000
--- a/backend/Server/Server/Debug/vc142.idb
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/vc142.pdb b/backend/Server/Server/Debug/vc142.pdb
deleted file mode 100644
index 21c2483..0000000
--- a/backend/Server/Server/Debug/vc142.pdb
+++ /dev/null
Binary files differ
diff --git a/backend/Server/Server/Debug/vcpkg.applocal.log b/backend/Server/Server/Debug/vcpkg.applocal.log
deleted file mode 100644
index 8b13789..0000000
--- a/backend/Server/Server/Debug/vcpkg.applocal.log
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/backend/Server/Server/Server.vcxproj b/backend/Server/Server/Server.vcxproj
index c673f44..650e217 100644
--- a/backend/Server/Server/Server.vcxproj
+++ b/backend/Server/Server/Server.vcxproj
@@ -141,6 +141,10 @@
<ItemGroup>
<ClCompile Include="..\..\server.cpp" />
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\Header.h" />
+ <ClInclude Include="..\..\stringmanip.h" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/backend/Server/Server/Server.vcxproj.filters b/backend/Server/Server/Server.vcxproj.filters
index 77af75f..b507bf5 100644
--- a/backend/Server/Server/Server.vcxproj.filters
+++ b/backend/Server/Server/Server.vcxproj.filters
@@ -19,4 +19,12 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\stringmanip.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\Header.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/backend/Server/Server/Server.vcxproj.user b/backend/Server/Server/Server.vcxproj.user
index c72ed2e..6813734 100644
--- a/backend/Server/Server/Server.vcxproj.user
+++ b/backend/Server/Server/Server.vcxproj.user
@@ -4,4 +4,7 @@
<LocalDebuggerWorkingDirectory>$(SolutionDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
+ <PropertyGroup>
+ <ShowAllFiles>true</ShowAllFiles>
+ </PropertyGroup>
</Project> \ No newline at end of file
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
diff --git a/backend/stringmanip.h b/backend/stringmanip.h
new file mode 100644
index 0000000..c5a32dc
--- /dev/null
+++ b/backend/stringmanip.h
@@ -0,0 +1,27 @@
+#pragma once
+#include <string.h>
+
+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));
+}
+
+void getCurrentDateStr(char* text) {
+ time_t now = time(NULL);
+ sprintf(text, "%s GMT", ctime(&now));
+} \ No newline at end of file