Final - PT1

This commit is contained in:
2025-12-03 19:30:55 +00:00
parent e51553d06e
commit e43a360189
2 changed files with 70 additions and 20 deletions
BIN
View File
Binary file not shown.
+70 -20
View File
@@ -5,6 +5,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
@@ -16,9 +17,9 @@
// Program Settings
#define BOUND_IP "10.4.78.8"
#define PORT 5000
#define PORT 8000
#define DEBUG 1 // Controls Optional Debug Output
#define DEBUG 0 // Controls Optional Debug Output
// Constants
#define REQ_HTTP_START_LINE_METHOD_LENGTH 8
@@ -26,6 +27,7 @@
#define REQ_HTTP_START_LINE_VERSION_LENGTH 16
#define REQ_HTTP_START_LINE_EXTRA_CHARS 4
#define REQ_HTTP_START_LINE_SEPARATOR ' '
#define REQ_HTTP_REQ_MESSAGE_BODY_LENGTH 8192
#define RES_HTTP_START_LINE_VERSION_LENGTH 16
#define RES_HTTP_START_LINE_STATUS_CODE_LENGTH 4
@@ -34,15 +36,12 @@
#define HTTP_HEADER_FIELD_SEPARATOR ": "
#define HTTP_HEADER_FIELD_NAME_LENGTH 256
#define HTTP_HEADER_FIELD_VALUE_LENGTH 1024
#define HTTP_HEADER_FIELD_EXTRA_CHARS 4
#define HTTP_HEADER_LINE_ENDING "\r\n"
#define HTTP_MESSAGE_MAX_HEADERS 100
#define HTTP_MESSAGE_BODY_LENGTH 8192
#define HTTP_BODY_SEPARATOR "\r\n\r\n"
#define MAX_MESSAGE_SIZE 20000
#define MAX_MESSAGE_COUNT 10
// Structs
struct req_http_start_line {
@@ -66,14 +65,15 @@ struct req_http_message {
struct req_http_start_line start_line;
struct http_header headers[HTTP_MESSAGE_MAX_HEADERS];
int header_count;
char body[HTTP_MESSAGE_BODY_LENGTH];
char body[REQ_HTTP_REQ_MESSAGE_BODY_LENGTH];
};
struct res_http_message {
struct res_http_start_line start_line;
struct http_header headers[HTTP_MESSAGE_MAX_HEADERS];
int header_count;
char body[HTTP_MESSAGE_BODY_LENGTH];
char *body;
int body_length;
};
struct http_forward_info {
@@ -107,7 +107,6 @@ struct req_http_start_line parse_req_http_start_line(char *start_line_unparsed)
memcpy(start_line.version, version_start, line_end);
start_line.version[line_end] = '\0';
// Debug: Print All Parts
if (DEBUG) {
printf(" Parsed HTTP Start Line:\n");
printf(" Method: %s\n", start_line.method);
@@ -139,7 +138,7 @@ struct http_header parse_http_header(char *header_str) {
// Parse HTTP Headers from Message String
int parse_http_headers(char *message_str, struct http_header *headers) {
// Find start of headers (after first \r\n)
// Find start of headers
char *headers_start = strstr(message_str, HTTP_HEADER_LINE_ENDING) + 2;
char *headers_end = strstr(headers_start, HTTP_BODY_SEPARATOR);
@@ -169,9 +168,19 @@ int parse_http_headers(char *message_str, struct http_header *headers) {
return header_count;
}
// Get Content-Length from headers
int get_content_length(struct res_http_message message) {
for (int i = 0; i < message.header_count; i++) {
if (strcasecmp(message.headers[i].field_name, "Content-Length") == 0) {
return atoi(message.headers[i].field_value);
}
}
return -1;
}
// Parse HTTP Body from Message String
void parse_http_body(char *message_str, char *body) {
// Find start of headers (after first \r\n)
// Find start of headers
char *headers_start = strstr(message_str, HTTP_HEADER_LINE_ENDING) + 2;
char *headers_end = strstr(headers_start, HTTP_BODY_SEPARATOR);
@@ -187,6 +196,29 @@ void parse_http_body(char *message_str, char *body) {
}
}
// Parse HTTP Response Body
void parse_http_response_body(char *message_str, struct res_http_message *message) {
// Find start of headers and body
char *headers_start = strstr(message_str, HTTP_HEADER_LINE_ENDING) + 2;
char *headers_end = strstr(headers_start, HTTP_BODY_SEPARATOR);
char *body_start = headers_end + strlen(HTTP_BODY_SEPARATOR);
// Get Content-Length from headers
int content_length = get_content_length(*message);
// Use Content-Length to determine body size
message->body_length = content_length;
message->body = malloc(content_length + 1);
memcpy(message->body, body_start, content_length);
message->body[content_length] = '\0';
if (DEBUG) {
printf(" Parsed HTTP Response Body:\n");
printf(" Content-Length: %d\n", content_length);
printf(" Actual Body Length: %d\n", message->body_length);
}
}
// Construct HTTP Message from String
struct req_http_message create_req_http_message_from_string(char *message_str) {
struct req_http_message message;
@@ -303,7 +335,9 @@ void res_http_message_to_string(struct res_http_message message, char *message_s
strcat(message_str, HTTP_HEADER_LINE_ENDING);
// Body
strcat(message_str, message.body);
if (message.body_length > 0) {
strncat(message_str, message.body, message.body_length);
}
}
// Construct RES Start Line
@@ -353,14 +387,20 @@ struct res_http_message create_res_http_message_from_string(char *message_str) {
message.header_count = parse_http_headers(message_str, message.headers);
// Parse Body
parse_http_body(message_str, message.body);
parse_http_response_body(message_str, &message);
return message;
}
// Forward Message and Await Response
struct res_http_message forward_message_await_response(struct http_forward_info forward_info) {
char response_buffer[MAX_MESSAGE_SIZE];
// Start with initial buffer size
int buffer_size = MAX_MESSAGE_SIZE;
char *response_buffer = malloc(buffer_size);
if (!response_buffer) {
perror("Failed to allocate response buffer");
exit(1);
}
// Convert HTTP Message Struct to String
char message_str[MAX_MESSAGE_SIZE];
@@ -375,29 +415,39 @@ struct res_http_message forward_message_await_response(struct http_forward_info
sa.sin_port = htons(forward_info.port);
inet_pton(AF_INET, forward_info.host, &(sa.sin_addr));
int recv_size = connect(my_sock, (struct sockaddr *)&sa, sizeof(sa));
printf("CONNECT: Origin Server Connected\n");
// Send Message to Origin Server
send(my_sock, message_str, strlen(message_str), 0);
if (DEBUG) printf("FORWARD: Message Sent to Origin Server\n");
// Await Response from Origin Server
memset(response_buffer, 0, MAX_MESSAGE_SIZE);
// Await Response from Origin Server with dynamic buffer expansion
memset(response_buffer, 0, buffer_size);
int total_received = 0;
int bytes_received;
while ((bytes_received = recv(my_sock, response_buffer + total_received, MAX_MESSAGE_SIZE - total_received - 1, 0)) > 0) {
while ((bytes_received = recv(my_sock, response_buffer + total_received, buffer_size - total_received - 1, 0)) > 0) {
total_received += bytes_received;
// Check if we need to expand the buffer
if (total_received >= buffer_size - 1000) {
buffer_size *= 2;
char *new_buffer = realloc(response_buffer, buffer_size);
response_buffer = new_buffer;
}
}
response_buffer[total_received] = '\0';
printf("RECEIVE: Response Received from Origin Server\n");
if (DEBUG) {
printf("FORWARD: Response Received from Origin Server (%d bytes)\n", total_received);
printf("RESPONSE:\n");
printf("%s\n", response_buffer);
}
struct res_http_message response_message = create_res_http_message_from_string(response_buffer);
// Clean up
free(response_buffer);
close(my_sock);
printf("DISCONNECT: Origin Server Disconnected\n");
return response_message;
}
@@ -437,7 +487,7 @@ int main(int argc, char *argv[]) {
printf("WAIT: Waiting for incoming connections...\n");
int c = sizeof(struct sockaddr_in);
client_sock = accept(serv_sock, (struct sockaddr *)&client, &c);
printf("CONNECT: Connection Accepted\n");
printf("CONNECT: Client Connected\n");
// Receive Message from Client
memset(client_message, 0, sizeof(client_message));
@@ -457,7 +507,7 @@ int main(int argc, char *argv[]) {
struct res_http_message origin_response = forward_message_await_response(relay_message);
// Send Response Back to Client
char response_str[MAX_MESSAGE_SIZE];
char response_str[origin_response.body_length + MAX_MESSAGE_SIZE];
res_http_message_to_string(origin_response, response_str);
send(client_sock, response_str, strlen(response_str), 0);
printf("RESPONSE: Response Sent Back to Client\n");