From 9e1a9c7c2398d46b02ea0a91f842b505606fd3ba Mon Sep 17 00:00:00 2001 From: SuperNovaa41 Date: Tue, 28 Jan 2025 22:50:06 -0500 Subject: [PATCH] initial commit --- .gitignore | 2 + src/Makefile | 16 +++++++ src/include/tcp.h | 26 +++++++++++ src/main.c | 49 ++++++++++++++++++++ src/tcp.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 .gitignore create mode 100644 src/Makefile create mode 100644 src/include/tcp.h create mode 100644 src/main.c create mode 100644 src/tcp.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8326e08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +build/ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..bff176b --- /dev/null +++ b/src/Makefile @@ -0,0 +1,16 @@ +TARGET=http +CC=gcc + +OBJ = main.o tcp.o + +$(TARGET): $(OBJ) + mkdir -p ../build + $(CC) -Wall -g -o $(TARGET) $(OBJ) -g + mv $(TARGET) ../build/ + +main.o: include/tcp.h +tcp.o: include/tcp.h + +.PHONY: clean +clean: + rm -rf ../build $(OBJ) diff --git a/src/include/tcp.h b/src/include/tcp.h new file mode 100644 index 0000000..12cc39a --- /dev/null +++ b/src/include/tcp.h @@ -0,0 +1,26 @@ +#include + +#ifndef TCP_H +#define TCP_H + +/// Default HTTP port +#define DEFAULT_PORT 8080 + +#define BUFFER_INC_LEN 200 + +typedef struct { + int socket; + struct sockaddr_in server_info; + size_t server_info_len; +} server_conn_t; + +void setup_socket(server_conn_t* conn); + +void recv_message(char** buffer, int socket); + +/// Threaded function to handle http requests +/// takes client socket as an argument +void* connection_handler(void* arg); + + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2a9c6cf --- /dev/null +++ b/src/main.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +#include "include/tcp.h" + +int main(void) +{ + server_conn_t server; + pthread_t client_thread; + int client_sock, err; + + setup_socket(&server); + puts("Server setup succesfully!"); + + // start accepting connections here + + + puts("Accepting new connections..."); + while (true) { + client_sock = accept(server.socket, (struct sockaddr*) &(server.server_info), + (socklen_t*) &(server.server_info_len)); + if (client_sock == -1) { + perror("accept"); + continue; + } + + printf("Connection established with %s\n", + inet_ntoa(server.server_info.sin_addr)); + + err = pthread_create(&client_thread, NULL, connection_handler, &client_sock); + if (err != 0) { + perror("pthread_create"); + continue; + } + + err = pthread_detach(client_thread); + if (err != 0) { + perror("pthread_detach"); + continue; + } + } + + close(server.socket); + + + return 0; +} diff --git a/src/tcp.c b/src/tcp.c new file mode 100644 index 0000000..693b79d --- /dev/null +++ b/src/tcp.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include + +#include "include/tcp.h" + +void setup_socket(server_conn_t* conn) +{ + int err; + size_t sockaddr_len; + + conn->socket = socket(AF_INET, SOCK_STREAM, 0); + if (conn->socket == -1) { + perror("socket"); + exit(EXIT_FAILURE); + } + + conn->server_info.sin_family = AF_INET; + conn->server_info.sin_addr.s_addr = INADDR_ANY; + conn->server_info.sin_port = htons(DEFAULT_PORT); + + + conn->server_info_len = sizeof(conn->server_info); + err = bind(conn->socket, (const struct sockaddr*) &(conn->server_info), + (socklen_t) conn->server_info_len); + if (err == -1) { + perror("bind"); + close(conn->socket); + exit(EXIT_FAILURE); + } + + err = listen(conn->socket, 1); + if (err == -1) { + perror("listen"); + close(conn->socket); + exit(EXIT_FAILURE); + } +} + +// this is a blocking call +void recv_message(char** buffer, int socket) +{ + ulong current_size, bytes_recv; + int status; + + /** + * TODO: look into poll()? recv is receiving : "Resource temporarily unavaiable" + */ + + current_size = bytes_recv = 0; + status = 0; + + do { + // if we received more data, lets realloc + if (bytes_recv >= current_size) { + // temporary buffer so if we fail a realloc we don't lose data + char* tmp; + + current_size += BUFFER_INC_LEN; + + tmp = realloc(*buffer, current_size); + if (tmp == NULL) { + perror("realloc"); + break; + } + // we succeeded so lets assign the new buffer + *buffer = tmp; + } + + // lets recv BUFFER_INC_LEN amount of bytes + status = recv(socket, *buffer + bytes_recv, BUFFER_INC_LEN, MSG_DONTWAIT); + if (status < 0) { + perror("recv"); + break; // don't want to crash on a recv failure, lets just break + } + + bytes_recv += status; + } while (status == BUFFER_INC_LEN); // break when we stop receiving, status == 0 means no more data + + (*buffer)[bytes_recv] = '\0'; +} + +void* connection_handler(void* arg) +{ + int client_socket = *(int*) arg; + char* buffer = NULL; + + recv_message(&buffer, client_socket); + + puts(buffer); + + /** + * Handle HTTP request here :) + */ + + // recv message + + // parse + // + // create payload + // + // send payload + + close(client_socket); + + return NULL; +} + +#include "include/tcp.h"