diff --git a/CMakeLists.txt b/CMakeLists.txt index 4658344..08b0afe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(server00 server00.c target_link_libraries(server00 wsock32 ws2_32) find_package(json-c CONFIG REQUIRED) +find_package(PCRE2 CONFIG REQUIRED 8BIT) add_executable(server01 server01.c @@ -32,5 +33,5 @@ target_link_libraries(server03 wsock32 ws2_32) add_executable(server04 server04.c server04.h ${COMMON_SOURCES}) target_link_libraries(server04 wsock32 ws2_32) -add_executable(server05 server05.c server05.h) -target_link_libraries(server05 wsock32 ws2_32) +add_executable(server05 server05.c server05.h ${COMMON_SOURCES}) +target_link_libraries(server05 wsock32 ws2_32 PCRE2::8BIT) diff --git a/server05.c b/server05.c index 61c3195..6b0c44c 100644 --- a/server05.c +++ b/server05.c @@ -7,20 +7,176 @@ #include #include #include "data.h" +#include +#include +#include +#define PCRE2_CODE_UNIT_WIDTH 8 +#include + + +const char *newline = "\n"; +const char *bogus_address = "7YWHMfk9JZe0LM0g1ZauHuiSxhI"; + int main() { SOCKET server = get_listen_socket(); SOCKADDR_IN clientAddr; SOCKET client; int clientAddrSize = sizeof(clientAddr); int connection_number = 1; + + char *message = "Please pay the ticket price of 15 Boguscoins to one of these addresses: 7ABnYzozPt2cyDHQqDq2ExIMz53xXVcErn 7z6kM0VlNJpZiqTEHmRjxW9FbVCkv2flb 7qReHdk11Ai67nRvvfTQXFjPZH3X"; + char *new_message = replace_bogus_coin(message); + // replace_bogus_coin(message); + printf("%s\n", new_message); + // exit(0); printf("Listening for incoming connections...\n"); while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET) { handle_args_t *args = malloc(sizeof(handle_args_t)); args->client = client; + args->server = get_chat_socket(); args->connection = connection_number++; pthread_t thread; - pthread_create(&thread, nullptr, handle_connection, args); + pthread_create(&thread, nullptr, handle_server, args); + pthread_create(&thread, nullptr, handle_client, args); } return 0; +} + +void *handle_server(void *args) { + handle_args_t *handleArgs = args; + char buffer[1024] = {}; + int bytesReceived; + printf("{%d} Server connected\n", handleArgs->connection); + char_array_t *data = char_array_create(1024); + while ((bytesReceived = recv(handleArgs->server, buffer, sizeof(buffer), 0)) > 0) { + printf("server 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) { + printf("{%d} server Said: %s\n", handleArgs->connection, request); + request = replace_bogus_coin(request); + send(handleArgs->client, request, strlen(request), 0); + send(handleArgs->client, newline, strlen(newline), 0); + free(request); + } + memset(buffer, 0, sizeof(buffer)); + } + // closesocket(handleArgs->server); + return nullptr; +} + +char *replace_bogus_coin(char *message) { + pcre2_code *re; + PCRE2_SPTR pattern = (PCRE2_SPTR)"\\b7\\w{25,34}\\b"; + PCRE2_SPTR subject = (PCRE2_SPTR)message; + size_t subject_length = strlen((char *)subject); + int errornumber; + PCRE2_SIZE erroroffset; + PCRE2_SIZE *ovector; + int rc; + size_t offset = 0; // Keep track of where we are in the string + + // Compile the pattern + re = pcre2_compile( + pattern, + PCRE2_ZERO_TERMINATED, + 0, + &errornumber, + &erroroffset, + NULL); + + if (re == NULL) { + PCRE2_UCHAR buff[256]; + pcre2_get_error_message(errornumber, buff, sizeof(buff)); + printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset, buff); + return message; + } + + // Create match data block + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re, NULL); + char *result = strdup(message); // Create a copy of the original message + + // Loop until no more matches are found + while (offset < subject_length) { + rc = pcre2_match( + re, + subject, + subject_length, + offset, // Start from last match position + 0, + match_data, + NULL); + + if (rc < 0) { + break; // No more matches + } + + ovector = pcre2_get_ovector_pointer(match_data); + PCRE2_SIZE start = ovector[0]; + PCRE2_SIZE end = ovector[1]; + + // Replace the matched text with bogus_address + char *temp = calloc(strlen(result) + strlen(bogus_address) + 1, sizeof(char)); + strncpy(temp, result, start); + strcat(temp, bogus_address); + strcat(temp, result + end); + + free(result); + result = temp; + + // Update the subject and length for next iteration + subject = (PCRE2_SPTR)result; + subject_length = strlen(result); + offset = start + strlen(bogus_address); + } + + // Clean up + pcre2_match_data_free(match_data); + pcre2_code_free(re); + + return result; +} + +void *handle_client(void *args) { + handle_args_t *handleArgs = args; + char buffer[1024] = {}; + int bytesReceived; + printf("{%d} Client connected\n", handleArgs->connection); + char_array_t *data = char_array_create(1024); + while ((bytesReceived = recv(handleArgs->client, buffer, sizeof(buffer), 0)) > 0) { + printf("server 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) { + printf("{%d} client Said: %s\n", handleArgs->connection, request); + request = replace_bogus_coin(request); + send(handleArgs->server, request, strlen(request), 0); + send(handleArgs->server, newline, strlen(newline), 0); + free(request); + } + memset(buffer, 0, sizeof(buffer)); + } + // closesocket(handleArgs->client); + return nullptr; +} + + + +SOCKET get_chat_socket() { + WSADATA WSAData; + + SOCKADDR_IN serverAddr; + struct hostent * host = gethostbyname("chat.protohackers.com"); + WSAStartup(MAKEWORD(2,0), &WSAData); + SOCKET server = socket(AF_INET, SOCK_STREAM, 0 ); + serverAddr.sin_addr.s_addr = AF_INET; + serverAddr.sin_family = AF_INET; + memcpy(&serverAddr.sin_addr.s_addr, host->h_addr_list[0], host->h_length); + + serverAddr.sin_port = htons(16963); + + connect(server, (SOCKADDR *) & serverAddr, sizeof (serverAddr)); + return server; } \ No newline at end of file diff --git a/server05.h b/server05.h index b7e5265..ee44faf 100644 --- a/server05.h +++ b/server05.h @@ -4,9 +4,28 @@ #ifndef SERVER05_H #define SERVER05_H +#include #endif //SERVER05_H typedef struct HandleArgs { + int connection; + SOCKET client; + SOCKET server; +}handle_args_t; -}handle_args_t; \ No newline at end of file +typedef struct BogusLocation { + size_t start; + size_t end; +} bogus_location_t; + +typedef enum SearchState { + START, + END +} search_state_t; + +void *handle_server(void *args); +void *handle_client(void *args); +void send_message(SOCKET dest, const char *message); +char *replace_bogus_coin(char *message); +SOCKET get_chat_socket();