re-structured, and updated hashmap

This commit is contained in:
aiden 2022-05-20 00:14:50 +01:00
parent 45b7ff20fb
commit 769648aba3
No known key found for this signature in database
GPG Key ID: 0D87FF3415416DB1
58 changed files with 428 additions and 260 deletions

3
.gitignore vendored
View File

@ -1,3 +1,2 @@
bidirectiond
build/
.DS_Store

6
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "src/hashmap"]
path = src/hashmap
url = https://git.tcp.direct/aiden/hashmap
[submodule "core/hashmap"]
path = core/hashmap
url = https://git.tcp.direct/aiden/hashmap.git
branch = main

18
bidirectiond/build.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
import os, subprocess, sys
file_dirname = os.path.dirname(__file__)
build_path = os.path.join(
file_dirname,
"..",
"build",
""
)
os.chdir(build_path)
gcc = ["/usr/bin/gcc", "-I" + os.path.join(file_dirname, "..", "inc"), "-c"]
for directory, _, files in os.walk(file_dirname):
for file_name in files:
if file_name[-2:] != ".c":
continue
gcc.append(os.path.join(directory, file_name))
gcc.extend(sys.argv[1:])
subprocess.run(gcc)

View File

@ -1,6 +1,10 @@
#ifndef bidirectiond__core_settings__h
#define bidirectiond__core_settings__h
#include <bddc/settings.h>
#include <bdd-core/settings.h>
extern const struct bdd_service services[];
extern struct bdd_settings settings;
extern const size_t n_services;
#endif

View File

@ -188,11 +188,9 @@ void input_processor(int sfd, char *br_buf, int br_buf_sz) {
goto tls_pem_load_err;
}
struct locked_hashmap *lh = hashmap_lock(settings.name_descriptions);
if (bdd_name_descriptions_use_cert_pkey(lh, &(x509), &(pkey))) {
if (bdd_name_descs_use_cert_pkey(settings.name_descs, &(x509), &(pkey))) {
e |= 0b10;
}
locked_hashmap_unlock(&(lh));
tls_pem_load_err:;
if (bio != NULL) {

View File

@ -6,7 +6,7 @@
#include <poll.h>
#include <assert.h>
#include <arpa/inet.h>
#include <bddc/settings.h>
#include <bdd-core/settings.h>
#include <fcntl.h>
#include <openssl/engine.h>
#include <openssl/err.h>
@ -28,7 +28,7 @@
#endif
struct bdd_settings settings = {
.name_descriptions = NULL,
.name_descs = NULL,
.n_conversations = 0x100,
.n_epoll_oevents = 0x200,
.n_worker_threads = 16,
@ -70,7 +70,6 @@ void storlim(rlim_t *dest, char *str) {
// main
#ifndef HASHMAP_MAIN
int main(int argc, char *argv[], char *env[]) {
puts("bidirectiond version " PROG_SEMVER);
// set up tls
SSL_library_init();
OpenSSL_add_all_algorithms();
@ -86,9 +85,9 @@ int main(int argc, char *argv[], char *env[]) {
};
int sig_fd = -1;
// name_descriptions
if ((settings.name_descriptions = bdd_name_descriptions_create()) == NULL) {
fputs("failed to allocate settings.name_descriptions\n", stderr);
// name_descs
if ((settings.name_descs = bdd_name_descs_create()) == NULL) {
fputs("failed to allocate settings.name_descs\n", stderr);
goto clean_up;
}
// args
@ -128,18 +127,17 @@ int main(int argc, char *argv[], char *env[]) {
}
endpwent();
struct locked_hashmap *lh = hashmap_lock(settings.name_descriptions);
size_t big_alloc_sz = 0;
#define EXPECT_ARGS(n) \
for (size_t idx = 1; idx <= n; ++idx) { \
if (arg[idx] == NULL || (arg[idx][0] == '-' && (arg[idx][1] < '1' || arg[idx][1] > '9'))) {\
if (arg[idx] == NULL || (arg[idx][0] == '-' && (arg[idx][1] < '1' || arg[idx][1] > '9'))) { \
goto arg_err; \
} \
}
arg_iter:;
while ((*arg) != NULL) {
if (strcmp((*arg), "--n-connection-threads") == 0 || strcmp((*arg), "-t") == 0) {
if (strcmp((*arg), "--n-worker-threads") == 0 || strcmp((*arg), "-t") == 0) {
EXPECT_ARGS(1);
stousi(&(settings.n_worker_threads), arg[1]);
arg += 2;
@ -231,7 +229,7 @@ int main(int argc, char *argv[], char *env[]) {
goto arg_creds_err;
}
if (!bdd_name_descriptions_use_cert_pkey(lh, &(x509), &(pkey))) {
if (!bdd_name_descs_use_cert_pkey(settings.name_descs, &(x509), &(pkey))) {
fputs("seemingly invalid certificate file\n", stderr);
goto arg_creds_err;
}
@ -273,22 +271,24 @@ int main(int argc, char *argv[], char *env[]) {
stosz(&(big_alloc_sz), arg[1]);
arg += 2;
} else {
for (size_t idx = 0; idx < N_SERVICES; ++idx) {
for (size_t idx = 0; idx < n_services; ++idx) {
if (services[idx].supported_arguments != NULL)
for (size_t pidx = 0; services[idx].supported_arguments[pidx]; ++pidx) {
if (strcmp((*arg), services[idx].supported_arguments[pidx]) == 0) {
size_t n = 1;
while (arg[n] != NULL
&& (arg[n][0] != '-'
|| (arg[n][1] >= '0' && arg[n][1] <= '9'))) {
while (
arg[n] != NULL &&
(arg[n][0] != '-' ||
(arg[n][1] >= '0' && arg[n][1] <= '9'))
) {
n += 1;
}
if (!services[idx].instantiate(
lh,
&(services[idx]),
n,
(const char **)arg
)) {
settings.name_descs,
&(services[idx]),
n,
(const char **)arg
)) {
goto arg_err;
}
arg = &(arg[n]);
@ -321,16 +321,14 @@ int main(int argc, char *argv[], char *env[]) {
"without restarting\n"
"--n-epoll-oevents: epoll_wait maxevents\n"
"--big-alloc: reserve some memory\n", stdout);
for (size_t idx = 0; idx < N_SERVICES; ++idx) {
for (size_t idx = 0; idx < n_services; ++idx) {
if (services[idx].arguments_help != NULL) {
fputs(services[idx].arguments_help, stdout);
}
}
locked_hashmap_unlock(&(lh));
goto clean_up;
}
}
locked_hashmap_unlock(&(lh));
// potentially a setuid program
if (getuid() != 0 && geteuid() == 0) {
@ -484,8 +482,8 @@ int main(int argc, char *argv[], char *env[]) {
close(settings.sv_socket);
}
// aight
if (settings.name_descriptions != NULL) {
hashmap_destroy(settings.name_descriptions);
if (settings.name_descs != NULL) {
bdd_name_descs_destroy(&(settings.name_descs));
}
// https://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
// FIPS_mode_set(0);

View File

@ -1,58 +1,16 @@
#!/usr/bin/env python3
semver = "wip-0.2.0"
import sys, json, os, subprocess
if sys.argv[0] != "./build.py":
print("shit")
exit(1)
gcc_args = ["gcc", "-o", "bidirectiond"]
services_c = "#include <bddc/settings.h>\n"
services = "const struct bdd_service services[] = {"
names = [
["bool %s(struct bdd_conversation *conversation, const char *protocol_name, void *instance_info, bdd_io_id client_id, struct sockaddr client_sockaddr);", "conversation_init"],
["void %s(void *instance_info);", "instance_info_destructor"],
]
np = 0
for dir, _, files in os.walk("src"):
for file in files:
if file[-2:] == ".c" or file[-2:] == ".o":
gcc_args.append(os.path.join(dir, file))
elif file == "service.json":
np += 1
path = os.path.join(dir, file)
fd = open(path)
p = json.loads(fd.read())
services += "{ NULL, "
for fn, member in names:
services += f".{member}="
if member in p:
name = p.get(member)
services_c += fn % name + "\n"
services += f"&({p.get(member)})"
else:
services += "NULL"
services += ","
services_c += f"""bool {p["instantiate"]}(struct locked_hashmap *name_descriptions, const struct bdd_service *service, size_t n_arguments, const char **arguments);\n"""
services_c += f"""void {p["handle_events"]}(struct bdd_conversation *conversation, const short int (*revents)[{p["n_max_io"]}]);\n"""
supported_protocols = "NULL"
if "supported_protocols" in p:
supported_protocols = "(const char *[]){ %s, NULL, }" % json.dumps(p["supported_protocols"])[1:-1]
services += """
.instantiate = &(%s),
.handle_events = (void *)&(%s),
.supported_arguments = (const char *[]){ %s, NULL, },
.arguments_help = (char *)%s,
.n_max_io = %i,
.supported_protocols = %s,
},""" % (p["instantiate"], p["handle_events"], json.dumps(p["supported_arguments"])[1:-1], json.dumps(p["arguments_help"]), p["n_max_io"], supported_protocols)
fd.close()
services += "};"
services_c += services
fd = open("src/_services.c", "w")
fd.write(services_c)
fd.close()
if not("src/_services.c" in gcc_args):
gcc_args.insert(1, "src/_services.c")
sysname = os.uname().sysname
gcc_args.extend(["-lpthread", "-lssl", "-lcrypto", "-Iinc", "-DN_SERVICES=" + str(np), "-DPROG_SEMVER=" + json.dumps(semver), "-funsigned-char"] + sys.argv[1:])
subprocess.call(gcc_args)
os.unlink("src/_services.c")
import os, subprocess, sys
file_dirname = os.path.dirname(__file__)
build_path = os.path.join(
file_dirname,
"build",
""
)
gcc = ["/usr/bin/gcc", "-lpthread", "-lssl", "-lcrypto", "-o", os.path.join(build_path, "bidirectiond"), "-I" + os.path.join(file_dirname, "build")]
for directory, _, files in os.walk(build_path):
for file_name in files:
if file_name[-2:] != ".o":
continue
gcc.append(os.path.join(directory, file_name))
gcc.extend(sys.argv[1:])
subprocess.run(gcc)

18
core/build.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
import os, subprocess, sys
file_dirname = os.path.dirname(__file__)
build_path = os.path.join(
file_dirname,
"..",
"build",
""
)
os.chdir(build_path)
gcc = ["/usr/bin/gcc", "-I" + os.path.join(file_dirname, "inc"), "-c"]
for directory, _, files in os.walk(file_dirname):
for file_name in files:
if file_name[-2:] != ".c":
continue
gcc.append(os.path.join(directory, file_name))
gcc.extend(sys.argv[1:])
subprocess.run(gcc)

1
core/hashmap Submodule

@ -0,0 +1 @@
Subproject commit c03bcfbab669be0b792413021b68ce582a34c675

View File

@ -4,15 +4,18 @@
#include <stdbool.h>
#include <stddef.h>
#include <sys/socket.h>
#include "src/headers/pollrdhup.h"
#include "src/headers/bdd_io_id.h"
#include "src/headers/bdd_service.h"
#include "src/headers/bdd_io_remove.h"
#include "src/headers/bdd_io_connect.h"
#include "src/headers/bdd_conversation_n_max_io.h"
#include "src/headers/bdd_poll.h"
#include "src/headers/bdd_io_shutdown.h"
#include <sys/epoll.h>
#include <hashmap/hashmap.h>
#include "../src/headers/pollrdhup.h"
#include "../src/headers/bdd_io_id.h"
#include "../src/headers/bdd_service.h"
#include "../src/headers/bdd_io_remove.h"
#include "../src/headers/bdd_name_descs.h"
#include "../src/headers/bdd_io_connect.h"
#include "../src/headers/bdd_conversation_n_max_io.h"
#include "../src/headers/bdd_poll.h"
#include "../src/headers/bdd_io_shutdown.h"
struct bdd_conversation;
@ -36,22 +39,34 @@ bool bdd_io_create(
int type,
int protocol
);
bool bdd_io_prep_ssl(struct bdd_conversation *conversation, bdd_io_id io_id, char *ssl_name);
bool bdd_io_prep_ssl(
struct bdd_conversation *conversation,
bdd_io_id io_id,
char *ssl_name
);
void bdd_set_associated(
struct bdd_conversation *conversation,
void *data,
void (*destructor)(void *)
);
void *bdd_get_associated(struct bdd_conversation *conversation);
bool bdd_name_descriptions_add_service_instance(
struct locked_hashmap *name_descriptions,
bool bdd_name_descs_add_service_instance(
struct bdd_name_descs *name_descs,
const char *scope,
size_t scope_sz,
const struct bdd_service *service,
void **instance_info
const void **instance_info
);
bool bdd_io_set_epoll_events(
struct bdd_conversation *conversation,
bdd_io_id io_id,
short int epoll_events
);
bool bdd_io_set_blocking(
struct bdd_conversation *conversation,
bdd_io_id io_id,
bool block
);
bool bdd_io_set_epoll_events(struct bdd_conversation *conversation, bdd_io_id io_id, short int epoll_events);
bool bdd_io_set_blocking(struct bdd_conversation *conversation, bdd_io_id io_id, bool block);
short int bdd_io_epoll_events(struct bdd_conversation *conversation, bdd_io_id io_id);
bool bdd_io_blocking(struct bdd_conversation *conversation, bdd_io_id io_id);

27
core/headers/settings.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef bidirectiond_core__settings__h
#define bidirectiond_core__settings__h
#include <openssl/ssl.h>
#include <stdbool.h>
#include "../src/headers/bdd_name_descs.h"
#include "../src/headers/bdd_settings.h"
#include "../src/headers/bdd_service.h"
#include "../src/headers/bdd_stop.h"
struct bdd_instance;
struct bdd_name_descs;
struct bdd_instance *bdd_go(struct bdd_settings settings);
void bdd_wait(struct bdd_instance *instance);
void bdd_destroy(struct bdd_instance *instance);
bool bdd_name_descs_use_cert_pkey(
struct bdd_name_descs *name_descriptions,
X509 **x509_ref,
EVP_PKEY **pkey_ref
);
struct bdd_name_descs *bdd_name_descs_create(void);
void bdd_name_descs_destroy(struct bdd_name_descs **name_descs);
#endif

1
core/inc/hashmap Symbolic link
View File

@ -0,0 +1 @@
../hashmap/headers

View File

@ -13,7 +13,7 @@
#include "headers/unlikely.h"
#include "headers/debug_log.h"
#include "headers/conversations.h"
#include "headers/name_descriptions.h"
#include "headers/name_descs.h"
#include "headers/bdd_service.h"
#include "headers/signal.h"
@ -23,8 +23,9 @@ int bdd_alpn_cb(
unsigned char *outlen,
const unsigned char *_,
unsigned int __,
struct bdd_accept_ctx *ctx
struct bdd_instance *instance
) {
struct bdd_accept_ctx *ctx = &(instance->accept.ctx);
if (ctx->protocol_name == NULL) {
return SSL_TLSEXT_ERR_NOACK;
}
@ -33,7 +34,11 @@ int bdd_alpn_cb(
return SSL_TLSEXT_ERR_OK;
}
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_accept_ctx *ctx) {
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_instance *instance) {
struct bdd_accept_ctx *ctx = &(instance->accept.ctx);
struct hashmap *name_descs = instance->name_descs;
struct hashmap_key key = HASHMAP_KEY_INITIALIZER;
int r = SSL_CLIENT_HELLO_ERROR;
const unsigned char *extension;
size_t extension_sz;
if (SSL_client_hello_get0_ext(client_ssl, TLSEXT_TYPE_server_name, &(extension), &(extension_sz)) == 0) {
@ -75,19 +80,21 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_accept_ctx *ctx) {
uint8_t found_req = 0;
for (size_t idx = 0;;) {
struct bdd_name_description *name_description = locked_hashmap_get_wl(
ctx->locked_name_descriptions,
(char *)&(name[idx]),
hashmap_key_obtain(
name_descs,
&(key),
&(name[idx]),
name_sz
);
if (name_description != NULL) {
if (!(found_req & 0b01) && name_description->x509 != NULL) {
struct bdd_name_desc *name_desc;
if (hashmap_get(name_descs, &(key), (void *)&(name_desc))) {
if (!(found_req & 0b01) && name_desc->x509 != NULL) {
found_req |= 0b01;
SSL_use_certificate(client_ssl, name_description->x509);
SSL_use_PrivateKey(client_ssl, name_description->pkey);
SSL_use_certificate(client_ssl, name_desc->x509);
SSL_use_PrivateKey(client_ssl, name_desc->pkey);
}
struct bdd_service_instance *inst;
if (!(found_req & 0b10) && (inst = name_description->service_instances) != NULL) {
if (!(found_req & 0b10) && (inst = name_desc->service_instances) != NULL) {
const char *cstr_protocol_name = NULL;
unsigned short int offset = alpn_sz;
struct bdd_service_instance *found = NULL;
@ -143,18 +150,21 @@ int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_accept_ctx *ctx) {
}
if (name_sz == 0) {
*alert = SSL_AD_UNRECOGNIZED_NAME;
return SSL_CLIENT_HELLO_ERROR;
goto out;
}
do {
idx += 1;
name_sz -= 1;
} while (name_sz != 0 && name[idx] != '.');
}
return SSL_CLIENT_HELLO_SUCCESS;
r = SSL_CLIENT_HELLO_SUCCESS;
out:;
hashmap_key_release(instance->name_descs, &(key), false);
return r;
}
void *bdd_accept(struct bdd_instance *instance) {
struct bdd_accept_ctx *ctx = &(instance->accept.accept_ctx);
struct bdd_accept_ctx *ctx = &(instance->accept.ctx);
poll:;
while (poll(instance->accept.pollfds, 2, -1) < 0) {
if (errno != EINTR) {
@ -204,10 +214,6 @@ void *bdd_accept(struct bdd_instance *instance) {
goto err;
}
if ((ctx->locked_name_descriptions = hashmap_lock(instance->name_descriptions)) == NULL) {
BDD_DEBUG_LOG("failed to obtain name_descriptions\n");
goto err;
}
if (SSL_accept(client_ssl) <= 0) {
BDD_DEBUG_LOG("rejected tls setup\n");
goto err;
@ -242,16 +248,12 @@ void *bdd_accept(struct bdd_instance *instance) {
}
}
locked_hashmap_unlock(&(ctx->locked_name_descriptions));
goto poll;
err:;
BDD_DEBUG_LOG("failed to accept connection\n");
if (ctx->locked_name_descriptions != NULL) {
locked_hashmap_unlock(&(ctx->locked_name_descriptions));
}
if (client_ssl != NULL) {
SSL_free(client_ssl);
}

View File

@ -659,7 +659,7 @@ enum bdd_conversation_init_status bdd_conversation_init(
struct sockaddr client_sockaddr,
const struct bdd_service *service,
const char *protocol_name,
void *instance_info
const void *instance_info
) {
assert(service->n_max_io > 0);
SSL *client_ssl = (*client_ssl_ref);

View File

@ -9,7 +9,6 @@ struct bdd_accept_ctx {
struct bdd_service_instance *service_instance;
const unsigned char *protocol_name;
const char *cstr_protocol_name;
struct locked_hashmap *locked_name_descriptions;
};
int bdd_alpn_cb(
@ -18,9 +17,9 @@ int bdd_alpn_cb(
unsigned char *outlen,
const unsigned char *_,
unsigned int __,
struct bdd_accept_ctx *ctx
struct bdd_instance *instance
);
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_accept_ctx *ctx);
int bdd_hello_cb(SSL *client_ssl, int *alert, struct bdd_instance *instance);
void *bdd_accept(struct bdd_instance *instance);
#endif

View File

@ -0,0 +1,6 @@
#ifndef bidirectiond_core__bdd_name_descs__h
#define bidirectiond_core__bdd_name_descs__h
struct bdd_name_descs;
#endif

View File

@ -4,24 +4,24 @@
#include <stddef.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <hashmap/hashmap.h>
#include "bdd_io_id.h"
struct bdd_conversation;
struct bdd_name_descs;
struct bdd_service {
bool (*handle_events)(struct bdd_conversation *conversation, short int *revents);
bool (*conversation_init)(
struct bdd_conversation *conversation,
const char *protocol_name,
void *instance_info,
const void *instance_info,
bdd_io_id client_id,
struct sockaddr client_sockaddr
);
void (*instance_info_destructor)(void *instance_info);
bool (*instantiate)(
struct locked_hashmap *name_descriptions,
struct bdd_name_descs *name_descs,
const struct bdd_service *service,
size_t n_arguments,
const char **arguments

View File

@ -7,7 +7,7 @@
struct bdd_settings {
int sv_socket;
struct hashmap *name_descriptions;
struct bdd_name_descs *name_descs;
uint32_t client_timeout;
int epoll_timeout;

View File

@ -84,7 +84,7 @@ enum bdd_conversation_init_status bdd_conversation_init(
struct sockaddr client_sockaddr,
const struct bdd_service *service,
const char *protocol_name,
void *instance_info
const void *instance_info
);
struct bdd_conversation *bdd_conversation_obtain(struct bdd_instance *instance);
void bdd_conversation_release(struct bdd_instance *instance, struct bdd_conversation **conversation);

View File

@ -29,7 +29,7 @@ struct bdd_instance {
struct epoll_event *epoll_oevents;
int epoll_timeout;
void *name_descriptions;
void *name_descs;
struct timeval client_timeout;
@ -55,7 +55,7 @@ struct bdd_instance {
int eventfd;
struct pollfd pollfds[2];
SSL_CTX *ssl_ctx;
struct bdd_accept_ctx accept_ctx;
struct bdd_accept_ctx ctx;
} accept;
struct {

View File

@ -1,15 +1,15 @@
#ifndef bidirectiond_core__name_descriptions__h
#define bidirectiond_core__name_descriptions__h
#ifndef bidirectiond_core__name_descs__h
#define bidirectiond_core__name_descs__h
#include <openssl/ssl.h>
struct bdd_service_instance {
const struct bdd_service *service;
void *instance_info;
const void *instance_info;
struct bdd_service_instance *next;
};
struct bdd_name_description {
struct bdd_name_desc {
X509 *x509;
EVP_PKEY *pkey;
struct bdd_service_instance *service_instances;

View File

@ -70,7 +70,11 @@ void bdd_destroy(struct bdd_instance *instance) {
pthread_mutex_destroy(&(instance->available_conversations.mutex));
pthread_cond_destroy(&(instance->available_conversations.cond));
for (int idx = 0; idx < instance->conversations_idx; ++idx) {
for (
size_t idx = 0;
idx < instance->conversations_idx;
++idx
) {
bdd_conversation_deinit(&(instance->conversations[idx]));
pthread_mutex_destroy(&(instance->conversations[idx].skip_mutex));
}
@ -89,7 +93,11 @@ void bdd_destroy(struct bdd_instance *instance) {
pthread_cond_destroy(&(instance->available_workers.cond));
free(instance->available_workers.ids);
for (unsigned short int idx = 0; idx < instance->n_workers; ++idx) {
for (
size_t idx = 0;
idx < instance->n_workers;
++idx
) {
pthread_mutex_destroy(&(instance->workers[idx].work_mutex));
pthread_cond_destroy(&(instance->workers[idx].work_cond));
}
@ -123,8 +131,8 @@ struct bdd_instance *bdd_instance_alloc(void) {
instance->n_epoll_oevents = 0;
instance->epoll_oevents = NULL;
instance->epoll_timeout = -1;
// name_descriptions
instance->name_descriptions = NULL;
// name_descs
instance->name_descs = NULL;
// client timeout
instance->client_timeout.tv_sec = 0;
instance->client_timeout.tv_usec = 0;
@ -149,10 +157,9 @@ struct bdd_instance *bdd_instance_alloc(void) {
instance->accept.pollfds[idx].revents = 0;
}
instance->accept.ssl_ctx = NULL;
instance->accept.accept_ctx.service_instance = NULL;
instance->accept.accept_ctx.protocol_name = NULL;
instance->accept.accept_ctx.cstr_protocol_name = NULL;
instance->accept.accept_ctx.locked_name_descriptions = NULL;
instance->accept.ctx.service_instance = NULL;
instance->accept.ctx.protocol_name = NULL;
instance->accept.ctx.cstr_protocol_name = NULL;
instance->to_epoll.head = NULL;
// serve_eventfd
instance->serve_eventfd = -1;
@ -172,7 +179,7 @@ struct bdd_instance *bdd_go(struct bdd_settings settings) {
settings.sv_socket < 0 ||
settings.n_conversations <= 0 ||
settings.n_epoll_oevents <= 0 ||
settings.name_descriptions == NULL ||
settings.name_descs == NULL ||
settings.n_worker_threads <= 0
) {
return NULL;
@ -218,8 +225,8 @@ struct bdd_instance *bdd_go(struct bdd_settings settings) {
goto err;
}
instance->epoll_timeout = settings.epoll_timeout;
// name_descriptions
instance->name_descriptions = settings.name_descriptions;
// name_descs
instance->name_descs = settings.name_descs;
// client timeout
instance->client_timeout.tv_sec = (settings.client_timeout / 1000);
instance->client_timeout.tv_usec = (settings.client_timeout % 1000) * 1000;
@ -244,7 +251,11 @@ struct bdd_instance *bdd_go(struct bdd_settings settings) {
goto err;
}
// init conversations, and the available stack
for (int *idx = &(instance->conversations_idx); (*idx) < settings.n_conversations; ++(*idx)) {
for (
int *idx = &(instance->conversations_idx);
(*idx) < settings.n_conversations;
++(*idx)
) {
(*(uint8_t *)&(instance->conversations[(*idx)].struct_type)) = 0;
if (pthread_mutex_init(&(instance->conversations[(*idx)].skip_mutex), NULL) != 0) {
goto err;
@ -270,8 +281,8 @@ struct bdd_instance *bdd_go(struct bdd_settings settings) {
if ((instance->accept.ssl_ctx = bdd_ssl_ctx_skel()) == NULL) {
goto err;
}
SSL_CTX_set_alpn_select_cb(instance->accept.ssl_ctx, (void *)bdd_alpn_cb, &(instance->accept.accept_ctx));
SSL_CTX_set_client_hello_cb(instance->accept.ssl_ctx, (void *)bdd_hello_cb, &(instance->accept.accept_ctx));
SSL_CTX_set_alpn_select_cb(instance->accept.ssl_ctx, (void *)bdd_alpn_cb, instance);
SSL_CTX_set_client_hello_cb(instance->accept.ssl_ctx, (void *)bdd_hello_cb, instance);
// serve
if ((instance->serve_eventfd = eventfd(0, EFD_NONBLOCK)) < 0) {
goto err;
@ -330,12 +341,15 @@ struct bdd_instance *bdd_go(struct bdd_settings settings) {
workers[(*idx)].id = (*idx);
workers[(*idx)].conversations = NULL;
workers[(*idx)].conversations_appender = NULL;
if (!e && pthread_create(
&(pthid),
NULL,
(void *(*)(void *))(&(bdd_worker)),
&(workers[(*idx)])
) == 0) {
if (
!e &&
pthread_create(
&(pthid),
NULL,
(void *(*)(void *))(&(bdd_worker)),
&(workers[(*idx)])
) == 0
) {
instance->n_running_threads += 1;
} else {
e = true;

View File

@ -4,54 +4,55 @@
#include <openssl/x509v3.h>
#include <string.h>
#include "headers/name_descriptions.h"
#include "headers/name_descs.h"
#include "headers/bdd_name_descs.h"
#include "headers/bdd_service.h"
#include "headers/bdd_ssl_ctx_skel.h"
// struct bdd_name_description
struct bdd_name_description *bdd_name_description_alloc(void) {
struct bdd_name_description *name_description = malloc(sizeof(struct bdd_name_description));
if (name_description == NULL) {
// struct bdd_name_desc
struct bdd_name_desc *bdd_name_desc_alloc(void) {
struct bdd_name_desc *name_desc = malloc(sizeof(struct bdd_name_desc));
if (name_desc == NULL) {
return NULL;
}
name_description->x509 = NULL;
name_description->pkey = NULL;
name_description->service_instances = NULL;
return name_description;
name_desc->x509 = NULL;
name_desc->pkey = NULL;
name_desc->service_instances = NULL;
return name_desc;
}
void bdd_name_description_clean_cert_pkey(struct bdd_name_description *name_description) {
if (name_description->x509 != NULL) {
void bdd_name_desc_clean_cert_pkey(struct bdd_name_desc *name_desc) {
if (name_desc->x509 != NULL) {
// misleading function name; it actually
// decs the ref count and frees the shit
// if the rc hits 0
X509_free(name_description->x509);
EVP_PKEY_free(name_description->pkey);
name_description->x509 = NULL;
name_description->pkey = NULL;
X509_free(name_desc->x509);
EVP_PKEY_free(name_desc->pkey);
name_desc->x509 = NULL;
name_desc->pkey = NULL;
}
return;
}
void bdd_name_description_clean_services(struct bdd_name_description *name_description) {
void bdd_name_desc_clean_services(struct bdd_name_desc *name_desc) {
for (
struct bdd_service_instance **service_inst = &(name_description->service_instances);
struct bdd_service_instance **service_inst = &(name_desc->service_instances);
(*service_inst) != NULL;
) {
struct bdd_service_instance *curr = (*service_inst);
(*service_inst) = curr->next;
curr->service->instance_info_destructor(curr->instance_info);
curr->service->instance_info_destructor((void *)curr->instance_info);
free(curr);
}
return;
}
bool bdd_name_description_add_service_instance(
struct bdd_name_description *name_description,
struct bdd_service_instance *service_inst
bool bdd_name_desc_add_service_instance(
struct bdd_name_desc *name_desc,
struct bdd_service_instance **service_inst
) {
struct bdd_service_instance **curr = &(name_description->service_instances);
const char *const *inst_sp = service_inst->service->supported_protocols;
struct bdd_service_instance **curr = &(name_desc->service_instances);
const char *const *inst_sp = (*service_inst)->service->supported_protocols;
for (; (*curr) != NULL; curr = &((*curr)->next)) {
const char *const *curr_sp = (*curr)->service->supported_protocols;
if (inst_sp == NULL || curr_sp == NULL) {
@ -68,27 +69,35 @@ bool bdd_name_description_add_service_instance(
}
}
}
(*curr) = service_inst;
(*curr) = (*service_inst);
(*service_inst) = NULL;
return true;
}
void bdd_name_description_set_cert_pkey(struct bdd_name_description *name_description, X509 *x509, EVP_PKEY *pkey) {
bdd_name_description_clean_cert_pkey(name_description);
name_description->x509 = x509;
name_description->pkey = pkey;
void bdd_name_desc_set_cert_pkey(struct bdd_name_desc *name_desc, X509 *x509, EVP_PKEY *pkey) {
bdd_name_desc_clean_cert_pkey(name_desc);
name_desc->x509 = x509;
name_desc->pkey = pkey;
return;
}
void bdd_name_description_destroy(struct bdd_name_description *name_description) {
bdd_name_description_clean_services(name_description);
bdd_name_description_clean_cert_pkey(name_description);
free(name_description);
void bdd_name_desc_destroy(struct bdd_name_desc *name_desc) {
bdd_name_desc_clean_services(name_desc);
bdd_name_desc_clean_cert_pkey(name_desc);
free(name_desc);
return;
}
void bdd_name_desc_destroy_hm(struct bdd_name_desc *name_desc, enum hashmap_drop_mode _) {
bdd_name_desc_destroy(name_desc);
return;
}
// name_descriptions hashmap
#define bdd_name_descriptions() \
// name_descs hashmap
#define bdd_name_descs_prelude() \
bool r = false; \
struct hashmap *name_descs = (struct hashmap *)bdd_name_descs; \
if (scope_sz > 254 || (scope_sz == 254 && scope[253] != '.')) { \
return false; \
} \
@ -102,77 +111,91 @@ void bdd_name_description_destroy(struct bdd_name_description *name_description)
scope += 1; \
scope_sz -= 1; \
} \
struct bdd_name_description *name_description \
= locked_hashmap_get_wl(name_descriptions, (char *)scope, scope_sz); \
bool created_name_description; \
if (name_description == NULL) { \
if ((name_description = bdd_name_description_alloc()) == NULL) { \
return false; \
struct hashmap_key key = HASHMAP_KEY_INITIALIZER; \
hashmap_key_obtain(name_descs, &(key), (char *)scope, scope_sz); \
struct bdd_name_desc *name_desc; \
bool created_name_desc; \
if (!hashmap_get(name_descs, &(key), (void *)&(name_desc))) { \
if ((name_desc = bdd_name_desc_alloc()) == NULL) { \
goto out; \
} \
created_name_description = true; \
created_name_desc = true; \
} else { \
created_name_description = false; \
created_name_desc = false; \
}
#define bdd_name_descs_out() \
out:; \
hashmap_key_release(name_descs, &(key), false); \
return r;
// exposed function
bool bdd_name_descriptions_add_service_instance(
struct locked_hashmap *name_descriptions,
// bdd_name_descs_add_service_instance **cannot** replace a service instance;
// it may only add service instances.
bool bdd_name_descs_add_service_instance(
struct bdd_name_descs *bdd_name_descs,
const char *scope,
size_t scope_sz,
const struct bdd_service *service,
void **instance_info
const void **instance_info
) {
bdd_name_descriptions();
bdd_name_descs_prelude();
struct bdd_service_instance *service_inst = malloc(sizeof(struct bdd_service_instance));
service_inst->service = service;
service_inst->next = NULL;
if (!bdd_name_description_add_service_instance(name_description, service_inst)) {
if (created_name_description) {
bdd_name_description_destroy(name_description);
if (!bdd_name_desc_add_service_instance(name_desc, &(service_inst))) {
if (created_name_desc) {
bdd_name_desc_destroy(name_desc);
}
free(service_inst);
return false;
goto out;
}
if (created_name_description) {
if (!locked_hashmap_set_wl(name_descriptions, (char *)scope, scope_sz, name_description, 1)) {
if (created_name_desc) {
if (!hashmap_set(name_descs, &(key), name_desc)) {
// will free service_inst
bdd_name_description_destroy(name_description);
return false;
bdd_name_desc_destroy(name_desc);
goto out;
}
}
service_inst->instance_info = *instance_info;
*instance_info = NULL;
return true;
r = true;
goto out;
bdd_name_descs_out();
}
// internal function
bool bdd_name_descriptions_set_cert_pkey(
struct locked_hashmap *name_descriptions,
bool bdd_name_descs_set_cert_pkey(
struct bdd_name_descs *bdd_name_descs,
const char *scope,
size_t scope_sz,
X509 *x509,
EVP_PKEY *pkey
) {
bdd_name_descriptions();
bdd_name_descs_prelude();
bdd_name_description_set_cert_pkey(name_description, x509, pkey);
bdd_name_desc_set_cert_pkey(name_desc, x509, pkey);
if (created_name_description) {
if (!locked_hashmap_set_wl(name_descriptions, (char *)scope, scope_sz, name_description, 1)) {
bdd_name_description_destroy(name_description);
return false;
if (created_name_desc) {
if (!hashmap_set(name_descs, &(key), name_desc)) {
bdd_name_desc_destroy(name_desc);
goto out;
}
}
return true;
r = true;
goto out;
bdd_name_descs_out();
}
// exposed function
bool bdd_name_descriptions_use_cert_pkey(
struct locked_hashmap *name_descriptions,
bool bdd_name_descs_use_cert_pkey(
struct bdd_name_descs *bdd_name_descs,
X509 **x509_ref,
EVP_PKEY **pkey_ref
) {
@ -193,8 +216,8 @@ bool bdd_name_descriptions_use_cert_pkey(
}
ASN1_IA5STRING *asn1_str = entry->d.dNSName;
int data_length = asn1_str->length;
bool s = bdd_name_descriptions_set_cert_pkey(
name_descriptions,
bool s = bdd_name_descs_set_cert_pkey(
bdd_name_descs,
(char *)asn1_str->data,
data_length,
x509,
@ -228,8 +251,8 @@ bool bdd_name_descriptions_use_cert_pkey(
continue;
}
int data_length = asn1_str->length;
bool s = bdd_name_descriptions_set_cert_pkey(
name_descriptions,
bool s = bdd_name_descs_set_cert_pkey(
bdd_name_descs,
(char *)asn1_str->data,
data_length,
x509,
@ -259,6 +282,11 @@ bool bdd_name_descriptions_use_cert_pkey(
return true;
}
struct hashmap *bdd_name_descriptions_create(void) {
return hashmap_create((void (*)(void *)) & (bdd_name_description_destroy));
struct bdd_name_descs *bdd_name_descs_create(void) {
return (struct bdd_name_descs *)hashmap_create(183, 1, (void *)&(bdd_name_desc_destroy_hm));
}
void bdd_name_descs_destroy(struct bdd_name_descs **name_descs) {
hashmap_destroy_ref((struct hashmap **)name_descs);
return;
}

1
inc/bdd-core Symbolic link
View File

@ -0,0 +1 @@
../core/headers

View File

@ -1 +0,0 @@
../src/core

View File

@ -1 +0,0 @@
../src/hashmap/

108
services/glue.py Normal file
View File

@ -0,0 +1,108 @@
#!/usr/bin/env python3
import sys, json, os, tempfile, subprocess, glob
dir_path = os.path.dirname(__file__)
declarations = ""
services = "const struct bdd_service services[] = {"
n_services = 0
def append_service(service):
service_str = "{"
key, value = None, None
#
key = "conversation_init"
if key in service:
value = service[key]
if type(value) != str:
raise Exception("error")
declarations += f"bool {value}(struct bdd_conversation *conversation, const char *protocol_name, void *instance_info, bdd_io_id client_id, struct sockaddr client_sockaddr);"
else:
value = "NULL"
service_str += f".{key} = &({value}),"
#
key = "instance_info_destructor"
if key in service:
value = service[key]
if type(value) != str:
raise Exception("error")
declarations += f"void {value}(void *instance_info);"
else:
value = "NULL"
service_str += f".{key} = &({value}),"
#
key = "instantiate"
value = service[key]
if type(value) != str:
raise Exception("error")
declarations += f"void {value}(void *instance_info);"
service_str += f".{key} = &({value}),"
#
key = "n_max_io"
n_max_io = service[key]
if type(n_max_io) != int:
raise Exception("error")
service_str += f".{key} = {n_max_io},"
#
key = "handle_events"
value = service[key]
if type(value) != str:
raise Exception("error")
declarations += f"void {key}(struct bdd_conversation *conversation, const short int (*revents)[{n_max_io}]);"
service_str += f".{key} = &({value}),"
#
key = "supported_protocols"
if key in service:
if type(service[key]) != list:
raise Exception("error")
value = "(const char *[]){"
for entry in service[key]:
if type(entry) != str:
raise Exception("error")
value += json.dumps(entry)
value += ","
value += "NULL}"
else:
value = "NULL"
service_str += f".{key} = {value},"
#
key = "supported_arguments"
if type(service[key]) != list:
raise Exception("error")
value = "(const char *[]){"
for entry in service[key]:
if type(entry) != str:
raise Exception("error")
value += json.dumps(entry)
value += ","
value += "NULL}"
service_str += f".{key} = {value},"
#
key = "arguments_help"
value = service[key]
if type(value) != str:
raise Exception("error")
service_str += f".{key} = (char *){value},"
#
service_str += "},"
services += service_str
n_services += 1
for path in glob.glob(os.path.join(dir_path, "*/service.json")):
fd = open(path)
append_service(json.load(fd))
fd.close()
services += "};const size_t n_services = " + str(n_services) + ";"
fd = tempfile.NamedTemporaryFile(delete=False, suffix=".c")
fd.write(b"#include <bdd-core/settings.h>\n" + bytes(declarations, "ascii") + bytes(services, "ascii"))
fd.close()
subprocess.run([
"gcc",
"-c", fd.name,
"-o", os.path.join(dir_path, "..", "build", "glue.o"),
"-I" + os.path.join(dir_path, "..", "inc"),
])
os.unlink(fd.name)

View File

@ -1,24 +0,0 @@
#ifndef bidirectiond_core__settings__h
#define bidirectiond_core__settings__h
#include <openssl/ssl.h>
#include <hashmap/hashmap.h>
#include <stdbool.h>
#include "src/headers/bdd_settings.h"
#include "src/headers/bdd_service.h"
#include "src/headers/bdd_stop.h"
struct bdd_instance;
struct bdd_instance *bdd_go(struct bdd_settings settings);
void bdd_wait(struct bdd_instance *instance);
void bdd_destroy(struct bdd_instance *instance);
bool bdd_name_descriptions_use_cert_pkey(
struct locked_hashmap *name_descriptions,
X509 **x509_ref,
EVP_PKEY **pkey_ref
);
struct hashmap *bdd_name_descriptions_create(void);
#endif

@ -1 +0,0 @@
Subproject commit 1efff1ccf6a2169a2f18a040e690cd0166d6e2e8