Final - PT1
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user