Skip to content

Commit

Permalink
rebrand library from luxio to the pandio
Browse files Browse the repository at this point in the history
pandio - library major refactor
  • Loading branch information
michaldziuba03 authored Aug 19, 2024
2 parents fd2cedd + 273b7c0 commit b018eb1
Show file tree
Hide file tree
Showing 41 changed files with 1,513 additions and 1,846 deletions.
18 changes: 18 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}"
],
"defines": [
"__USE_POSIX199309",
"CLOCK_MONOTONIC"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "gnu++17"
}
],
"version": 4
}
12 changes: 10 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
"internet": "c",
"string_view": "c",
"sstream": "c",
"random": "c"
}
"random": "c",
"chrono": "c",
"compare": "c",
"functional": "c",
"ratio": "c",
"tuple": "c",
"type_traits": "c",
"utility": "c"
},
"C_Cpp.errorSquiggles": "enabled"
}
37 changes: 29 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,39 @@ SRC_DIR=src
BUILD_DIR=build
TEST_DIR=test
TEST_BUILD_DIR=$(TEST_DIR)/build
SAMPLES_DIR=samples
TARGET=server
LIBRARY=libluxio.a

SRCS=$(shell find $(SRC_DIR) -name '*.c')
LIBRARY=libpandio.a

UNAME_S := $(shell uname -s)

ifeq ($(UNAME_S),Linux)
PLATFORM_SRC=$(SRC_DIR)/unix
else ifeq ($(UNAME_S),Darwin) # Dodane wsparcie dla macOS
PLATFORM_SRC=$(SRC_DIR)/unix
else ifeq ($(UNAME_S),Windows_NT)
PLATFORM_SRC=$(SRC_DIR)/win32
else
$(error Platform not supported)
endif

SRCS=$(shell find $(SRC_DIR) -name '*.c' -not -path "$(SRC_DIR)/unix/*" -not -path "$(SRC_DIR)/win32/*") \
$(shell find $(PLATFORM_SRC) -name '*.c')
TEST_SRCS=$(shell find $(TEST_DIR) -name '*.c')
SAMPLES_SRCS=$(shell find $(SAMPLES_DIR) -name '*.c')

OBJECTS=$(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))
TEST_OBJECTS=$(patsubst $(TEST_DIR)/%.c,$(TEST_BUILD_DIR)/%.o,$(TEST_SRCS))
SAMPLES_OBJECTS=$(patsubst $(SAMPLES_DIR)/%.c,$(BUILD_DIR)/samples/%.o,$(SAMPLES_SRCS))

all: $(TARGET)

$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(BUILD_DIR)/$(TARGET)
ar rcs $(BUILD_DIR)/$(LIBRARY) $(OBJECTS)

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@

lib: $(OBJECTS)
ar rcs $(BUILD_DIR)/$(LIBRARY) $(OBJECTS)
$(CC) $(CFLAGS) -c $< -o $@

test: $(TARGET) $(TEST_OBJECTS)
$(CC) $(CFLAGS) $(TEST_OBJECTS) -o $(TEST_BUILD_DIR)/test -lcriterion
Expand All @@ -34,6 +47,14 @@ $(TEST_BUILD_DIR)/%.o: $(TEST_DIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@

samples: $(SAMPLES_OBJECTS)
@mkdir -p $(BUILD_DIR)/samples
$(CC) $(CFLAGS) $(SAMPLES_OBJECTS) -L$(BUILD_DIR) -lpandio -lrt -o $(BUILD_DIR)/samples/tcp_echo

$(BUILD_DIR)/samples/%.o: $(SAMPLES_DIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@

clean:
@rm -rf $(BUILD_DIR)
@rm -rf $(TEST_BUILD_DIR)
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
> ⚠️ Early stage of development.
# luxio
<img src="https://github.com/user-attachments/assets/cf70d4ac-9cef-4c66-8295-04946abdafd2" alt="banner" />

Simple async io library for C (it will be in the future, for now it's just HTTP server) - it will be used across my personal projects.
# Pandio

Simple library for non-blocking I/O operations. Developed mainly for my PandJS project (JavaScript runtime).

### TODO:

- [x] Timers using heap data structure (works like `setTimeout`, `setInterval`).
- [x] Non-blocking IO for sockets using epoll.
- [x] Basic networking abstraction to handle TCP.
- [ ] HTTP module.
- [ ] WebSockets module.
- [ ] TLS support.
- [ ] Thread pool and files handling.
- [ ] Support many platforms: Windows, MacOS and FreeBSD.

### Build static library

Make sure you have `make` utility installed. Library uses just system calls, so it does not have any external dependencies.

```sh
make && ./build/server
make
```

> This command will create `libpandio.a` file inside `build` directory.
### Running tests

Project uses [Criterion](https://github.com/Snaipe/Criterion) for unit testing:
Expand All @@ -35,10 +40,6 @@ pacaur -S criterion
make test
```

## Resources
- [Beej's Guide to Network Programming](https://www.beej.us/guide/bgnet/html/split/index.html)
- [The C10K problem](http://www.kegel.com/c10k.html)
- [Wikipedia - epoll()](https://en.wikipedia.org/wiki/Epoll)
- [Such Programming - epoll() In 3 Easy Steps!](https://suchprogramming.com/epoll-in-3-easy-steps/)
- [Trung Vuong Thien - A simple HTTP server from scratch](https://trungams.github.io/2020-08-23-a-simple-http-server-from-scratch)
- [HTTP RFC](https://datatracker.ietf.org/doc/html/rfc7230)
## License

Distributed under the MIT License. See `LICENSE` for more information.
41 changes: 41 additions & 0 deletions docs/tcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Pandio

Docs not ready yet

## TCP streams

Creating TCP server

```c
void handle_close(pnd_tcp_t *stream) {
// perform clean up
free(stream);
}

// echo server
void handle_read(pnd_tcp_t *stream) {
char buf[1024] = {};
ssize_t bytes = pnd_tcp_read(stream, buf, 1024);
if (bytes > 0) {
pnd_tcp_write(stream, buf, bytes);
}
pnd_tcp_close(stream);
}

void handle_connection(pnd_fd_t fd) {
printf("New connection accepted: %d\n", fd);
pnd_tcp_t *client = malloc(sizeof(pnd_tcp_t));
pnd_tcp_accept(client, fd);

client->on_data = handle_read;
client->on_close = handle_close;
}

int main() {
pnd_tcp_t *server = malloc(sizeof(pnd_tcp_t));
pnd_tcp_init(server);
pnd_tcp_listen(server, 8080, handle_connection);

return 0;
}
```
133 changes: 133 additions & 0 deletions samples/tcp_echo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include <pandio.h>
#include <unistd.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>

void handle_close(pnd_tcp_t *stream) {
// perform clean up
//printf("Connection closed: %d\n", stream->fd);
free(stream);
}

void handle_write(pnd_write_t *write_op, int status) {
//printf("write completed with status: %d\n", status);
free(write_op->buf);
free(write_op);
}

// echo server
void handle_read(pnd_tcp_t *stream) {
char buf[1024] = {};
ssize_t bytes = read(stream->fd, buf, 1024);
if (bytes < 0) {
perror("read");
return;
}

if (bytes == 0) {
//pnd_tcp_close(stream);
printf("Received 0 bytes for: %d\n", stream->fd);
pnd_tcp_destroy(stream);
return;
}

//printf("read %ld bytes\n", bytes); fflush(stdout);
pnd_write_t *write_op = malloc(sizeof(pnd_write_t));
const char *response = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello";
pnd_tcp_write_init(write_op, strdup(response), strlen(response), handle_write);
//memcpy((void*)write_op->buf, (void*)buf, bytes);
pnd_tcp_write_async(stream, write_op);
//pnd_tcp_try_write(stream, response, strlen(response));
pnd_tcp_close(stream);
}

void handle_connection(pnd_tcp_t *server, pnd_fd_t fd) {
//printf("New connection accepted: %d\n", fd);
pnd_tcp_t *client = malloc(sizeof(pnd_tcp_t));
pnd_io_t *ctx = pnd_tcp_ctx(server);
pnd_tcp_init(ctx, client);
pnd_tcp_accept(client, fd);

client->on_data = handle_read;
client->on_close = handle_close;
}

int main_old() {
printf("Starting server, pid is: %d\n", getpid());
pnd_io_t ctx;
pnd_io_init(&ctx);

pnd_tcp_t *server = malloc(sizeof(pnd_tcp_t));
pnd_tcp_init(&ctx, server);
pnd_tcp_listen(server, 8000, handle_connection);

pnd_io_run(&ctx);

return 0;
}

void on_server_response(pnd_tcp_t *stream) {
char buf[1024] = {};
ssize_t bytes = read(stream->fd, buf, 1023);
if (bytes < 0) {
perror("read");
return;
}

if (bytes == 0) {
//pnd_tcp_close(stream);
printf("Received 0 bytes for: %d\n", stream->fd);
pnd_tcp_destroy(stream);
return;
}

printf("Response from server: %s\n", buf);

pnd_tcp_close(stream);
}

void handle_connect(pnd_tcp_t *client, pnd_fd_t fd) {
printf("Connected to server. Client fd: %d\n", fd);

client->on_data = on_server_response;
client->on_close = handle_close;

pnd_write_t *write_op = malloc(sizeof(pnd_write_t));
pnd_tcp_write_init(write_op, strdup("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"), 35, handle_write);
pnd_tcp_write(client, write_op);
}

void long_task() {
printf("Long task started...\n");
sleep(3);
}

void after_task() {
printf("Long task done, but from main thread...\n");
}

int main() {
printf("Starting client, pid is: %d\n", getpid());
pnd_io_t *ctx = malloc(sizeof(pnd_io_t));
pnd_io_init(ctx);

pnd_task_t *task = malloc(sizeof(pnd_task_t));
task->work = long_task;
task->done = after_task;
pnd_work_submit(ctx, task);

pnd_task_t *task2 = malloc(sizeof(pnd_task_t));
task2->work = long_task;
task2->done = after_task;
pnd_work_submit(ctx, task2);

pnd_tcp_t *client = malloc(sizeof(pnd_tcp_t));
pnd_tcp_init(ctx, client);
int status = pnd_tcp_connect(client, "127.0.0.1", 3000, handle_connect);
printf("Connect status: %d\n", status);

pnd_io_run(ctx);

return 0;
}
37 changes: 0 additions & 37 deletions scripts/long-request.js

This file was deleted.

27 changes: 0 additions & 27 deletions scripts/perfect-request.js

This file was deleted.

Loading

0 comments on commit b018eb1

Please sign in to comment.