diff --git a/.idea/cprotohackers.iml b/.idea/cprotohackers.iml
index f08604b..83f477b 100644
--- a/.idea/cprotohackers.iml
+++ b/.idea/cprotohackers.iml
@@ -1,2 +1,8 @@
-
\ No newline at end of file
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0b76fe5..a424e87 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,8 @@
+
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 072582b..980bd4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,24 @@
cmake_minimum_required(VERSION 3.31)
-project(cprotohackers C)
+project(server00 C)
set(CMAKE_C_STANDARD 23)
-add_executable(cprotohackers main.c
- main.h
+
+set(COMMON_SOURCES
data.c
data.h)
-target_link_libraries(cprotohackers wsock32 ws2_32)
+
+
+add_executable(server00 server00.c
+ server00.h
+ ${COMMON_SOURCES})
+target_link_libraries(server00 wsock32 ws2_32)
+
+find_package(json-c CONFIG REQUIRED)
+
+
+add_executable(server01 server01.c
+ server01.h
+ ${COMMON_SOURCES})
+
+target_link_libraries(server01 PRIVATE wsock32 ws2_32 json-c::json-c)
\ No newline at end of file
diff --git a/data.c b/data.c
index 99af864..5e6caae 100644
--- a/data.c
+++ b/data.c
@@ -6,6 +6,25 @@
#include
#include
+#define PORT 40000
+SOCKET get_listen_socket() {
+ WSADATA WSAData;
+
+ SOCKET client;
+
+ SOCKADDR_IN serverAddr, clientAddr;
+
+ WSAStartup(MAKEWORD(2,0), &WSAData);
+ SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
+
+ serverAddr.sin_addr.s_addr = INADDR_ANY;
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_port = htons(PORT);
+
+ bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
+ listen(server, 0);
+ return server;
+}
char_array_t *char_array_create(int capacity) {
char_array_t *array = malloc(sizeof(char_array_t));
@@ -22,10 +41,11 @@ void char_array_append(char_array_t *array, char *value, size_t length) {
if (array->data == NULL) {
exit(1);
}
- printf("old size: %llu\n", array->size);
- printf("length: %llu\n", length);
+ // char *temp = calloc(length+1, sizeof(char));
+ // memcpy(temp, value, length);
+ // printf("Appending '%s' bytes\n", temp);
+ // free(temp);
size_t new_size = array->size + length;
- printf("New size: %llu\n", new_size);
if (new_size > array->capacity) {
array->capacity = new_size;
char *new_array = realloc(array->data, array->capacity);
@@ -47,3 +67,35 @@ void char_array_wipe(char_array_t *array) {
array->size = 0;
memset(array->data, 0, array->capacity);
};
+
+bool char_array_has_char(char_array_t *array, char c) {
+ const char *ret = memchr(array->data, c, array->size);
+ if (ret == NULL) {
+ return false;
+ }
+ return true;
+};
+char *char_array_get_until_char(char_array_t *array, char c) {
+ size_t idx = 0;
+ for (size_t i = 0; i < array->size; i++) {
+ if (array->data[i] == c) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx == 0) {
+ return NULL;
+ }
+ char *ret = malloc(idx+1);
+ memcpy(ret, array->data, idx);
+ ret[idx] = '\0';
+ char *temp = calloc(array->capacity, sizeof(char));
+ size_t new_i = 0;
+ for (size_t i = idx+1; i < array->size; i++) {
+ temp[new_i++] = array->data[i];
+ }
+ free(array->data);
+ array->data = temp;
+ array->size = new_i;
+ return ret;
+};
\ No newline at end of file
diff --git a/data.h b/data.h
index d488001..e005199 100644
--- a/data.h
+++ b/data.h
@@ -1,6 +1,6 @@
#pragma once
#include
-
+#include
typedef struct CharArray {
size_t size;
size_t capacity;
@@ -11,4 +11,8 @@ char_array_t *char_array_create(int size);
void char_array_destroy(char_array_t *array);
void char_array_append(char_array_t *array, char *value, size_t length);
void char_array_print(const char_array_t *array);
-void char_array_wipe(char_array_t *array);
\ No newline at end of file
+void char_array_wipe(char_array_t *array);
+bool char_array_has_char(char_array_t *array, char c);
+char *char_array_get_until_char(char_array_t *array, char c);
+
+SOCKET get_listen_socket();
\ No newline at end of file
diff --git a/echo_server_test.py b/echo_server_test.py
new file mode 100644
index 0000000..a0eee28
--- /dev/null
+++ b/echo_server_test.py
@@ -0,0 +1,55 @@
+import socket
+import time
+
+def test_echo_server(host='localhost', port=40000, message="Hello, Echo Server!"):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ try:
+ s.connect((host, port))
+ print(f"Connected to {host}:{port}")
+
+ # Send the message
+ print(f"Sending message of length: {len(message)}")
+ s.sendall(message.encode())
+ s.shutdown(socket.SHUT_WR)
+
+
+ # Receive the response in chunks
+ chunks = []
+ bytes_received = 0
+ while bytes_received < len(message):
+ chunk = s.recv(1024)
+ if not chunk:
+ break
+ chunks.append(chunk)
+ bytes_received += len(chunk)
+ time.sleep(0.1) # Match the server's Sleep(100)
+
+ response = b''.join(chunks).decode()
+ print(f"Received {len(response)} bytes")
+
+ # Check if it's a true echo
+ if response == message:
+ print("SUCCESS: Received message matches sent message!")
+ else:
+ print("FAILURE: Received message differs from sent message!")
+ if len(response) != len(message):
+ print(f"Length mismatch: sent {len(message)}, received {len(response)}")
+
+ except ConnectionRefusedError:
+ print("Connection failed! Make sure the server is running.")
+ except Exception as e:
+ print(f"An error occurred: {e}")
+
+if __name__ == "__main__":
+ # Test with a simple message
+ test_echo_server()
+
+ # Test with a longer message
+ test_echo_server(message="This is a longer message to test the echo server's ability to handle larger strings!")
+
+ # Test with special characters
+ test_echo_server(message="Special chars: !@#$%^&*()")
+
+ # Test with a large message
+ large_message = "X" * 10000 # 10KB of data
+ test_echo_server(message=large_message)
\ No newline at end of file
diff --git a/main.c b/main.c
deleted file mode 100644
index b9ff1bd..0000000
--- a/main.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include
-#include
-#include
-#include "main.h"
-#include "data.h"
-
-#define PORT 40000
-#define BUFFER_SIZE 1024
-
-
-int main()
-{
- // load_file();
-
- WSADATA WSAData;
-
- SOCKET client;
-
- SOCKADDR_IN serverAddr, clientAddr;
-
- WSAStartup(MAKEWORD(2,0), &WSAData);
- SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
-
- serverAddr.sin_addr.s_addr = INADDR_ANY;
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(PORT);
-
- bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
- listen(server, 0);
-
- printf("Listening for incoming connections...\n");
-
- char buffer[BUFFER_SIZE] = {0};
- int clientAddrSize = sizeof(clientAddr);
- int recieved;
- char_array_t *reply = char_array_create(1024);
- while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET)
- {
- printf(" Client connected!\n");
- while ((recieved = recv(client, buffer, sizeof(buffer), 0)) > 0) {
- printf(" Client says: |%.1024s|\n",buffer);
- char_array_append(reply, buffer, recieved);
- if (buffer[recieved] == '\0') {
- break;
- }
- memset(buffer, 0, sizeof(buffer));
- Sleep(10);
- }
-
- printf(" Sending back...\n");
-
- printf(" Sending back: |%d| \n", reply->size);
- send(client, reply->data,reply->size,0);
- char_array_wipe(reply);
-
- closesocket(client);
- printf("Client disconnected.\n");
- }
-}
-
-void echo(SOCKET client) {
- char buffer[BUFFER_SIZE] = {0};
- char_array_t *reply = char_array_create(BUFFER_SIZE);
- int bytesReceived;
- while ((bytesReceived = recv(client, buffer, sizeof(buffer), 0)) > 0) {
- printf(" Client says: |%.1024s|\n",buffer);
- char_array_append(reply, buffer, bytesReceived);
- if (buffer[bytesReceived] == '\0') {
- break;
- }
- memset(buffer, 0, sizeof(buffer));
- Sleep(10);
- }
- printf(" Sending back...\n");
-
- printf(" Sending back: |%llu| \n", reply->size);
- send(client, reply->data,reply->size,0);
- closesocket(client);
-}
\ No newline at end of file
diff --git a/main.h b/main.h
deleted file mode 100644
index f7ecf77..0000000
--- a/main.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Created by Ajurna on 27/07/2025.
-//
-
-#ifndef MAIN_H
-#define MAIN_H
-
-#endif //MAIN_H
-
-
-typedef struct ReplyArray {
- size_t size;
- size_t capacity;
- char *data;
-} array_t;
-
-array_t *array_create(int size);
-void array_destroy(array_t *array);
-void array_append(array_t *array, char *value, size_t length);
-void array_print(const array_t *array);
-void array_wipe(array_t *array);
\ No newline at end of file
diff --git a/parallel_echo_client_test.py b/parallel_echo_client_test.py
new file mode 100644
index 0000000..8f7f6f1
--- /dev/null
+++ b/parallel_echo_client_test.py
@@ -0,0 +1,84 @@
+import socket
+import threading
+import time
+import random
+import string
+
+def random_string(length):
+ """Generate a random string of fixed length"""
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
+
+def echo_client(client_id, message):
+ """Individual client function that connects and sends/receives data"""
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ try:
+ s.connect(('localhost', 40000))
+ print(f"Client {client_id}: Connected")
+
+ # Send the message
+ print(f"Client {client_id}: Sending message of length {len(message)}")
+ s.sendall(message.encode())
+
+ # Receive the response in chunks
+ chunks = []
+ bytes_received = 0
+ while bytes_received < len(message):
+ chunk = s.recv(1024)
+ if not chunk:
+ break
+ chunks.append(chunk)
+ bytes_received += len(chunk)
+ time.sleep(0.1)
+
+ response = b''.join(chunks).decode()
+
+ # Verify response
+ if response == message:
+ print(f"Client {client_id}: SUCCESS - Message verified ({len(response)} bytes)")
+ else:
+ print(f"Client {client_id}: FAILURE - Message mismatch!")
+ print(f"Client {client_id}: Expected length: {len(message)}, Got: {len(response)}")
+
+ except Exception as e:
+ print(f"Client {client_id}: Error - {str(e)}")
+
+def run_parallel_test(num_clients=5, message_size_range=(100, 5000)):
+ """Run multiple clients in parallel"""
+ threads = []
+
+ print(f"Starting parallel test with {num_clients} clients...")
+
+ # Create and start threads
+ for i in range(num_clients):
+ # Generate random message size between min and max range
+ msg_size = random.randint(*message_size_range)
+ message = random_string(msg_size)
+
+ thread = threading.Thread(target=echo_client, args=(i, message))
+ threads.append(thread)
+ thread.start()
+ # Small delay between starting threads
+ time.sleep(0.1)
+
+ # Wait for all threads to complete
+ for thread in threads:
+ thread.join()
+
+ print("All clients finished")
+
+if __name__ == "__main__":
+ # Test 1: Few clients with small messages
+ print("\nTest 1: 3 parallel clients with small messages")
+ run_parallel_test(num_clients=3, message_size_range=(100, 500))
+
+ time.sleep(1) # Wait between tests
+
+ # Test 2: More clients with varying message sizes
+ print("\nTest 2: 5 parallel clients with varying message sizes")
+ run_parallel_test(num_clients=5, message_size_range=(1000, 5000))
+
+ time.sleep(1) # Wait between tests
+
+ # Test 3: Stress test with many clients
+ print("\nTest 3: Stress test with 10 parallel clients")
+ run_parallel_test(num_clients=10, message_size_range=(500, 10000))
diff --git a/prime_time_server_tests.py b/prime_time_server_tests.py
new file mode 100644
index 0000000..758d433
--- /dev/null
+++ b/prime_time_server_tests.py
@@ -0,0 +1,163 @@
+import socket
+import json
+import threading
+import time
+import random
+
+def send_request(sock, request):
+ """Send a request and get response"""
+ request_str = json.dumps(request) + '\n'
+ sock.sendall(request_str.encode())
+
+ response = sock.recv(1024).decode()
+ try:
+ return json.loads(response.strip())
+ except json.JSONDecodeError:
+ return response.strip()
+
+def batch_test_client():
+ """Run a test with 50 problems in quick succession"""
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ try:
+ sock.connect(('localhost', 40000))
+ print("Batch Test: Connected")
+
+ # Generate 50 test cases with known prime and non-prime numbers
+ test_numbers = (
+ # Known primes
+ [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47] +
+ # Non-primes
+ [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25] +
+ # Edge cases
+ [0, 1, -1, 1.5, 2.0] +
+ # Larger numbers
+ [97, 100, 121, 169, 289, 361, 529, 841, 961, 1001] +
+ # Random numbers to complete 50
+ [random.randint(1000, 10000) for _ in range(5)]
+ )
+
+ success_count = 0
+ start_time = time.time()
+
+ for i, number in enumerate(test_numbers):
+ request = {"method": "isPrime", "number": number}
+
+ try:
+ response = send_request(sock, request)
+ expected_prime = (
+ isinstance(number, int) and
+ number > 1 and
+ all(number % i != 0 for i in range(2, int(number ** 0.5) + 1))
+ )
+ expected = {"method": "isPrime", "prime": expected_prime}
+
+ if response == expected:
+ success_count += 1
+ print(f"✓ Test {i+1}/50: {number} -> {response['prime']}")
+ else:
+ print(f"✗ Test {i+1}/50: {number} Expected: {expected}, Got: {response}")
+
+ except Exception as e:
+ print(f"Error on test {i+1}/50 with number {number}: {e}")
+ break
+
+ end_time = time.time()
+ duration = end_time - start_time
+
+ print(f"\nBatch Test Results:")
+ print(f"Total tests: 50")
+ print(f"Successful: {success_count}")
+ print(f"Failed: {50 - success_count}")
+ print(f"Time taken: {duration:.2f} seconds")
+ print(f"Average time per request: {(duration/50)*1000:.2f} ms")
+
+ except ConnectionRefusedError:
+ print("Batch Test: Connection failed! Is the server running?")
+
+def test_client(test_cases, client_id):
+ """Run a series of test cases"""
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ try:
+ sock.connect(('localhost', 40000))
+ print(f"Client {client_id}: Connected")
+
+ for i, test in enumerate(test_cases):
+ request = test['request']
+ expected = test['expected']
+ desc = test.get('desc', 'No description')
+
+ print(f"\nClient {client_id}: Test {i + 1} - {desc}")
+ print(f"Request: {request}")
+
+ try:
+ response = send_request(sock, request)
+ print(f"Response: {response}")
+
+ if test.get('should_disconnect', False):
+ try:
+ send_request(sock, {"method": "isPrime", "number": 2})
+ print("ERROR: Server didn't disconnect when it should have")
+ except:
+ print("SUCCESS: Server correctly disconnected")
+ break
+
+ if response == expected:
+ print("SUCCESS: Response matches expected")
+ else:
+ print(f"FAILURE: Expected {expected}, got {response}")
+
+ except Exception as e:
+ print(f"Error during test: {e}")
+ if test.get('should_disconnect', False):
+ print("SUCCESS: Expected disconnect occurred")
+ else:
+ print("FAILURE: Unexpected error")
+ break
+
+ except ConnectionRefusedError:
+ print(f"Client {client_id}: Connection failed! Is the server running?")
+
+def run_all_tests():
+ print("Starting Prime Time Server tests...")
+
+ # Test 1: Basic functionality
+ print("\nTest 1: Single client with valid requests")
+ test_client([{
+ 'desc': "Basic prime test",
+ 'request': {"method": "isPrime", "number": 7},
+ 'expected': {"method": "isPrime", "prime": True}
+ }], 0)
+
+ time.sleep(1)
+
+ # Test 2: Malformed request
+ print("\nTest 2: Single client with malformed request")
+ test_client([{
+ 'desc': "Malformed request test",
+ 'request': {"method": "wrong", "number": 7},
+ 'expected': "malformed",
+ 'should_disconnect': True
+ }], 0)
+
+ time.sleep(1)
+
+ # Test 3: Batch test with 50 problems
+ print("\nTest 3: Batch test with 50 problems")
+ batch_test_client()
+
+ time.sleep(1)
+
+ # Test 4: Multiple parallel clients
+ print("\nTest 4: Multiple parallel clients")
+ threads = []
+ for i in range(5):
+ thread = threading.Thread(target=batch_test_client)
+ threads.append(thread)
+ thread.start()
+ time.sleep(0.1)
+
+ for thread in threads:
+ thread.join()
+
+if __name__ == "__main__":
+ run_all_tests()
\ No newline at end of file
diff --git a/server00.c b/server00.c
new file mode 100644
index 0000000..5c8a61b
--- /dev/null
+++ b/server00.c
@@ -0,0 +1,68 @@
+#include
+#include
+#include
+#include "server00.h"
+#include "data.h"
+
+#define PORT 40000
+#define BUFFER_SIZE 1024
+
+
+
+int main()
+{
+ // load_file();
+
+ WSADATA WSAData;
+
+ SOCKET client;
+
+ SOCKADDR_IN serverAddr, clientAddr;
+
+ WSAStartup(MAKEWORD(2,0), &WSAData);
+ SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
+
+ serverAddr.sin_addr.s_addr = INADDR_ANY;
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_port = htons(PORT);
+
+ bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
+ listen(server, 0);
+
+ printf("Listening for incoming connections...\n");
+
+ int clientAddrSize = sizeof(clientAddr);
+ int connection_number = 0;
+ char_array_t *reply = char_array_create(1024);
+ while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET)
+ {
+ struct EchoArgs *args = malloc(sizeof(struct EchoArgs));
+ args->client = client;
+ args->connection = connection_number++;
+ pthread_t thread;
+ pthread_create(&thread, nullptr, echo,(void *) args);
+ }
+}
+
+void *echo(void *args) {
+ const auto echoArgs = (struct EchoArgs *) args;
+ char buffer[BUFFER_SIZE] = {0};
+ char_array_t *reply = char_array_create(BUFFER_SIZE);
+ int bytesReceived;
+ int bytesTotal = 0;
+ while ((bytesReceived = recv(echoArgs->client, buffer, sizeof(buffer), 0)) > 0) {
+ // printf(" Client {%d} says: |%.1024s|\n", echoArgs->connection ,buffer);
+ printf("Client sent {%d}: |%d| \n", echoArgs->connection, bytesReceived);
+
+ char_array_append(reply, buffer, bytesReceived);
+ bytesTotal += bytesReceived;
+ memset(buffer, 0, sizeof(buffer));
+ Sleep(20);
+ }
+ printf("Total bytes received {%d}: %d\n", echoArgs->connection, bytesTotal);
+ printf("Sending back {%d}: |%llu| \n", echoArgs->connection, reply->size);
+ send(echoArgs->client, reply->data,reply->size,0);
+ closesocket(echoArgs->client);
+ free(echoArgs);
+ return NULL;
+}
\ No newline at end of file
diff --git a/server00.h b/server00.h
new file mode 100644
index 0000000..7c63a30
--- /dev/null
+++ b/server00.h
@@ -0,0 +1,17 @@
+//
+// Created by Ajurna on 27/07/2025.
+//
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#endif //MAIN_H
+#include
+#pragma once
+
+struct EchoArgs {
+ int connection;
+ SOCKET client;
+};
+
+void *echo(void *args);
\ No newline at end of file
diff --git a/server01.c b/server01.c
new file mode 100644
index 0000000..42076cb
--- /dev/null
+++ b/server01.c
@@ -0,0 +1,124 @@
+//
+// Created by PeterDwyer on 28/07/2025.
+//
+
+#include "server01.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "data.h"
+
+#define IS_PRIME "{\"method\":\"isPrime\",\"prime\":true}\n"
+#define IS_NOT_PRIME "{\"method\":\"isPrime\",\"prime\":false}\n"
+#define IS_PRIME_ERROR "{\"method\":\"isPrime\",\"error\":true}\n"
+int main() {
+ SOCKET server = get_listen_socket();
+ SOCKADDR_IN serverAddr, clientAddr;
+ SOCKET client;
+ int clientAddrSize = sizeof(clientAddr);
+ int connection_number = 1;
+ while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET)
+ {
+ handle_args_t *args = malloc(sizeof(handle_args_t));
+ args->client = client;
+ args->connection = connection_number++;
+ pthread_t thread;
+ pthread_create(&thread, nullptr, handle_connection, args);
+ }
+ return 0;
+}
+
+void *handle_connection(void *args) {
+ handle_args_t *handleArgs = args;
+ char buffer[1024] = {0};
+ int bytesReceived;
+ char_array_t *data = char_array_create(1024);
+ while ((bytesReceived = recv(handleArgs->client, buffer, sizeof(buffer), 0)) > 0) {
+ printf("Client sent {%d}: |%d| \n", handleArgs->connection, bytesReceived);
+ char_array_append(data, buffer, bytesReceived);
+ char *request;
+ while ((request = char_array_get_until_char(data, '\n')) != NULL) {
+ parse_request(handleArgs, request, data);
+ }
+
+
+
+ memset(buffer, 0, sizeof(buffer));
+ }
+ pthread_exit(NULL);
+}
+
+void parse_request(handle_args_t *handleArgs, const char *request, char_array_t *data) {
+ if (request != NULL) {
+ const json_object *obj = json_tokener_parse(request);
+ if (obj == NULL) {
+ printf("{%d} Failed to parse json\n", handleArgs->connection);
+ send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0);
+ char_array_destroy(data);
+ closesocket(handleArgs->client);
+ pthread_exit(NULL);
+ }
+ json_object *method_obj = json_object_object_get(obj, "method");
+ json_object *number_obj = json_object_object_get(obj, "number");
+ if (method_obj == NULL || number_obj == NULL) {
+ printf("{%d} Missing Fields\n", handleArgs->connection);
+ send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0);
+ char_array_destroy(data);
+ closesocket(handleArgs->client);
+ pthread_exit(NULL);
+ }
+ const int number_type = json_object_get_type(number_obj);
+ if (!(json_object_is_type(method_obj, json_type_string) && (number_type== json_type_double || number_type == json_type_int))) {
+ printf("{%d} Fields Wrong Type\n", handleArgs->connection);
+ send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0);
+ char_array_destroy(data);
+ closesocket(handleArgs->client);
+ pthread_exit(NULL);
+ }
+ const char *method = json_object_get_string(method_obj);
+ if (strcmp(method, "isPrime") != 0) {
+ printf("{%d} Invalid method\n", handleArgs->connection);
+ send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0);
+ char_array_destroy(data);
+ closesocket(handleArgs->client);
+ }
+ if (number_type == json_type_double) {
+ printf("{%d} Floats cannot be prime\n", handleArgs->connection);
+ send(handleArgs->client, IS_NOT_PRIME, strlen(IS_NOT_PRIME), 0);
+ }
+ const int number = json_object_get_int(number_obj);
+ bool number_is_prime;
+ if (number == INT32_MAX) {
+ number_is_prime = false;
+ } else {
+ number_is_prime = is_prime(number);
+ }
+
+ printf("{%d} '%d' is prime: %d\n", handleArgs->connection, number, number_is_prime);
+ char *response = number_is_prime ? IS_PRIME : IS_NOT_PRIME;
+ send(handleArgs->client, response, strlen(response), 0);
+ }
+}
+
+bool is_prime(const int number) {
+ if (number == 2) {
+ return true;
+ }
+ if (number < 2 || number % 2 == 0) {
+ return false;
+ }
+
+ const int limit = (int)sqrt(number);
+ for (int i = 3; i <= limit; i+=2) {
+ if (number % i == 0) {
+ return false;
+ }
+ }
+ return true;
+}
\ No newline at end of file
diff --git a/server01.h b/server01.h
new file mode 100644
index 0000000..d48814c
--- /dev/null
+++ b/server01.h
@@ -0,0 +1,21 @@
+//
+// Created by PeterDwyer on 28/07/2025.
+//
+
+#ifndef SERVER01_H
+#define SERVER01_H
+#include
+
+#include "data.h"
+#pragma once
+
+typedef struct HandleArgs {
+ int connection;
+ SOCKET client;
+} handle_args_t;
+
+#endif //SERVER01_H
+
+bool is_prime(const int number);
+void *handle_connection(void *args);
+void parse_request(handle_args_t *handleArgs, const char *request, char_array_t *data);
\ No newline at end of file