initial commit
This commit is contained in:
commit
9e1a9c7c23
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.o
|
||||
build/
|
16
src/Makefile
Normal file
16
src/Makefile
Normal file
@ -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)
|
26
src/include/tcp.h
Normal file
26
src/include/tcp.h
Normal file
@ -0,0 +1,26 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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
|
49
src/main.c
Normal file
49
src/main.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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;
|
||||
}
|
112
src/tcp.c
Normal file
112
src/tcp.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
|
||||
#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"
|
Loading…
x
Reference in New Issue
Block a user