Skip to content

Refactor: simplify the server flow, remove threads and read packets in bulk #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ passwd_file
.ccls
.clangd
.vscode
.cache
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ add_definitions("-D_DEFAULT_SOURCE")
find_package(OpenSSL REQUIRED)

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)

# Add include directories for headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/lib)

file(GLOB SOURCES src/*.c)
file(GLOB TEST src/hashtable.c src/bst.c src/config.c src/list.c src/trie.c
Expand Down Expand Up @@ -44,8 +48,11 @@ else (APPLE)
TARGET_LINK_LIBRARIES(sol pthread ssl crypto crypt)
TARGET_LINK_LIBRARIES(sol_test pthread ssl crypto crypt)
endif (APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused -Werror -pedantic \
-Wno-unused-result -std=c11 -O3")
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused -Werror -pedantic \
# -Wno-unused-result -std=c11 -O3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused -Werror -pedantic \
-Wno-unused-result -std=c11 -ggdb -fsanitize=address \
-fsanitize=undefined -fno-omit-frame-pointer -pg")

endif (DEBUG)

Expand Down
2 changes: 1 addition & 1 deletion COPYING
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 2-Clause License

Copyright (c) 2023, Andrea Giacomo Baldan
Copyright (c) 2025, Andrea Giacomo Baldan
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
10 changes: 5 additions & 5 deletions conf/sol.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# is set, UNIX family socket will be used

ip_address 127.0.0.1
ip_port 8883
ip_port 1883 # 8883 for MQTT over TLS (MQTT clients such as mosquitto will automatically add TLS)

# unix_socket /tmp/sol.sock

Expand All @@ -30,11 +30,11 @@ tcp_backlog 128
# Interval of time between one stats publish on $SOL topics and the subsequent
stats_publish_interval 10s

cafile certs/ca.crt
certfile certs/alaptop.crt
keyfile certs/alaptop.key
# cafile certs/ca.crt
# certfile certs/alaptop.crt
# keyfile certs/alaptop.key

# allow_anonymous false
# password_file passwd_file

tls_protocols tlsv1,tlsv1_1,tlsv1_2,tlsv1_3
# tls_protocols tlsv1,tlsv1_1,tlsv1_2,tlsv1_3
56 changes: 56 additions & 0 deletions include/arena.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef ARENA_H
#define ARENA_H

#include <stdint.h>
#include <stdlib.h>

typedef struct pool_allocator {
void *(*alloc)(void *context);
void (*free)(void *context, void *ptr);
void *context;
} Pool_Allocator;

#define pool_alloc(a) ((a)->alloc((a)->context))
#define pool_free(a, p) ((a)->free((a)->context, p))

void *arena_pool_alloc(void *context);
void arena_pool_free(void *context, void *ptr);

struct memorypool *memorypool_new(size_t, size_t);
void memorypool_destroy(struct memorypool *);
void *memorypool_alloc(struct memorypool *);
void memorypool_free(struct memorypool *, void *);

// Free list definition

typedef struct Free_List_Header {
size_t block_size;
size_t padding;
} Free_List_Header;

typedef struct Free_List_Node {
struct Free_List_Node *next;
size_t block_size;
} Free_List_Node;

typedef struct Free_List {
void *data;
size_t size;
size_t used;
Free_List_Node *head;
} Free_List;

typedef struct arena_allocator {
void *(*alloc)(void *context, size_t size);
void (*free)(void *context, void *ptr);
void *context;
} Arena_Allocator;

#define arena_alloc(a, s) ((a)->alloc((a)->context, (s)))
#define arena_free(a, p) ((a)->free((a)->context, (p)))

Free_List *free_list_new(size_t size);
void *free_list_alloc(void *, size_t);
void free_list_free(void *, void *);

#endif
4 changes: 2 additions & 2 deletions src/bst.h → include/bst.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* BSD 2-Clause License
*
* Copyright (c) 2023 Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025 Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -45,6 +45,6 @@ struct bst_node *bst_search(const struct bst_node *, unsigned char);

struct bst_node *bst_delete(struct bst_node *, unsigned char);

void bst_destroy(struct bst_node *, void (*free_fn)(struct bst_node *));
void bst_free(struct bst_node *, void (*free_fn)(struct bst_node *));

#endif
2 changes: 1 addition & 1 deletion src/config.h → include/config.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down
26 changes: 26 additions & 0 deletions include/darray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef DARRAY_H
#define DARRAY_H

#include <assert.h>

// Dynamic array helpers

#define da_extend(da) \
do { \
(da).capacity *= 2; \
(da).items = realloc((da).items, (da).capacity * sizeof(*(da).items)); \
if (!(da).items) { \
fprintf(stderr, "DA realloc failed"); \
exit(EXIT_FAILURE); \
} \
} while (0)

#define da_append(da, item) \
do { \
assert((da)); \
if ((da).length + 1 == (da).capacity) \
da_extend((da)); \
(da).items[(da).length++] = (item); \
} while (0)

#endif
31 changes: 15 additions & 16 deletions src/ev.h → include/ev.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -50,23 +50,25 @@ enum ev_type {

struct ev_ctx;

typedef void (*ev_callback)(struct ev_ctx *, void *);

/*
* Event struture used as the main carrier of clients informations, it will be
* tracked by an array in every context created
*/
struct ev {
int fd;
int mask;
void *rdata; // opaque pointer for read callback args
void *wdata; // opaque pointer for write callback args
void (*rcallback)(struct ev_ctx *, void *); // read callback
void (*wcallback)(struct ev_ctx *, void *); // write callback
void *rdata; // opaque pointer for read callback args
void *wdata; // opaque pointer for write callback args
ev_callback rcallback; // read callback
ev_callback wcallback; // write callback
};

/*
* Event loop context, carry the expected number of events to be monitored at
* every cycle and an opaque pointer to the backend used as engine
* (Select | Epoll | Kqueue).
* (Select | Epoll | Kqueue).ev
* By now we stick with epoll and skip over select, cause as the current
* threaded model employed by the server is not very friendly with select
* Level-trigger default setting. But it would be quiet easy abstract over the
Expand All @@ -81,13 +83,13 @@ struct ev_ctx {
int stop;
int maxevents;
unsigned long long fired_events;
struct ev *events_monitored;
struct ev *monitored;
void *api; // opaque pointer to platform defined backends
};

int ev_init(struct ev_ctx *, int);

void ev_destroy(struct ev_ctx *);
void ev_free(struct ev_ctx *);

/*
* Poll an event context for events, accepts a timeout or block forever,
Expand All @@ -113,32 +115,29 @@ void ev_stop(struct ev_ctx *);
* ev_fire_event just without an event to be carried. Useful to add simple
* descritors like a listening socket o message queue FD.
*/
int ev_watch_fd(struct ev_ctx *, int, int);
int ev_watch(struct ev_ctx *, int, int);

/*
* Remove a FD from the loop, even tho a close syscall is sufficient to remove
* the FD from the underlying backend such as EPOLL/SELECT, this call ensure
* that any associated events is cleaned out an set to EV_NONE
*/
int ev_del_fd(struct ev_ctx *, int);
int ev_delete(struct ev_ctx *, int);

/*
* Register a new event, semantically it's equal to ev_register_event but
* it's meant to be used when an FD is not already watched by the event loop.
* It could be easily integrated in ev_fire_event call but I prefer maintain
* the samantic separation of responsibilities.
*/
int ev_register_event(struct ev_ctx *, int, int,
void (*callback)(struct ev_ctx *, void *), void *);
int ev_add_event(struct ev_ctx *, int, int, ev_callback, void *);

int ev_register_cron(struct ev_ctx *, void (*callback)(struct ev_ctx *, void *),
void *, long long, long long);
int ev_add_cron(struct ev_ctx *, ev_callback, void *, long long, long long);

/*
* Register a new event for the next loop cycle to a FD. Equal to ev_watch_fd
* but allow to carry an event object for the next cycle.
*/
int ev_fire_event(struct ev_ctx *, int, int,
void (*callback)(struct ev_ctx *, void *), void *);
int ev_oneshot(struct ev_ctx *, int, int, ev_callback, void *);

#endif
11 changes: 6 additions & 5 deletions src/handlers.h → include/handlers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -28,12 +28,13 @@
#ifndef HANDLERS_H
#define HANDLERS_H

struct topic;
typedef struct topic Topic;
struct mqtt_packet;
struct io_event;
typedef struct connection_context Connection_Context;
typedef struct arena_allocator Arena_Allocator;

int publish_message(struct mqtt_packet *, const struct topic *);
void publish_message(struct mqtt_packet *, const Topic *, Arena_Allocator *);

int handle_command(unsigned, struct io_event *);
int handle_command(Connection_Context *);

#endif
4 changes: 2 additions & 2 deletions src/iterator.h → include/iterator.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -47,7 +47,7 @@ struct iterator {
struct iterator *iter_new(void *, void (*next)(struct iterator *));
void iter_init(struct iterator *, void *, void (*next)(struct iterator *));
struct iterator *iter_next(struct iterator *);
void iter_destroy(struct iterator *);
void iter_free(struct iterator *);

#define FOREACH(it) for (; it && it->ptr; it = iter_next(it))

Expand Down
4 changes: 2 additions & 2 deletions src/list.h → include/list.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan
* Copyright (c) 2025, Andrea Giacomo Baldan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -56,7 +56,7 @@ List *list_new(int (*destructor)(struct list_node *));
* Release a list, accept a integer flag to control the depth of the free call
* (e.g. going to free also data field of every node)
*/
void list_destroy(List *, int);
void list_free(List *, int);

/* Return list size */
unsigned long list_size(const List *);
Expand Down
2 changes: 1 addition & 1 deletion src/logging.h → include/logging.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down
2 changes: 1 addition & 1 deletion src/memory.h → include/memory.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* BSD 2-Clause License
*
* Copyright (c) 2023, Andrea Giacomo Baldan All rights reserved.
* Copyright (c) 2025, Andrea Giacomo Baldan All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down
Loading