floof-c/src/floof.c
Alain Zscheile 591a42941b use tcp
2022-11-30 12:18:57 +01:00

140 lines
2.7 KiB
C

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <glib.h>
#include <sodium.h>
#include "floof_int.h"
#include "floof_db.h"
typedef struct {
floof_db_t *db;
GThreadPool *thpool;
bool (*filter_packets)(unsigned char *data, size_t datalen);
} floof_node_t;
typedef struct {
floof_node_t * node;
int sock;
} floof_conn_t;
typedef struct {
unsigned char pubkey[crypto_sign_PUBLICKEYBYTES];
unsigned char sig[crypto_sign_BYTES];
unsigned char *data;
size_t datalen;
} floof_worker_task_t;
/** internal **/
static void floof_free_task(void * data) {
floof_worker_task_t * task = (floof_worker_task_t*) data;
free(task->data);
free(task);
}
static void floof_worker(void * data, void * user_data) {
floof_worker_task_t * task = (floof_worker_task_t*) data;
floof_node_t * node = (floof_node_t*) user_data;
if(0 != crypto_sign_verify_detached(task->sig, task->data, task->datalen, task->pubkey)) {
// signature check failed, drop packet
goto drop;
}
if(!node->filter_packets(task->data, task->datalen)) {
// drop packet
goto drop;
}
// forward packet
floof_db_insert_packet(node->db, task);
goto cleanup;
drop:
cleanup:
floof_free_task(data);
}
/** external **/
floof_node_t * floof_new_node(const char * spooldir) {
floof_node_t * ret = calloc(sizeof(floof_node_t), 1);
if(!ret) return 0;
const unsigned int cpu_count = floof_get_cpu_count();
ret->thpool = g_thread_pool_new(
floof_worker,
(void*) ret,
g_get_num_processors(),
FALSE,
0);
if(floof_db_open(&ret->db, spooldir) == -1)
goto error;
return ret;
error:
floof_destroy_node(ret);
return 0;
}
floof_conn_t * floof_socket(floof_node_t * node, int domain) {
floof_conn_t * ret = calloc(sizeof(floof_conn_t), 1);
if(!ret) return 0;
ret->node = node;
if(-1 == (ret->sock = socket(domain, SOCK_SEQPACKET, IPPROTO_TCP))) {
free(ret);
return 0;
}
return ret;
}
int floof_bind_listen(floof_conn_t * conn, struct sockaddr *addr, socklen_t addrlen) {
if(bind(conn->sock, addr, addrlen) < 0)
return -1;
if(listen(conn->sock, 10) < 0)
return -1;
return 0;
}
int floof_connect(floof_node_t * conn, struct sockaddr *remotename, socklen_t addrlen) {
if(connect(conn->sock, remotename, addrlen) < 0)
return -1;
return 0;
}
void floof_close(floof_conn_t * conn) {
if(!conn) return;
if(conn->sock != -1)
close(conn->sock);
free(conn);
}
void floof_destroy_node(floof_node_t * node) {
if(!node) return;
if(node->thpool)
g_thread_pool_free(node->thpool, TRUE, TRUE);
floof_db_close(&node->db);
free(node);
}