First Working Version
This commit is contained in:
@@ -12,36 +12,409 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Program Settings
|
||||
#define BOUND_IP "10.4.78.8"
|
||||
#define PORT 5000
|
||||
|
||||
#define DEBUG 1 // Controls Optional Debug Output
|
||||
|
||||
// Constants
|
||||
#define PORT 5000
|
||||
#define DEBUG 0
|
||||
#define REQ_HTTP_START_LINE_METHOD_LENGTH 8
|
||||
#define REQ_HTTP_START_LINE_PATH_LENGTH 1024
|
||||
#define REQ_HTTP_START_LINE_VERSION_LENGTH 16
|
||||
#define REQ_HTTP_START_LINE_EXTRA_CHARS 4
|
||||
#define REQ_HTTP_START_LINE_SEPARATOR ' '
|
||||
|
||||
// Globals
|
||||
#define RES_HTTP_START_LINE_VERSION_LENGTH 16
|
||||
#define RES_HTTP_START_LINE_STATUS_CODE_LENGTH 4
|
||||
#define RES_HTTP_START_LINE_REASON_PHRASE_LENGTH 64
|
||||
|
||||
#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 http_start_line {
|
||||
char method[8];
|
||||
char path[1024];
|
||||
char version[16];
|
||||
struct req_http_start_line {
|
||||
char method[REQ_HTTP_START_LINE_METHOD_LENGTH];
|
||||
char path[REQ_HTTP_START_LINE_PATH_LENGTH];
|
||||
char version[REQ_HTTP_START_LINE_VERSION_LENGTH];
|
||||
};
|
||||
|
||||
struct res_http_start_line {
|
||||
char version[RES_HTTP_START_LINE_VERSION_LENGTH];
|
||||
char status_code[RES_HTTP_START_LINE_STATUS_CODE_LENGTH];
|
||||
char reason_phrase[RES_HTTP_START_LINE_REASON_PHRASE_LENGTH];
|
||||
};
|
||||
|
||||
struct http_header {
|
||||
char field_name[256];
|
||||
char field_value[1024];
|
||||
char field_name[HTTP_HEADER_FIELD_NAME_LENGTH];
|
||||
char field_value[HTTP_HEADER_FIELD_VALUE_LENGTH];
|
||||
};
|
||||
|
||||
struct http_message {
|
||||
struct http_start_line start_line;
|
||||
struct http_header headers[100];
|
||||
char body[8192];
|
||||
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];
|
||||
};
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
struct http_forward_info {
|
||||
char host[REQ_HTTP_START_LINE_PATH_LENGTH];
|
||||
int port;
|
||||
char transport_protocol[5];
|
||||
struct req_http_message new_message;
|
||||
};
|
||||
|
||||
// Functions
|
||||
struct http_message create_http_message_from_string(char *message_str) {
|
||||
struct http_message message;
|
||||
|
||||
// Construct REQ Start Line
|
||||
struct req_http_start_line parse_req_http_start_line(char *start_line_unparsed) {
|
||||
|
||||
struct req_http_start_line start_line;
|
||||
|
||||
// Method
|
||||
int first_space_seperator = strchr(start_line_unparsed, REQ_HTTP_START_LINE_SEPARATOR) - start_line_unparsed;
|
||||
memcpy(start_line.method, start_line_unparsed, first_space_seperator);
|
||||
start_line.method[first_space_seperator] = '\0';
|
||||
|
||||
// Path
|
||||
char *path_start = start_line_unparsed + first_space_seperator + 1;
|
||||
int second_space_seperator = strchr(path_start, REQ_HTTP_START_LINE_SEPARATOR) - path_start;
|
||||
memcpy(start_line.path, path_start, second_space_seperator);
|
||||
start_line.path[second_space_seperator] = '\0';
|
||||
|
||||
// Version
|
||||
char *version_start = path_start + second_space_seperator + 1;
|
||||
int line_end = strchr(version_start, '\r') - version_start;
|
||||
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);
|
||||
printf(" Path: %s\n", start_line.path);
|
||||
printf(" Version: %s\n", start_line.version);
|
||||
}
|
||||
|
||||
return start_line;
|
||||
}
|
||||
|
||||
// Construct Header from String
|
||||
struct http_header parse_http_header(char *header_str) {
|
||||
struct http_header header;
|
||||
|
||||
// Header Field Name
|
||||
char *separator_pos = strstr(header_str, HTTP_HEADER_FIELD_SEPARATOR);
|
||||
int field_name_len = separator_pos - header_str;
|
||||
memcpy(header.field_name, header_str, field_name_len);
|
||||
header.field_name[field_name_len] = '\0';
|
||||
|
||||
// Header Field Value
|
||||
char *field_value_start = separator_pos + strlen(HTTP_HEADER_FIELD_SEPARATOR);
|
||||
int field_value_len = strlen(field_value_start);
|
||||
memcpy(header.field_value, field_value_start, field_value_len);
|
||||
header.field_value[field_value_len] = '\0';
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// Construct HTTP Message from String
|
||||
struct req_http_message create_req_http_message_from_string(char *message_str) {
|
||||
struct req_http_message message;
|
||||
// Parse Start Line
|
||||
int start_line_len = REQ_HTTP_START_LINE_METHOD_LENGTH + REQ_HTTP_START_LINE_PATH_LENGTH + REQ_HTTP_START_LINE_VERSION_LENGTH + REQ_HTTP_START_LINE_EXTRA_CHARS;
|
||||
char start_line_unparsed[start_line_len];
|
||||
memcpy(start_line_unparsed, message_str, start_line_len);
|
||||
message.start_line = parse_req_http_start_line(start_line_unparsed);
|
||||
// Parse Headers
|
||||
|
||||
// Find start of headers (after first \r\n)
|
||||
char *headers_start = strstr(message_str, HTTP_HEADER_LINE_ENDING) + 2;
|
||||
char *headers_end = strstr(headers_start, HTTP_BODY_SEPARATOR);
|
||||
|
||||
// Parse each header line
|
||||
char *current_line = headers_start;
|
||||
int header_count = 0;
|
||||
while (current_line < headers_end && header_count < HTTP_MESSAGE_MAX_HEADERS) {
|
||||
|
||||
char *line_end = strstr(current_line, HTTP_HEADER_LINE_ENDING);
|
||||
if (line_end == NULL || line_end > headers_end) break;
|
||||
|
||||
char current_header_unparsed[HTTP_HEADER_FIELD_NAME_LENGTH + HTTP_HEADER_FIELD_VALUE_LENGTH + 4];
|
||||
memcpy(current_header_unparsed, current_line, line_end - current_line);
|
||||
current_header_unparsed[line_end - current_line] = '\0';
|
||||
|
||||
message.headers[header_count] = parse_http_header(current_header_unparsed);
|
||||
if (DEBUG) {
|
||||
printf(" Parsed HTTP Header %d:\n", header_count + 1);
|
||||
printf(" Field Name: %s\n", message.headers[header_count].field_name);
|
||||
printf(" Field Value: %s\n", message.headers[header_count].field_value);
|
||||
}
|
||||
header_count++;
|
||||
|
||||
current_line = line_end + strlen(HTTP_HEADER_LINE_ENDING);
|
||||
}
|
||||
message.header_count = header_count;
|
||||
|
||||
// Parse body
|
||||
char *body_start = headers_end + strlen(HTTP_BODY_SEPARATOR);
|
||||
int body_len = strlen(body_start);
|
||||
memcpy(message.body, body_start, body_len);
|
||||
message.body[body_len] = '\0';
|
||||
if (DEBUG) {
|
||||
printf(" Parsed HTTP Body:\n");
|
||||
printf(" Body Length: %d\n", body_len);
|
||||
printf(" Body Content: %s\n", message.body);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// Process Message for Relay
|
||||
struct http_forward_info process_for_relay(struct req_http_message received_message) {
|
||||
struct http_forward_info forward_info;
|
||||
forward_info.new_message = received_message;
|
||||
|
||||
// New Transport Protocol
|
||||
char *original_host = memcpy(received_message.start_line.path, received_message.start_line.path, strlen(received_message.start_line.path));
|
||||
char *transport_protocol_end = strstr(original_host, "://") + 3;
|
||||
memcpy(forward_info.transport_protocol, original_host, transport_protocol_end - original_host);
|
||||
|
||||
// New Host
|
||||
char *host_end = strchr(transport_protocol_end, ':');
|
||||
char *port_end = strchr(host_end, '/');
|
||||
memcpy(forward_info.host, transport_protocol_end, host_end - transport_protocol_end);
|
||||
forward_info.host[host_end - transport_protocol_end] = '\0';
|
||||
|
||||
// New Port
|
||||
forward_info.port = atoi(host_end + 1);
|
||||
printf(" Extracted Port: %d\n", forward_info.port);
|
||||
|
||||
// New Path
|
||||
char *entire_host_string_end = strchr(transport_protocol_end, '/');
|
||||
memcpy(forward_info.new_message.start_line.path, entire_host_string_end, strlen(entire_host_string_end));
|
||||
forward_info.new_message.start_line.path[strlen(entire_host_string_end)] = '\0';
|
||||
|
||||
// Strip out Proxy-Connection Header and replace with Connection: Close
|
||||
int new_header_count = 0;
|
||||
for (int i = 0; i < forward_info.new_message.header_count; i++) {
|
||||
if (strcmp(forward_info.new_message.headers[i].field_name, "Proxy-Connection") == 0) {
|
||||
// Replace Proxy-Connection with Connection: close
|
||||
strcpy(forward_info.new_message.headers[new_header_count].field_name, "Connection");
|
||||
strcpy(forward_info.new_message.headers[new_header_count].field_value, "Close");
|
||||
new_header_count++;
|
||||
} else {
|
||||
// Keep the existing header
|
||||
forward_info.new_message.headers[new_header_count] = forward_info.new_message.headers[i];
|
||||
new_header_count++;
|
||||
}
|
||||
}
|
||||
forward_info.new_message.header_count = new_header_count;
|
||||
|
||||
if (DEBUG) {
|
||||
printf(" Processed Forward Info:\n");
|
||||
printf(" Host: %s\n", forward_info.host);
|
||||
printf(" Port: %d\n", forward_info.port);
|
||||
printf(" New Path: %s\n", forward_info.new_message.start_line.path);
|
||||
for (int i = 0; i < forward_info.new_message.header_count; i++) {
|
||||
printf(" Header %d: %s: %s\n", i + 1,
|
||||
forward_info.new_message.headers[i].field_name,
|
||||
forward_info.new_message.headers[i].field_value);
|
||||
}
|
||||
}
|
||||
|
||||
return forward_info;
|
||||
}
|
||||
|
||||
// Convert HTTP REQ Message Struct to String
|
||||
void req_http_message_to_string(struct req_http_message message, char *message_str) {
|
||||
// Start Line
|
||||
sprintf(message_str, "%s %s %s%s", message.start_line.method, message.start_line.path, message.start_line.version, HTTP_HEADER_LINE_ENDING);
|
||||
|
||||
// Headers
|
||||
for (int i = 0; i < message.header_count; i++) {
|
||||
strcat(message_str, message.headers[i].field_name);
|
||||
strcat(message_str, HTTP_HEADER_FIELD_SEPARATOR);
|
||||
strcat(message_str, message.headers[i].field_value);
|
||||
strcat(message_str, HTTP_HEADER_LINE_ENDING);
|
||||
}
|
||||
|
||||
// End of Headers
|
||||
strcat(message_str, HTTP_HEADER_LINE_ENDING);
|
||||
|
||||
// Body
|
||||
strcat(message_str, message.body);
|
||||
}
|
||||
|
||||
// Convert HTTP RES Message Struct to String
|
||||
void res_http_message_to_string(struct res_http_message message, char *message_str) {
|
||||
// Start Line
|
||||
sprintf(message_str, "%s %s %s%s", message.start_line.version, message.start_line.status_code, message.start_line.reason_phrase, HTTP_HEADER_LINE_ENDING);
|
||||
|
||||
// Headers
|
||||
for (int i = 0; i < message.header_count; i++) {
|
||||
strcat(message_str, message.headers[i].field_name);
|
||||
strcat(message_str, HTTP_HEADER_FIELD_SEPARATOR);
|
||||
strcat(message_str, message.headers[i].field_value);
|
||||
strcat(message_str, HTTP_HEADER_LINE_ENDING);
|
||||
}
|
||||
|
||||
// End of Headers
|
||||
strcat(message_str, HTTP_HEADER_LINE_ENDING);
|
||||
|
||||
// Body
|
||||
strcat(message_str, message.body);
|
||||
}
|
||||
|
||||
// Construct RES Start Line
|
||||
struct res_http_start_line parse_res_http_start_line(char *start_line_unparsed) {
|
||||
|
||||
struct res_http_start_line start_line;
|
||||
|
||||
// Version
|
||||
int first_space_seperator = strchr(start_line_unparsed, REQ_HTTP_START_LINE_SEPARATOR) - start_line_unparsed;
|
||||
memcpy(start_line.version, start_line_unparsed, first_space_seperator);
|
||||
start_line.version[first_space_seperator] = '\0';
|
||||
|
||||
// Status Code
|
||||
char *status_code_start = start_line_unparsed + first_space_seperator + 1;
|
||||
int second_space_seperator = strchr(status_code_start, REQ_HTTP_START_LINE_SEPARATOR) - status_code_start;
|
||||
memcpy(start_line.status_code, status_code_start, second_space_seperator);
|
||||
start_line.status_code[second_space_seperator] = '\0';
|
||||
|
||||
// Reason Phrase
|
||||
char *reason_phrase_start = status_code_start + second_space_seperator + 1;
|
||||
int line_end = strchr(reason_phrase_start, '\r') - reason_phrase_start;
|
||||
memcpy(start_line.reason_phrase, reason_phrase_start, line_end);
|
||||
start_line.reason_phrase[line_end] = '\0';
|
||||
|
||||
// Debug: Print All Parts
|
||||
if (DEBUG) {
|
||||
printf(" Parsed HTTP Start Line:\n");
|
||||
printf(" Version: %s\n", start_line.version);
|
||||
printf(" Status Code: %s\n", start_line.status_code);
|
||||
printf(" Reason Phrase: %s\n", start_line.reason_phrase);
|
||||
}
|
||||
|
||||
return start_line;
|
||||
}
|
||||
|
||||
// Construct HTTP RES Message from String
|
||||
struct res_http_message create_res_http_message_from_string(char *message_str) {
|
||||
struct res_http_message message;
|
||||
|
||||
// Parse Start Line
|
||||
int start_line_len = RES_HTTP_START_LINE_VERSION_LENGTH + RES_HTTP_START_LINE_STATUS_CODE_LENGTH + RES_HTTP_START_LINE_REASON_PHRASE_LENGTH + REQ_HTTP_START_LINE_EXTRA_CHARS;
|
||||
char start_line_unparsed[start_line_len];
|
||||
memcpy(start_line_unparsed, message_str, start_line_len);
|
||||
message.start_line = parse_res_http_start_line(start_line_unparsed);
|
||||
|
||||
// Parse Headers
|
||||
|
||||
// Find start of headers (after first \r\n)
|
||||
char *headers_start = strstr(message_str, HTTP_HEADER_LINE_ENDING) + 2;
|
||||
char *headers_end = strstr(headers_start, HTTP_BODY_SEPARATOR);
|
||||
|
||||
// Parse each header line
|
||||
char *current_line = headers_start;
|
||||
int header_count = 0;
|
||||
while (current_line < headers_end && header_count < HTTP_MESSAGE_MAX_HEADERS) {
|
||||
|
||||
char *line_end = strstr(current_line, HTTP_HEADER_LINE_ENDING);
|
||||
if (line_end == NULL || line_end > headers_end) break;
|
||||
|
||||
char current_header_unparsed[HTTP_HEADER_FIELD_NAME_LENGTH + HTTP_HEADER_FIELD_VALUE_LENGTH + 4];
|
||||
memcpy(current_header_unparsed, current_line, line_end - current_line);
|
||||
current_header_unparsed[line_end - current_line] = '\0';
|
||||
|
||||
message.headers[header_count] = parse_http_header(current_header_unparsed);
|
||||
if (DEBUG) {
|
||||
printf(" Parsed HTTP Header %d:\n", header_count + 1);
|
||||
printf(" Field Name: %s\n", message.headers[header_count].field_name);
|
||||
printf(" Field Value: %s\n", message.headers[header_count].field_value);
|
||||
}
|
||||
header_count++;
|
||||
|
||||
current_line = line_end + strlen(HTTP_HEADER_LINE_ENDING);
|
||||
}
|
||||
message.header_count = header_count;
|
||||
|
||||
// Parse body
|
||||
char *body_start = headers_end + strlen(HTTP_BODY_SEPARATOR);
|
||||
int body_len = strlen(body_start);
|
||||
memcpy(message.body, body_start, body_len);
|
||||
message.body[body_len] = '\0';
|
||||
if (DEBUG) {
|
||||
printf(" Parsed HTTP Body:\n");
|
||||
printf(" Body Length: %d\n", body_len);
|
||||
printf(" Body Content: %s\n", message.body);
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
|
||||
// Convert HTTP Message Struct to String
|
||||
char message_str[MAX_MESSAGE_SIZE];
|
||||
req_http_message_to_string(forward_info.new_message, message_str);
|
||||
|
||||
if (DEBUG) printf("FORWARD:\n%s\n", message_str);
|
||||
|
||||
// Create TCP Socket to Origin Server
|
||||
struct sockaddr_in sa;
|
||||
int my_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
sa.sin_family = AF_INET;
|
||||
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));
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
total_received += bytes_received;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
close(my_sock);
|
||||
|
||||
return response_message;
|
||||
}
|
||||
|
||||
// Main
|
||||
@@ -51,7 +424,7 @@ int main(int argc, char *argv[]) {
|
||||
if (DEBUG) printf("SETUP: Setup Sockets\n");
|
||||
int serv_sock, client_sock, read_size;
|
||||
struct sockaddr_in server, client;
|
||||
char client_message[20000];
|
||||
char client_message[MAX_MESSAGE_SIZE];
|
||||
serv_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
client_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (DEBUG) printf("SETUP: Socket Created\n");
|
||||
@@ -59,8 +432,15 @@ int main(int argc, char *argv[]) {
|
||||
// Bind Sockets
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(PORT);
|
||||
// inet_pton(AF_INET, INADDR_ANY, &(server.sin_addr));
|
||||
bind(serv_sock,(struct sockaddr *)&server, sizeof(server));
|
||||
inet_pton(AF_INET, BOUND_IP, &(server.sin_addr));
|
||||
|
||||
// TODO: REMOVE THIS BEFORE SUBMISSION
|
||||
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &server, sizeof(server));
|
||||
|
||||
if (bind(serv_sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
|
||||
perror("BIND FAILED");
|
||||
return 1;
|
||||
}
|
||||
if (DEBUG) printf("SETUP: Socket Bound\n");
|
||||
|
||||
// Start Listening and Waiting for Connections
|
||||
@@ -69,23 +449,37 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
while (1) {
|
||||
// Accept Connection from Client
|
||||
if (DEBUG) printf("WAIT: Waiting for incoming connections...\n");
|
||||
printf("WAIT: Waiting for incoming connections...\n");
|
||||
int c = sizeof(struct sockaddr_in);
|
||||
client_sock = accept(serv_sock, (struct sockaddr *)&client, &c);
|
||||
if (DEBUG) printf("CONNECT: Connection Accepted\n");
|
||||
printf("CONNECT: Connection Accepted\n");
|
||||
|
||||
// Receive Message from Client
|
||||
memset(client_message, 0, sizeof(client_message));
|
||||
read_size = recv(client_sock, client_message, sizeof(client_message), 0);
|
||||
if (DEBUG) printf("RECEIVE: Message Received\n");
|
||||
printf("RECEIVE: Message Received\n");
|
||||
|
||||
// Process Message From Client
|
||||
if (DEBUG) printf("PROCESS: Processing Message\n");
|
||||
struct http_message message = create_http_message_from_string(client_message);
|
||||
printf("PROCESS: Processing Message\n");
|
||||
struct req_http_message received_message = create_req_http_message_from_string(client_message);
|
||||
|
||||
// Process Message for Relay
|
||||
printf("PROCESS: Processing for Relay\n");
|
||||
struct http_forward_info relay_message = process_for_relay(received_message);
|
||||
|
||||
// Forward Message to Destination Server
|
||||
printf("FORWARD: Forwarding Message to %s\n", relay_message.host);
|
||||
struct res_http_message origin_response = forward_message_await_response(relay_message);
|
||||
|
||||
// Send Response Back to Client
|
||||
char response_str[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");
|
||||
|
||||
// Close Client Socket
|
||||
close(client_sock);
|
||||
if (DEBUG) printf("DISCONNECT: Client Disconnected\n\n");
|
||||
printf("DISCONNECT: Client Disconnected\n\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user