aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-usockets/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/bun-usockets/src')
-rw-r--r--packages/bun-usockets/src/crypto/openssl.c2993
-rw-r--r--packages/bun-usockets/src/internal/internal.h344
2 files changed, 1834 insertions, 1503 deletions
diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c
index 9819c90d4..eb494a40c 100644
--- a/packages/bun-usockets/src/crypto/openssl.c
+++ b/packages/bun-usockets/src/crypto/openssl.c
@@ -18,11 +18,11 @@
#if (defined(LIBUS_USE_OPENSSL) || defined(LIBUS_USE_WOLFSSL))
/* These are in sni_tree.cpp */
-void* sni_new();
-void sni_free(void* sni, void (*cb)(void*));
-int sni_add(void* sni, const char* hostname, void* user);
-void* sni_remove(void* sni, const char* hostname);
-void* sni_find(void* sni, const char* hostname);
+void *sni_new();
+void sni_free(void *sni, void (*cb)(void *));
+int sni_add(void *sni, const char *hostname, void *user);
+void *sni_remove(void *sni, const char *hostname);
+void *sni_find(void *sni, const char *hostname);
#include "internal/internal.h"
#include "libusockets.h"
@@ -44,1637 +44,1892 @@ void* sni_find(void* sni, const char* hostname);
#endif
#include "./root_certs.h"
-// #include <stdatomic.h>
-static const size_t root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]);
-static X509* root_cert_instances[1] = { NULL };
-// static atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT;
-// static atomic_bool root_cert_instances_initialized = 0;
+static const size_t root_certs_size =
+ sizeof(root_certs) / sizeof(root_certs[0]);
+static X509 *root_cert_instances[root_certs_size] = {NULL};
/* These are in root_certs.cpp */
-extern X509_STORE* us_get_default_ca_store();
+extern X509_STORE *us_get_default_ca_store();
struct loop_ssl_data {
- char *ssl_read_input, *ssl_read_output;
- unsigned int ssl_read_input_length;
- unsigned int ssl_read_input_offset;
+ char *ssl_read_input, *ssl_read_output;
+ unsigned int ssl_read_input_length;
+ unsigned int ssl_read_input_offset;
- struct us_socket_t* ssl_socket;
+ struct us_socket_t *ssl_socket;
- int last_write_was_msg_more;
- int msg_more;
+ int last_write_was_msg_more;
+ int msg_more;
- BIO* shared_rbio;
- BIO* shared_wbio;
- BIO_METHOD* shared_biom;
+ BIO *shared_rbio;
+ BIO *shared_wbio;
+ BIO_METHOD *shared_biom;
};
struct us_internal_ssl_socket_context_t {
- struct us_socket_context_t sc;
-
- // this thing can be shared with other socket contexts via socket transfer!
- // maybe instead of holding once you hold many, a vector or set
- // when a socket that belongs to another socket context transfers to a new socket context
- SSL_CTX* ssl_context;
- int is_parent;
-
- /* These decorate the base implementation */
- struct us_internal_ssl_socket_t* (*on_open)(struct us_internal_ssl_socket_t*, int is_client, char* ip, int ip_length);
- struct us_internal_ssl_socket_t* (*on_data)(struct us_internal_ssl_socket_t*, char* data, int length);
- struct us_internal_ssl_socket_t* (*on_writable)(struct us_internal_ssl_socket_t*);
- struct us_internal_ssl_socket_t* (*on_close)(struct us_internal_ssl_socket_t*, int code, void* reason);
-
- /* Called for missing SNI hostnames, if not NULL */
- void (*on_server_name)(struct us_internal_ssl_socket_context_t*, const char* hostname);
-
- /* Pointer to sni tree, created when the context is created and freed likewise when freed */
- void* sni;
-
- us_internal_on_handshake_t on_handshake;
- void* handshake_data;
+ struct us_socket_context_t sc;
+
+ // this thing can be shared with other socket contexts via socket transfer!
+ // maybe instead of holding once you hold many, a vector or set
+ // when a socket that belongs to another socket context transfers to a new
+ // socket context
+ SSL_CTX *ssl_context;
+ int is_parent;
+
+ /* These decorate the base implementation */
+ struct us_internal_ssl_socket_t *(*on_open)(struct us_internal_ssl_socket_t *,
+ int is_client, char *ip,
+ int ip_length);
+ struct us_internal_ssl_socket_t *(*on_data)(struct us_internal_ssl_socket_t *,
+ char *data, int length);
+ struct us_internal_ssl_socket_t *(*on_writable)(
+ struct us_internal_ssl_socket_t *);
+ struct us_internal_ssl_socket_t *(*on_close)(
+ struct us_internal_ssl_socket_t *, int code, void *reason);
+
+ /* Called for missing SNI hostnames, if not NULL */
+ void (*on_server_name)(struct us_internal_ssl_socket_context_t *,
+ const char *hostname);
+
+ /* Pointer to sni tree, created when the context is created and freed likewise
+ * when freed */
+ void *sni;
+
+ us_internal_on_handshake_t on_handshake;
+ void *handshake_data;
};
// same here, should or shouldn't it contain s?
struct us_internal_ssl_socket_t {
- struct us_socket_t s;
- SSL* ssl;
- int ssl_write_wants_read; // we use this for now
- int ssl_read_wants_write;
- int pending_handshake;
+ struct us_socket_t s;
+ SSL *ssl;
+ int ssl_write_wants_read; // we use this for now
+ int ssl_read_wants_write;
+ int pending_handshake;
};
-int passphrase_cb(char* buf, int size, int rwflag, void* u)
-{
- const char* passphrase = (const char*)u;
- size_t passphrase_length = strlen(passphrase);
- memcpy(buf, passphrase, passphrase_length);
- // put null at end? no?
- return (int)passphrase_length;
+int passphrase_cb(char *buf, int size, int rwflag, void *u) {
+ const char *passphrase = (const char *)u;
+ size_t passphrase_length = strlen(passphrase);
+ memcpy(buf, passphrase, passphrase_length);
+ // put null at end? no?
+ return (int)passphrase_length;
}
-int BIO_s_custom_create(BIO* bio)
-{
- BIO_set_init(bio, 1);
- return 1;
+int BIO_s_custom_create(BIO *bio) {
+ BIO_set_init(bio, 1);
+ return 1;
}
-long BIO_s_custom_ctrl(BIO* bio, int cmd, long num, void* user)
-{
- switch (cmd) {
- case BIO_CTRL_FLUSH:
- return 1;
- default:
- return 0;
- }
+long BIO_s_custom_ctrl(BIO *bio, int cmd, long num, void *user) {
+ switch (cmd) {
+ case BIO_CTRL_FLUSH:
+ return 1;
+ default:
+ return 0;
+ }
}
-int BIO_s_custom_write(BIO* bio, const char* data, int length)
-{
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)BIO_get_data(bio);
+int BIO_s_custom_write(BIO *bio, const char *data, int length) {
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)BIO_get_data(bio);
- loop_ssl_data->last_write_was_msg_more = loop_ssl_data->msg_more || length == 16413;
- int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length, loop_ssl_data->last_write_was_msg_more);
+ loop_ssl_data->last_write_was_msg_more =
+ loop_ssl_data->msg_more || length == 16413;
+ int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length,
+ loop_ssl_data->last_write_was_msg_more);
- if (!written) {
- BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_WRITE);
- return -1;
- }
+ if (!written) {
+ BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_WRITE);
+ return -1;
+ }
- // printf("BIO_s_custom_write returns: %d\n", written);
+ // printf("BIO_s_custom_write returns: %d\n", written);
- return written;
+ return written;
}
-int BIO_s_custom_read(BIO* bio, char* dst, int length)
-{
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)BIO_get_data(bio);
+int BIO_s_custom_read(BIO *bio, char *dst, int length) {
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)BIO_get_data(bio);
- // printf("BIO_s_custom_read\n");
+ // printf("BIO_s_custom_read\n");
- if (!loop_ssl_data->ssl_read_input_length) {
- BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ);
- return -1;
- }
+ if (!loop_ssl_data->ssl_read_input_length) {
+ BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ);
+ return -1;
+ }
- if ((unsigned int)length > loop_ssl_data->ssl_read_input_length) {
- length = loop_ssl_data->ssl_read_input_length;
- }
+ if ((unsigned int)length > loop_ssl_data->ssl_read_input_length) {
+ length = loop_ssl_data->ssl_read_input_length;
+ }
- memcpy(dst, loop_ssl_data->ssl_read_input + loop_ssl_data->ssl_read_input_offset, length);
+ memcpy(dst,
+ loop_ssl_data->ssl_read_input + loop_ssl_data->ssl_read_input_offset,
+ length);
- loop_ssl_data->ssl_read_input_offset += length;
- loop_ssl_data->ssl_read_input_length -= length;
- return length;
+ loop_ssl_data->ssl_read_input_offset += length;
+ loop_ssl_data->ssl_read_input_length -= length;
+ return length;
}
-struct us_internal_ssl_socket_t* ssl_on_open(struct us_internal_ssl_socket_t* s, int is_client, char* ip, int ip_length)
-{
+struct us_internal_ssl_socket_t *ssl_on_open(struct us_internal_ssl_socket_t *s,
+ int is_client, char *ip,
+ int ip_length) {
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
- struct us_loop_t* loop = us_socket_context_loop(0, &context->sc);
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
+ struct us_loop_t *loop = us_socket_context_loop(0, &context->sc);
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
- s->ssl = SSL_new(context->ssl_context);
- s->ssl_write_wants_read = 0;
- s->ssl_read_wants_write = 0;
+ s->ssl = SSL_new(context->ssl_context);
+ s->ssl_write_wants_read = 0;
+ s->ssl_read_wants_write = 0;
- SSL_set_bio(s->ssl, loop_ssl_data->shared_rbio, loop_ssl_data->shared_wbio);
+ SSL_set_bio(s->ssl, loop_ssl_data->shared_rbio, loop_ssl_data->shared_wbio);
- BIO_up_ref(loop_ssl_data->shared_rbio);
- BIO_up_ref(loop_ssl_data->shared_wbio);
+ BIO_up_ref(loop_ssl_data->shared_rbio);
+ BIO_up_ref(loop_ssl_data->shared_wbio);
- if (is_client) {
- SSL_set_connect_state(s->ssl);
- } else {
- SSL_set_accept_state(s->ssl);
- }
+ if (is_client) {
+ SSL_set_connect_state(s->ssl);
+ } else {
+ SSL_set_accept_state(s->ssl);
+ }
- struct us_internal_ssl_socket_t* result = (struct us_internal_ssl_socket_t*)context->on_open(s, is_client, ip, ip_length);
+ struct us_internal_ssl_socket_t *result =
+ (struct us_internal_ssl_socket_t *)context->on_open(s, is_client, ip,
+ ip_length);
- // Hello Message!
- // always handshake after open if on_handshake is set
- if (context->on_handshake || s->pending_handshake) {
- s->pending_handshake = 1;
- us_internal_ssl_handshake(s, context->on_handshake, context->handshake_data);
- }
+ // Hello Message!
+ // always handshake after open if on_handshake is set
+ if (context->on_handshake || s->pending_handshake) {
+ s->pending_handshake = 1;
+ us_internal_ssl_handshake(s);
+ }
- return result;
+ return result;
}
-void us_internal_on_ssl_handshake(struct us_internal_ssl_socket_context_t* context, void (*on_handshake)(struct us_internal_ssl_socket_t*, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data)
-{
- context->on_handshake = on_handshake;
- context->handshake_data = custom_data;
+void us_internal_on_ssl_handshake(
+ struct us_internal_ssl_socket_context_t *context,
+ void (*on_handshake)(struct us_internal_ssl_socket_t *, int success,
+ struct us_bun_verify_error_t verify_error,
+ void *custom_data),
+ void *custom_data) {
+ context->on_handshake = on_handshake;
+ context->handshake_data = custom_data;
}
-void us_internal_ssl_handshake(struct us_internal_ssl_socket_t* s, us_internal_on_handshake_t on_handshake, void* custom_data)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+void us_internal_ssl_handshake(struct us_internal_ssl_socket_t *s) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ void (*on_handshake)(struct us_internal_ssl_socket_t *, int,
+ struct us_bun_verify_error_t, void *) =
+ context->on_handshake;
+ void *custom_data = context->handshake_data;
- // will start on_open, on_writable or on_data
- if (!s->ssl) {
+ // will start on_open, on_writable or on_data
+ if (!s->ssl) {
+ s->pending_handshake = 1;
+ return;
+ }
- s->pending_handshake = 1;
- context->on_handshake = on_handshake;
- context->handshake_data = custom_data;
- return;
- }
+ struct us_loop_t *loop = us_socket_context_loop(0, &context->sc);
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
- struct us_loop_t* loop = us_socket_context_loop(0, &context->sc);
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
+ loop_ssl_data->ssl_socket = &s->s;
- loop_ssl_data->ssl_socket = &s->s;
+ if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
+ s->pending_handshake = 0;
- if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
- s->pending_handshake = 0;
+ struct us_bun_verify_error_t verify_error = (struct us_bun_verify_error_t){
+ .error = 0, .code = NULL, .reason = NULL};
+ if (on_handshake != NULL) {
+ on_handshake(s, 0, verify_error, custom_data);
+ }
+ return;
+ }
+
+ int result = SSL_do_handshake(s->ssl);
+ if (result <= 0) {
+ int err = SSL_get_error(s->ssl, result);
+ // as far as I know these are the only errors we want to handle
+ if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
+ s->pending_handshake = 0;
+
+ struct us_bun_verify_error_t verify_error = us_internal_verify_error(s);
+ // clear per thread error queue if it may contain something
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
+ ERR_clear_error();
+ }
+
+ // error
+ if (on_handshake != NULL) {
+ on_handshake(s, 0, verify_error, custom_data);
+ }
+ return;
+ } else {
- struct us_bun_verify_error_t verify_error = (struct us_bun_verify_error_t) { .error = 0, .code = NULL, .reason = NULL };
- if (on_handshake != NULL) {
- on_handshake(s, 0, verify_error, custom_data);
- }
- return;
+ s->pending_handshake = 1;
+ context->on_handshake = on_handshake;
+ context->handshake_data = custom_data;
+ // Ensure that we'll cycle through internal openssl's state
+ if (!us_socket_is_closed(0, &s->s) &&
+ !us_internal_ssl_socket_is_shut_down(s)) {
+ us_socket_write(1, loop_ssl_data->ssl_socket, "\0", 0, 0);
+ }
}
+ } else {
+ s->pending_handshake = 0;
- int result = SSL_do_handshake(s->ssl);
-
- if (result <= 0) {
- int err = SSL_get_error(s->ssl, result);
- // as far as I know these are the only errors we want to handle
- if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
- s->pending_handshake = 0;
-
- struct us_bun_verify_error_t verify_error = us_internal_verify_error(s);
- // clear per thread error queue if it may contain something
- if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
- ERR_clear_error();
- }
-
- // error
- if (on_handshake != NULL) {
- on_handshake(s, 0, verify_error, custom_data);
- }
- return;
- } else {
- s->pending_handshake = 1;
- context->on_handshake = on_handshake;
- context->handshake_data = custom_data;
- // Ensure that we'll cycle through internal openssl's state
- if (!us_socket_is_closed(0, &s->s) && !us_internal_ssl_socket_is_shut_down(s)) {
- us_socket_write(1, loop_ssl_data->ssl_socket, "\0", 0, 0);
- }
- }
- } else {
- s->pending_handshake = 0;
-
- struct us_bun_verify_error_t verify_error = us_internal_verify_error(s);
- // success
- if (on_handshake != NULL) {
- on_handshake(s, 1, verify_error, custom_data);
- }
- // Ensure that we'll cycle through internal openssl's state
- if (!us_socket_is_closed(0, &s->s) && !us_internal_ssl_socket_is_shut_down(s)) {
- us_socket_write(1, loop_ssl_data->ssl_socket, "\0", 0, 0);
- }
+ struct us_bun_verify_error_t verify_error = us_internal_verify_error(s);
+ // success
+ if (on_handshake != NULL) {
+ on_handshake(s, 1, verify_error, custom_data);
}
+ // Ensure that we'll cycle through internal openssl's state
+ if (!us_socket_is_closed(0, &s->s) &&
+ !us_internal_ssl_socket_is_shut_down(s)) {
+ us_socket_write(1, loop_ssl_data->ssl_socket, "\0", 0, 0);
+ }
+ }
}
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_close(struct us_internal_ssl_socket_t* s, int code, void* reason)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- if (s->pending_handshake) {
- s->pending_handshake = 0;
+struct us_internal_ssl_socket_t *
+us_internal_ssl_socket_close(struct us_internal_ssl_socket_t *s, int code,
+ void *reason) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ if (s->pending_handshake) {
+ s->pending_handshake = 0;
+ if (context->on_handshake != NULL) {
+ struct us_bun_verify_error_t verify_error = us_internal_verify_error(s);
+ context->on_handshake(s, 0, verify_error, context->handshake_data);
}
- return (struct us_internal_ssl_socket_t*)us_socket_close(0, (struct us_socket_t*)s, code, reason);
+ }
+ return (struct us_internal_ssl_socket_t *)us_socket_close(
+ 0, (struct us_socket_t *)s, code, reason);
}
-struct us_internal_ssl_socket_t* ssl_on_close(struct us_internal_ssl_socket_t* s, int code, void* reason)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- if (s->pending_handshake) {
- s->pending_handshake = 0;
- }
- SSL_free(s->ssl);
+struct us_internal_ssl_socket_t *
+ssl_on_close(struct us_internal_ssl_socket_t *s, int code, void *reason) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ if (s->pending_handshake) {
+ s->pending_handshake = 0;
+ }
+ SSL_free(s->ssl);
- return context->on_close(s, code, reason);
+ return context->on_close(s, code, reason);
}
-struct us_internal_ssl_socket_t* ssl_on_end(struct us_internal_ssl_socket_t* s)
-{
- if (s && s->pending_handshake) {
- s->pending_handshake = 0;
- }
- // whatever state we are in, a TCP FIN is always an answered shutdown
+struct us_internal_ssl_socket_t *
+ssl_on_end(struct us_internal_ssl_socket_t *s) {
+ if (&s->s && s->pending_handshake) {
+ s->pending_handshake = 0;
+ }
+ // whatever state we are in, a TCP FIN is always an answered shutdown
- /* Todo: this should report CLEANLY SHUTDOWN as reason */
- return us_internal_ssl_socket_close(s, 0, NULL);
+ /* Todo: this should report CLEANLY SHUTDOWN as reason */
+ return us_internal_ssl_socket_close(s, 0, NULL);
}
// this whole function needs a complete clean-up
-struct us_internal_ssl_socket_t* ssl_on_data(struct us_internal_ssl_socket_t* s, void* data, int length)
-{
+struct us_internal_ssl_socket_t *ssl_on_data(struct us_internal_ssl_socket_t *s,
+ void *data, int length) {
+
+ // note: this context can change when we adopt the socket!
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+
+ struct us_loop_t *loop = us_socket_context_loop(0, &context->sc);
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
+
+ if (s->pending_handshake) {
+ us_internal_ssl_handshake(s);
+ }
+
+ // note: if we put data here we should never really clear it (not in write
+ // either, it still should be available for SSL_write to read from!)
+ loop_ssl_data->ssl_read_input = data;
+ loop_ssl_data->ssl_read_input_length = length;
+ loop_ssl_data->ssl_read_input_offset = 0;
+ loop_ssl_data->ssl_socket = &s->s;
+ loop_ssl_data->msg_more = 0;
+
+ if (us_socket_is_closed(0, &s->s)) {
+ return s;
+ }
- // note: this context can change when we adopt the socket!
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ if (us_internal_ssl_socket_is_shut_down(s)) {
- struct us_loop_t* loop = us_socket_context_loop(0, &context->sc);
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
+ int ret = 0;
+ if ((ret = SSL_shutdown(s->ssl)) == 1) {
+ // two phase shutdown is complete here
+ // printf("Two step SSL shutdown complete\n");
- if (s->pending_handshake) {
- us_internal_ssl_handshake(s, context->on_handshake, context->handshake_data);
- }
+ /* Todo: this should also report some kind of clean shutdown */
+ return us_internal_ssl_socket_close(s, 0, NULL);
+ } else if (ret < 0) {
- // note: if we put data here we should never really clear it (not in write either, it still should be available for SSL_write to read from!)
- loop_ssl_data->ssl_read_input = data;
- loop_ssl_data->ssl_read_input_length = length;
- loop_ssl_data->ssl_read_input_offset = 0;
- loop_ssl_data->ssl_socket = &s->s;
- loop_ssl_data->msg_more = 0;
+ int err = SSL_get_error(s->ssl, ret);
- if (us_socket_is_closed(0, &s->s)) {
- return s;
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
+ // we need to clear the error queue in case these added to the thread
+ // local queue
+ ERR_clear_error();
+ }
}
- if (us_internal_ssl_socket_is_shut_down(s)) {
-
- int ret = 0;
- if ((ret = SSL_shutdown(s->ssl)) == 1) {
- // two phase shutdown is complete here
- // printf("Two step SSL shutdown complete\n");
-
- /* Todo: this should also report some kind of clean shutdown */
- return us_internal_ssl_socket_close(s, 0, NULL);
- } else if (ret < 0) {
-
- int err = SSL_get_error(s->ssl, ret);
-
- if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
- // we need to clear the error queue in case these added to the thread local queue
- ERR_clear_error();
- }
- }
-
- // no further processing of data when in shutdown state
- return s;
- }
+ // no further processing of data when in shutdown state
+ return s;
+ }
- // bug checking: this loop needs a lot of attention and clean-ups and check-ups
- int read = 0;
+ // bug checking: this loop needs a lot of attention and clean-ups and
+ // check-ups
+ int read = 0;
restart:
- while (1) {
- int just_read = SSL_read(s->ssl, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING + read, LIBUS_RECV_BUFFER_LENGTH - read);
-
- if (just_read <= 0) {
- int err = SSL_get_error(s->ssl, just_read);
-
- // as far as I know these are the only errors we want to handle
- if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
-
- if (err == SSL_ERROR_ZERO_RETURN) {
- // zero return can be EOF/FIN, if we have data just signal on_data and close
- if (read) {
- context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
-
- s = context->on_data(s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING, read);
- if (us_socket_is_closed(0, &s->s)) {
- return s;
- }
- }
- // terminate connection here
- return us_internal_ssl_socket_close(s, 0, NULL);
- }
-
- if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
- // clear per thread error queue if it may contain something
-
- ERR_clear_error();
- }
-
- // terminate connection here
- return us_internal_ssl_socket_close(s, 0, NULL);
- } else {
- // emit the data we have and exit
-
- if (err == SSL_ERROR_WANT_WRITE) {
- // here we need to trigger writable event next ssl_read!
- s->ssl_read_wants_write = 1;
- }
-
- // assume we emptied the input buffer fully or error here as well!
- if (loop_ssl_data->ssl_read_input_length) {
- return us_internal_ssl_socket_close(s, 0, NULL);
- }
-
- // cannot emit zero length to app
- if (!read) {
- break;
- }
-
- context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
-
- s = context->on_data(s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING, read);
- if (us_socket_is_closed(0, &s->s)) {
- return s;
- }
-
- break;
+ while (1) {
+ int just_read = SSL_read(s->ssl,
+ loop_ssl_data->ssl_read_output +
+ LIBUS_RECV_BUFFER_PADDING + read,
+ LIBUS_RECV_BUFFER_LENGTH - read);
+
+ if (just_read <= 0) {
+ int err = SSL_get_error(s->ssl, just_read);
+
+ // as far as I know these are the only errors we want to handle
+ if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
+
+ if (err == SSL_ERROR_ZERO_RETURN) {
+ // zero return can be EOF/FIN, if we have data just signal on_data and
+ // close
+ if (read) {
+ context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(
+ 0, &s->s);
+
+ s = context->on_data(
+ s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING,
+ read);
+ if (us_socket_is_closed(0, &s->s)) {
+ return s;
}
+ }
+ // terminate connection here
+ return us_internal_ssl_socket_close(s, 0, NULL);
}
- read += just_read;
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
+ // clear per thread error queue if it may contain something
- // at this point we might be full and need to emit the data to application and start over
- if (read == LIBUS_RECV_BUFFER_LENGTH) {
+ ERR_clear_error();
+ }
- context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ // terminate connection here
+ return us_internal_ssl_socket_close(s, 0, NULL);
+ } else {
+ // emit the data we have and exit
- // emit data and restart
- s = context->on_data(s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING, read);
- if (us_socket_is_closed(0, &s->s)) {
- return s;
- }
+ if (err == SSL_ERROR_WANT_WRITE) {
+ // here we need to trigger writable event next ssl_read!
+ s->ssl_read_wants_write = 1;
+ }
- read = 0;
- goto restart;
+ // assume we emptied the input buffer fully or error here as well!
+ if (loop_ssl_data->ssl_read_input_length) {
+ return us_internal_ssl_socket_close(s, 0, NULL);
}
- }
- // trigger writable if we failed last write with want read
- if (s->ssl_write_wants_read) {
- s->ssl_write_wants_read = 0;
+ // cannot emit zero length to app
+ if (!read) {
+ break;
+ }
- // make sure to update context before we call (context can change if the user adopts the socket!)
- context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ context = (struct us_internal_ssl_socket_context_t *)us_socket_context(
+ 0, &s->s);
- s = (struct us_internal_ssl_socket_t*)context->sc.on_writable(&s->s); // cast here!
- // if we are closed here, then exit
+ s = context->on_data(
+ s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING,
+ read);
if (us_socket_is_closed(0, &s->s)) {
- return s;
+ return s;
}
+
+ break;
+ }
}
- // check this then?
- if (SSL_get_shutdown(s->ssl) & SSL_RECEIVED_SHUTDOWN) {
- // printf("SSL_RECEIVED_SHUTDOWN\n");
+ read += just_read;
- // exit(-2);
+ // at this point we might be full and need to emit the data to application
+ // and start over
+ if (read == LIBUS_RECV_BUFFER_LENGTH) {
- // not correct anyways!
- s = us_internal_ssl_socket_close(s, 0, NULL);
+ context = (struct us_internal_ssl_socket_context_t *)us_socket_context(
+ 0, &s->s);
- // us_
- }
+ // emit data and restart
+ s = context->on_data(
+ s, loop_ssl_data->ssl_read_output + LIBUS_RECV_BUFFER_PADDING, read);
+ if (us_socket_is_closed(0, &s->s)) {
+ return s;
+ }
- return s;
-}
+ read = 0;
+ goto restart;
+ }
+ }
-struct us_internal_ssl_socket_t* ssl_on_writable(struct us_internal_ssl_socket_t* s)
-{
+ // trigger writable if we failed last write with want read
+ if (s->ssl_write_wants_read) {
+ s->ssl_write_wants_read = 0;
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ // make sure to update context before we call (context can change if the
+ // user adopts the socket!)
+ context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
- if (s->pending_handshake) {
- us_internal_ssl_handshake(s, context->on_handshake, context->handshake_data);
+ s = (struct us_internal_ssl_socket_t *)context->sc.on_writable(
+ &s->s); // cast here!
+ // if we are closed here, then exit
+ if (us_socket_is_closed(0, &s->s)) {
+ return s;
}
+ }
- // todo: cork here so that we efficiently output both from reading and from writing?
- if (s->ssl_read_wants_write) {
- s->ssl_read_wants_write = 0;
+ // check this then?
+ if (SSL_get_shutdown(s->ssl) & SSL_RECEIVED_SHUTDOWN) {
+ // printf("SSL_RECEIVED_SHUTDOWN\n");
- // make sure to update context before we call (context can change if the user adopts the socket!)
- context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
+ // exit(-2);
- // if this one fails to write data, it sets ssl_read_wants_write again
- s = (struct us_internal_ssl_socket_t*)context->sc.on_data(&s->s, 0, 0); // cast here!
- }
+ // not correct anyways!
+ s = us_internal_ssl_socket_close(s, 0, NULL);
- // should this one come before we have read? should it come always? spurious on_writable is okay
- s = context->on_writable(s);
+ // us_
+ }
- return s;
+ return s;
}
-/* Lazily inits loop ssl data first time */
-void us_internal_init_loop_ssl_data(struct us_loop_t* loop)
-{
- if (!loop->data.ssl_data) {
- struct loop_ssl_data* loop_ssl_data = us_malloc(sizeof(struct loop_ssl_data));
- loop_ssl_data->ssl_read_input_length = 0;
- loop_ssl_data->ssl_read_input_offset = 0;
- loop_ssl_data->last_write_was_msg_more = 0;
- loop_ssl_data->msg_more = 0;
-
- loop_ssl_data->ssl_read_output = us_malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2);
-
- OPENSSL_init_ssl(0, NULL);
-
- loop_ssl_data->shared_biom = BIO_meth_new(BIO_TYPE_MEM, "µS BIO");
- BIO_meth_set_create(loop_ssl_data->shared_biom, BIO_s_custom_create);
- BIO_meth_set_write(loop_ssl_data->shared_biom, BIO_s_custom_write);
- BIO_meth_set_read(loop_ssl_data->shared_biom, BIO_s_custom_read);
- BIO_meth_set_ctrl(loop_ssl_data->shared_biom, BIO_s_custom_ctrl);
-
- loop_ssl_data->shared_rbio = BIO_new(loop_ssl_data->shared_biom);
- loop_ssl_data->shared_wbio = BIO_new(loop_ssl_data->shared_biom);
- BIO_set_data(loop_ssl_data->shared_rbio, loop_ssl_data);
- BIO_set_data(loop_ssl_data->shared_wbio, loop_ssl_data);
-
- loop->data.ssl_data = loop_ssl_data;
- }
-}
+struct us_internal_ssl_socket_t *
+ssl_on_writable(struct us_internal_ssl_socket_t *s) {
-/* Called by loop free, clears any loop ssl data */
-void us_internal_free_loop_ssl_data(struct us_loop_t* loop)
-{
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
- if (loop_ssl_data) {
- us_free(loop_ssl_data->ssl_read_output);
+ if (s->pending_handshake) {
+ us_internal_ssl_handshake(s);
+ }
- BIO_free(loop_ssl_data->shared_rbio);
- BIO_free(loop_ssl_data->shared_wbio);
+ // todo: cork here so that we efficiently output both from reading and from
+ // writing?
+ if (s->ssl_read_wants_write) {
+ s->ssl_read_wants_write = 0;
- BIO_meth_free(loop_ssl_data->shared_biom);
+ // make sure to update context before we call (context can change if the
+ // user adopts the socket!)
+ context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
- us_free(loop_ssl_data);
- }
-}
+ // if this one fails to write data, it sets ssl_read_wants_write again
+ s = (struct us_internal_ssl_socket_t *)context->sc.on_data(&s->s, 0,
+ 0); // cast here!
+ }
-// we throttle reading data for ssl sockets that are in init state. here we actually use
-// the kernel buffering to our advantage
-int ssl_is_low_prio(struct us_internal_ssl_socket_t* s)
-{
- /* We use SSL_in_before() instead of SSL_in_init(), because only the first step is CPU intensive, and we want to
- * speed up the rest of connection establishing if the CPU intensive work is already done, so fully established
- * connections increase lineary over time under high load */
- return SSL_in_init(s->ssl);
-}
+ // should this one come before we have read? should it come always? spurious
+ // on_writable is okay
+ s = context->on_writable(s);
-/* Per-context functions */
-void* us_internal_ssl_socket_context_get_native_handle(struct us_internal_ssl_socket_context_t* context)
-{
- return context->ssl_context;
+ return s;
}
-struct us_internal_ssl_socket_context_t* us_internal_create_child_ssl_socket_context(struct us_internal_ssl_socket_context_t* context, int context_ext_size)
-{
- /* Create a new non-SSL context */
- struct us_socket_context_options_t options = { 0 };
- struct us_internal_ssl_socket_context_t* child_context = (struct us_internal_ssl_socket_context_t*)us_create_socket_context(0, context->sc.loop, sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size, options);
+/* Lazily inits loop ssl data first time */
+void us_internal_init_loop_ssl_data(struct us_loop_t *loop) {
+ if (!loop->data.ssl_data) {
+ struct loop_ssl_data *loop_ssl_data =
+ us_malloc(sizeof(struct loop_ssl_data));
+ loop_ssl_data->ssl_read_input_length = 0;
+ loop_ssl_data->ssl_read_input_offset = 0;
+ loop_ssl_data->last_write_was_msg_more = 0;
+ loop_ssl_data->msg_more = 0;
- /* The only thing we share is SSL_CTX */
- child_context->ssl_context = context->ssl_context;
- child_context->is_parent = 0;
+ loop_ssl_data->ssl_read_output =
+ us_malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2);
- return child_context;
-}
+ OPENSSL_init_ssl(0, NULL);
-/* Common function for creating a context from options.
- * We must NOT free a SSL_CTX with only SSL_CTX_free! Also free any password */
-void free_ssl_context(SSL_CTX* ssl_context)
-{
- if (!ssl_context) {
- return;
- }
+ loop_ssl_data->shared_biom = BIO_meth_new(BIO_TYPE_MEM, "µS BIO");
+ BIO_meth_set_create(loop_ssl_data->shared_biom, BIO_s_custom_create);
+ BIO_meth_set_write(loop_ssl_data->shared_biom, BIO_s_custom_write);
+ BIO_meth_set_read(loop_ssl_data->shared_biom, BIO_s_custom_read);
+ BIO_meth_set_ctrl(loop_ssl_data->shared_biom, BIO_s_custom_ctrl);
- /* If we have set a password string, free it here */
- void* password = SSL_CTX_get_default_passwd_cb_userdata(ssl_context);
- /* OpenSSL returns NULL if we have no set password */
- us_free(password);
+ loop_ssl_data->shared_rbio = BIO_new(loop_ssl_data->shared_biom);
+ loop_ssl_data->shared_wbio = BIO_new(loop_ssl_data->shared_biom);
+ BIO_set_data(loop_ssl_data->shared_rbio, loop_ssl_data);
+ BIO_set_data(loop_ssl_data->shared_wbio, loop_ssl_data);
- SSL_CTX_free(ssl_context);
+ loop->data.ssl_data = loop_ssl_data;
+ }
}
-/* This function should take any options and return SSL_CTX - which has to be free'd with
- * our destructor function - free_ssl_context() */
-SSL_CTX* create_ssl_context_from_options(struct us_socket_context_options_t options)
-{
- /* Create the context */
- SSL_CTX* ssl_context = SSL_CTX_new(TLS_method());
+/* Called by loop free, clears any loop ssl data */
+void us_internal_free_loop_ssl_data(struct us_loop_t *loop) {
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
- /* Default options we rely on - changing these will break our logic */
- SSL_CTX_set_read_ahead(ssl_context, 1);
- SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ if (loop_ssl_data) {
+ us_free(loop_ssl_data->ssl_read_output);
- /* Anything below TLS 1.2 is disabled */
- SSL_CTX_set_min_proto_version(ssl_context, TLS1_2_VERSION);
+ BIO_free(loop_ssl_data->shared_rbio);
+ BIO_free(loop_ssl_data->shared_wbio);
- /* The following are helpers. You may easily implement whatever you want by using the native handle directly */
+ BIO_meth_free(loop_ssl_data->shared_biom);
- /* Important option for lowering memory usage, but lowers performance slightly */
- if (options.ssl_prefer_low_memory_usage) {
- SSL_CTX_set_mode(ssl_context, SSL_MODE_RELEASE_BUFFERS);
- }
+ us_free(loop_ssl_data);
+ }
+}
- if (options.passphrase) {
- /* When freeing the CTX we need to check SSL_CTX_get_default_passwd_cb_userdata and
- * free it if set */
- SSL_CTX_set_default_passwd_cb_userdata(ssl_context, (void*)strdup(options.passphrase));
- SSL_CTX_set_default_passwd_cb(ssl_context, passphrase_cb);
- }
+// we throttle reading data for ssl sockets that are in init state. here we
+// actually use the kernel buffering to our advantage
+int ssl_is_low_prio(struct us_internal_ssl_socket_t *s) {
+ /* We use SSL_in_before() instead of SSL_in_init(), because only the first
+ * step is CPU intensive, and we want to speed up the rest of connection
+ * establishing if the CPU intensive work is already done, so fully
+ * established connections increase lineary over time under high load */
+ return SSL_in_init(s->ssl);
+}
- /* This one most probably do not need the cert_file_name string to be kept alive */
- if (options.cert_file_name) {
- if (SSL_CTX_use_certificate_chain_file(ssl_context, options.cert_file_name) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+/* Per-context functions */
+void *us_internal_ssl_socket_context_get_native_handle(
+ struct us_internal_ssl_socket_context_t *context) {
+ return context->ssl_context;
+}
- /* Same as above - we can discard this string afterwards I suppose */
- if (options.key_file_name) {
- if (SSL_CTX_use_PrivateKey_file(ssl_context, options.key_file_name, SSL_FILETYPE_PEM) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+struct us_internal_ssl_socket_context_t *
+us_internal_create_child_ssl_socket_context(
+ struct us_internal_ssl_socket_context_t *context, int context_ext_size) {
+ /* Create a new non-SSL context */
+ struct us_socket_context_options_t options = {0};
+ struct us_internal_ssl_socket_context_t *child_context =
+ (struct us_internal_ssl_socket_context_t *)us_create_socket_context(
+ 0, context->sc.loop,
+ sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size,
+ options);
- if (options.ca_file_name) {
- STACK_OF(X509_NAME) * ca_list;
- ca_list = SSL_load_client_CA_file(options.ca_file_name);
- if (ca_list == NULL) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- SSL_CTX_set_client_CA_list(ssl_context, ca_list);
- if (SSL_CTX_load_verify_locations(ssl_context, options.ca_file_name, NULL) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
- }
+ /* The only thing we share is SSL_CTX */
+ child_context->ssl_context = context->ssl_context;
+ child_context->is_parent = 0;
- if (options.dh_params_file_name) {
- /* Set up ephemeral DH parameters. */
- DH* dh_2048 = NULL;
- FILE* paramfile;
- paramfile = fopen(options.dh_params_file_name, "r");
-
- if (paramfile) {
- dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
- fclose(paramfile);
- } else {
- free_ssl_context(ssl_context);
- return NULL;
- }
+ return child_context;
+}
- if (dh_2048 == NULL) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+/* Common function for creating a context from options.
+ * We must NOT free a SSL_CTX with only SSL_CTX_free! Also free any password */
+void free_ssl_context(SSL_CTX *ssl_context) {
+ if (!ssl_context) {
+ return;
+ }
+
+ /* If we have set a password string, free it here */
+ void *password = SSL_CTX_get_default_passwd_cb_userdata(ssl_context);
+ /* OpenSSL returns NULL if we have no set password */
+ us_free(password);
+
+ SSL_CTX_free(ssl_context);
+}
+
+/* This function should take any options and return SSL_CTX - which has to be
+ * free'd with our destructor function - free_ssl_context() */
+SSL_CTX *
+create_ssl_context_from_options(struct us_socket_context_options_t options) {
+ /* Create the context */
+ SSL_CTX *ssl_context = SSL_CTX_new(TLS_method());
+
+ /* Default options we rely on - changing these will break our logic */
+ SSL_CTX_set_read_ahead(ssl_context, 1);
+ SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ /* Anything below TLS 1.2 is disabled */
+ SSL_CTX_set_min_proto_version(ssl_context, TLS1_2_VERSION);
+
+ /* The following are helpers. You may easily implement whatever you want by
+ * using the native handle directly */
+
+ /* Important option for lowering memory usage, but lowers performance slightly
+ */
+ if (options.ssl_prefer_low_memory_usage) {
+ SSL_CTX_set_mode(ssl_context, SSL_MODE_RELEASE_BUFFERS);
+ }
+
+ if (options.passphrase) {
+ /* When freeing the CTX we need to check
+ * SSL_CTX_get_default_passwd_cb_userdata and free it if set */
+ SSL_CTX_set_default_passwd_cb_userdata(ssl_context,
+ (void *)strdup(options.passphrase));
+ SSL_CTX_set_default_passwd_cb(ssl_context, passphrase_cb);
+ }
+
+ /* This one most probably do not need the cert_file_name string to be kept
+ * alive */
+ if (options.cert_file_name) {
+ if (SSL_CTX_use_certificate_chain_file(ssl_context,
+ options.cert_file_name) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ }
+
+ /* Same as above - we can discard this string afterwards I suppose */
+ if (options.key_file_name) {
+ if (SSL_CTX_use_PrivateKey_file(ssl_context, options.key_file_name,
+ SSL_FILETYPE_PEM) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ }
+
+ if (options.ca_file_name) {
+ STACK_OF(X509_NAME) * ca_list;
+ ca_list = SSL_load_client_CA_file(options.ca_file_name);
+ if (ca_list == NULL) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ SSL_CTX_set_client_CA_list(ssl_context, ca_list);
+ if (SSL_CTX_load_verify_locations(ssl_context, options.ca_file_name,
+ NULL) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
+ }
+
+ if (options.dh_params_file_name) {
+ /* Set up ephemeral DH parameters. */
+ DH *dh_2048 = NULL;
+ FILE *paramfile;
+ paramfile = fopen(options.dh_params_file_name, "r");
+
+ if (paramfile) {
+ dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
+ fclose(paramfile);
+ } else {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+
+ if (dh_2048 == NULL) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+
+ const long set_tmp_dh = SSL_CTX_set_tmp_dh(ssl_context, dh_2048);
+ DH_free(dh_2048);
+
+ if (set_tmp_dh != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+
+ /* OWASP Cipher String 'A+'
+ * (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */
+ if (SSL_CTX_set_cipher_list(
+ ssl_context,
+ "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-"
+ "AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ }
+
+ if (options.ssl_ciphers) {
+ if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ }
+
+ /* This must be free'd with free_ssl_context, not SSL_CTX_free */
+ return ssl_context;
+}
+
+int us_ssl_ctx_use_privatekey_content(SSL_CTX *ctx, const char *content,
+ int type) {
+ int reason_code, ret = 0;
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+ in = BIO_new_mem_buf(content, strlen(content));
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_PEM) {
+ reason_code = ERR_R_PEM_LIB;
+ pkey = PEM_read_bio_PrivateKey(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
+ SSL_CTX_get_default_passwd_cb_userdata(ctx));
+ } else if (type == SSL_FILETYPE_ASN1) {
+ reason_code = ERR_R_ASN1_LIB;
+ pkey = d2i_PrivateKey_bio(in, NULL);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, reason_code);
+ goto end;
+ }
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
- const long set_tmp_dh = SSL_CTX_set_tmp_dh(ssl_context, dh_2048);
- DH_free(dh_2048);
+end:
+ BIO_free(in);
+ return ret;
+}
- if (set_tmp_dh != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+int add_ca_cert_to_ctx_store(SSL_CTX *ctx, const char *content,
+ X509_STORE *store) {
- /* OWASP Cipher String 'A+' (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */
- if (SSL_CTX_set_cipher_list(ssl_context, "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+ X509 *x = NULL;
+ BIO *in;
- if (options.ssl_ciphers) {
- if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+ ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
- /* This must be free'd with free_ssl_context, not SSL_CTX_free */
- return ssl_context;
-}
+ in = BIO_new_mem_buf(content, strlen(content));
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
+ goto end;
+ }
-int us_ssl_ctx_use_privatekey_content(SSL_CTX* ctx, const char* content, int type)
-{
- int reason_code, ret = 0;
- BIO* in;
- EVP_PKEY* pkey = NULL;
- in = BIO_new_mem_buf(content, strlen(content));
- if (in == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- goto end;
- }
+ int count = 0;
- if (type == SSL_FILETYPE_PEM) {
- reason_code = ERR_R_PEM_LIB;
- pkey = PEM_read_bio_PrivateKey(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
- SSL_CTX_get_default_passwd_cb_userdata(ctx));
- } else if (type == SSL_FILETYPE_ASN1) {
- reason_code = ERR_R_ASN1_LIB;
- pkey = d2i_PrivateKey_bio(in, NULL);
- } else {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
- goto end;
- }
+ while (x = PEM_read_bio_X509(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
+ SSL_CTX_get_default_passwd_cb_userdata(ctx))) {
- if (pkey == NULL) {
- OPENSSL_PUT_ERROR(SSL, reason_code);
- goto end;
+ X509_STORE_add_cert(store, x);
+
+ if (!SSL_CTX_add_client_CA(ctx, x)) {
+ X509_free(x);
+ BIO_free(in);
+ return 0;
}
- ret = SSL_CTX_use_PrivateKey(ctx, pkey);
- EVP_PKEY_free(pkey);
+ count++;
+ X509_free(x);
+ }
end:
- BIO_free(in);
- return ret;
-}
+ BIO_free(in);
-X509* us_ssl_ctx_get_X509_from(SSL_CTX* ctx, const char* content)
-{
- X509* x = NULL;
- BIO* in;
+ return count > 0;
+}
- ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
+int us_ssl_ctx_use_certificate_chain(SSL_CTX *ctx, const char *content) {
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
- in = BIO_new_mem_buf(content, strlen(content));
- if (in == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- goto end;
- }
+ ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
- x = PEM_read_bio_X509(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
- SSL_CTX_get_default_passwd_cb_userdata(ctx));
- if (x == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
- goto end;
- }
+ in = BIO_new_mem_buf(content, strlen(content));
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
+ goto end;
+ }
- return x;
+ x = PEM_read_bio_X509_AUX(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
+ SSL_CTX_get_default_passwd_cb_userdata(ctx));
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
+ goto end;
+ }
-end:
- X509_free(x);
- BIO_free(in);
- return NULL;
-}
+ ret = SSL_CTX_use_certificate(ctx, x);
-int us_ssl_ctx_use_certificate_chain(SSL_CTX* ctx, const char* content)
-{
- BIO* in;
- int ret = 0;
- X509* x = NULL;
+ if (ERR_peek_error() != 0) {
+ ret = 0; // Key/certificate mismatch doesn't imply ret==0 ...
+ }
- ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
+ if (ret) {
+ // If we could set up our certificate, now proceed to the CA
+ // certificates.
+ X509 *ca;
+ int r;
+ uint32_t err;
- in = BIO_new_mem_buf(content, strlen(content));
- if (in == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- goto end;
- }
+ SSL_CTX_clear_chain_certs(ctx);
- x = PEM_read_bio_X509_AUX(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
- SSL_CTX_get_default_passwd_cb_userdata(ctx));
- if (x == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
+ while ((ca = PEM_read_bio_X509(
+ in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
+ SSL_CTX_get_default_passwd_cb_userdata(ctx))) != NULL) {
+ r = SSL_CTX_add0_chain_cert(ctx, ca);
+ if (!r) {
+ X509_free(ca);
+ ret = 0;
goto end;
+ }
+ // Note that we must not free r if it was successfully added to the chain
+ // (while we must free the main certificate, since its reference count is
+ // increased by SSL_CTX_use_certificate).
}
- ret = SSL_CTX_use_certificate(ctx, x);
-
- if (ERR_peek_error() != 0) {
- ret = 0; // Key/certificate mismatch doesn't imply ret==0 ...
- }
-
- if (ret) {
- // If we could set up our certificate, now proceed to the CA
- // certificates.
- X509* ca;
- int r;
- uint32_t err;
-
- SSL_CTX_clear_chain_certs(ctx);
-
- while ((ca = PEM_read_bio_X509(in, NULL, SSL_CTX_get_default_passwd_cb(ctx),
- SSL_CTX_get_default_passwd_cb_userdata(ctx)))
- != NULL) {
- r = SSL_CTX_add0_chain_cert(ctx, ca);
- if (!r) {
- X509_free(ca);
- ret = 0;
- goto end;
- }
- // Note that we must not free r if it was successfully added to the chain
- // (while we must free the main certificate, since its reference count is
- // increased by SSL_CTX_use_certificate).
- }
-
- // When the while loop ends, it's usually just EOF.
- err = ERR_peek_last_error();
- if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
- ERR_clear_error();
- } else {
- ret = 0; // some real error
- }
+ // When the while loop ends, it's usually just EOF.
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+ ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
+ ERR_clear_error();
+ } else {
+ ret = 0; // some real error
}
+ }
end:
- X509_free(x);
- BIO_free(in);
- return ret;
-}
-
-const char* us_X509_error_code(long err)
-{ // NOLINT(runtime/int)
- const char* code = "UNSPECIFIED";
-#define CASE_X509_ERR(CODE) \
- case X509_V_ERR_##CODE: \
- code = #CODE; \
- break;
- switch (err) {
- // if you modify anything in here, *please* update the respective section in
- // doc/api/tls.md as well
- CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
- CASE_X509_ERR(UNABLE_TO_GET_CRL)
- CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
- CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
- CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
- CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
- CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
- CASE_X509_ERR(CERT_NOT_YET_VALID)
- CASE_X509_ERR(CERT_HAS_EXPIRED)
- CASE_X509_ERR(CRL_NOT_YET_VALID)
- CASE_X509_ERR(CRL_HAS_EXPIRED)
- CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
- CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
- CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
- CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
- CASE_X509_ERR(OUT_OF_MEM)
- CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
- CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
- CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
- CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
- CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
- CASE_X509_ERR(CERT_REVOKED)
- CASE_X509_ERR(INVALID_CA)
- CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
- CASE_X509_ERR(INVALID_PURPOSE)
- CASE_X509_ERR(CERT_UNTRUSTED)
- CASE_X509_ERR(CERT_REJECTED)
- CASE_X509_ERR(HOSTNAME_MISMATCH)
- }
+ X509_free(x);
+ BIO_free(in);
+ return ret;
+}
+
+const char *us_X509_error_code(long err) { // NOLINT(runtime/int)
+ const char *code = "UNSPECIFIED";
+#define CASE_X509_ERR(CODE) \
+ case X509_V_ERR_##CODE: \
+ code = #CODE; \
+ break;
+ switch (err) {
+ // if you modify anything in here, *please* update the respective section in
+ // doc/api/tls.md as well
+ CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
+ CASE_X509_ERR(UNABLE_TO_GET_CRL)
+ CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
+ CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
+ CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
+ CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
+ CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
+ CASE_X509_ERR(CERT_NOT_YET_VALID)
+ CASE_X509_ERR(CERT_HAS_EXPIRED)
+ CASE_X509_ERR(CRL_NOT_YET_VALID)
+ CASE_X509_ERR(CRL_HAS_EXPIRED)
+ CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
+ CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
+ CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
+ CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
+ CASE_X509_ERR(OUT_OF_MEM)
+ CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
+ CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
+ CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
+ CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
+ CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
+ CASE_X509_ERR(CERT_REVOKED)
+ CASE_X509_ERR(INVALID_CA)
+ CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
+ CASE_X509_ERR(INVALID_PURPOSE)
+ CASE_X509_ERR(CERT_UNTRUSTED)
+ CASE_X509_ERR(CERT_REJECTED)
+ CASE_X509_ERR(HOSTNAME_MISMATCH)
+ }
#undef CASE_X509_ERR
- return code;
+ return code;
}
long us_internal_verify_peer_certificate( // NOLINT(runtime/int)
- const SSL* ssl,
- long def)
-{ // NOLINT(runtime/int)
- long err = def; // NOLINT(runtime/int)
- X509* peer_cert = SSL_get_peer_certificate(ssl);
- if (peer_cert) {
- X509_free(peer_cert);
- err = SSL_get_verify_result(ssl);
- } else {
- const SSL_CIPHER* curr_cipher = SSL_get_current_cipher(ssl);
-
- const SSL_SESSION* sess = SSL_get_session(ssl);
- // Allow no-cert for PSK authentication in TLS1.2 and lower.
- // In TLS1.3 check that session was reused because TLS1.3 PSK
- // looks like session resumption.
- if ((curr_cipher && SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk) || (sess && SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION && SSL_session_reused(ssl))) {
- return X509_V_OK;
- }
- }
- return err;
-}
-
-struct us_bun_verify_error_t us_internal_verify_error(struct us_internal_ssl_socket_t* s)
-{
-
- if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
- return (struct us_bun_verify_error_t) { .error = 0, .code = NULL, .reason = NULL };
+ const SSL *ssl,
+ long def) { // NOLINT(runtime/int)
+ long err = def; // NOLINT(runtime/int)
+ X509 *peer_cert = SSL_get_peer_certificate(ssl);
+ if (peer_cert) {
+ X509_free(peer_cert);
+ err = SSL_get_verify_result(ssl);
+ } else {
+ const SSL_CIPHER *curr_cipher = SSL_get_current_cipher(ssl);
+
+ const SSL_SESSION *sess = SSL_get_session(ssl);
+ // Allow no-cert for PSK authentication in TLS1.2 and lower.
+ // In TLS1.3 check that session was reused because TLS1.3 PSK
+ // looks like session resumption.
+ if ((curr_cipher && SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk) ||
+ (sess && SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION &&
+ SSL_session_reused(ssl))) {
+ return X509_V_OK;
+ }
+ }
+ return err;
+}
+
+struct us_bun_verify_error_t
+us_internal_verify_error(struct us_internal_ssl_socket_t *s) {
+
+ if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
+ return (struct us_bun_verify_error_t){
+ .error = 0, .code = NULL, .reason = NULL};
+ }
+
+ SSL *ssl = s->ssl;
+ long x509_verify_error = // NOLINT(runtime/int)
+ us_internal_verify_peer_certificate(ssl,
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
+
+ if (x509_verify_error == X509_V_OK)
+ return (struct us_bun_verify_error_t){
+ .error = x509_verify_error, .code = NULL, .reason = NULL};
+
+ const char *reason = X509_verify_cert_error_string(x509_verify_error);
+ const char *code = us_X509_error_code(x509_verify_error);
+
+ return (struct us_bun_verify_error_t){
+ .error = x509_verify_error, .code = code, .reason = reason};
+}
+
+int us_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
+ // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
+ //
+ // If VerifyCallback returns 1, the verification process is continued. If
+ // VerifyCallback always returns 1, the TLS/SSL handshake will not be
+ // terminated with respect to verification failures and the connection will
+ // be established. The calling process can however retrieve the error code
+ // of the last verification error using SSL_get_verify_result(3) or by
+ // maintaining its own error storage managed by VerifyCallback.
+ //
+ // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
+ // this callback, we ignore all preverify_ok errors and let the handshake
+ // continue. It is imperative that the user use Connection::VerifyError after
+ // the 'secure' callback has been made.
+ return 1;
+}
+
+SSL_CTX *create_ssl_context_from_bun_options(
+ struct us_bun_socket_context_options_t options) {
+ /* Create the context */
+ SSL_CTX *ssl_context = SSL_CTX_new(TLS_method());
+
+ /* Default options we rely on - changing these will break our logic */
+ SSL_CTX_set_read_ahead(ssl_context, 1);
+ SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ /* Anything below TLS 1.2 is disabled */
+ SSL_CTX_set_min_proto_version(ssl_context, TLS1_2_VERSION);
+
+ /* The following are helpers. You may easily implement whatever you want by
+ * using the native handle directly */
+
+ /* Important option for lowering memory usage, but lowers performance slightly
+ */
+ if (options.ssl_prefer_low_memory_usage) {
+ SSL_CTX_set_mode(ssl_context, SSL_MODE_RELEASE_BUFFERS);
+ }
+
+ if (options.passphrase) {
+ /* When freeing the CTX we need to check
+ * SSL_CTX_get_default_passwd_cb_userdata and free it if set */
+ SSL_CTX_set_default_passwd_cb_userdata(ssl_context,
+ (void *)strdup(options.passphrase));
+ SSL_CTX_set_default_passwd_cb(ssl_context, passphrase_cb);
+ }
+
+ /* This one most probably do not need the cert_file_name string to be kept
+ * alive */
+ if (options.cert_file_name) {
+ if (SSL_CTX_use_certificate_chain_file(ssl_context,
+ options.cert_file_name) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ } else if (options.cert && options.cert_count > 0) {
+ for (unsigned int i = 0; i < options.cert_count; i++) {
+ if (us_ssl_ctx_use_certificate_chain(ssl_context, options.cert[i]) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ }
+ }
+
+ /* Same as above - we can discard this string afterwards I suppose */
+ if (options.key_file_name) {
+ if (SSL_CTX_use_PrivateKey_file(ssl_context, options.key_file_name,
+ SSL_FILETYPE_PEM) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+ } else if (options.key && options.key_count > 0) {
+ for (unsigned int i = 0; i < options.key_count; i++) {
+ if (us_ssl_ctx_use_privatekey_content(ssl_context, options.key[i],
+ SSL_FILETYPE_PEM) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
}
+ }
- SSL* ssl = s->ssl;
- long x509_verify_error = // NOLINT(runtime/int)
- us_internal_verify_peer_certificate(
- ssl,
- X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
-
- if (x509_verify_error == X509_V_OK)
- return (struct us_bun_verify_error_t) { .error = x509_verify_error, .code = NULL, .reason = NULL };
-
- const char* reason = X509_verify_cert_error_string(x509_verify_error);
- const char* code = us_X509_error_code(x509_verify_error);
-
- return (struct us_bun_verify_error_t) { .error = x509_verify_error, .code = code, .reason = reason };
-}
-
-int us_verify_callback(int preverify_ok, X509_STORE_CTX* ctx)
-{
- // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
- //
- // If VerifyCallback returns 1, the verification process is continued. If
- // VerifyCallback always returns 1, the TLS/SSL handshake will not be
- // terminated with respect to verification failures and the connection will
- // be established. The calling process can however retrieve the error code
- // of the last verification error using SSL_get_verify_result(3) or by
- // maintaining its own error storage managed by VerifyCallback.
- //
- // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
- // this callback, we ignore all preverify_ok errors and let the handshake
- // continue. It is imperative that the user use Connection::VerifyError after
- // the 'secure' callback has been made.
- return 1;
-}
-
-SSL_CTX* create_ssl_context_from_bun_options(struct us_bun_socket_context_options_t options)
-{
- /* Create the context */
- SSL_CTX* ssl_context = SSL_CTX_new(TLS_method());
-
- /* Default options we rely on - changing these will break our logic */
- SSL_CTX_set_read_ahead(ssl_context, 1);
- SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
-
- /* Anything below TLS 1.2 is disabled */
- SSL_CTX_set_min_proto_version(ssl_context, TLS1_2_VERSION);
+ if (options.ca_file_name) {
+ SSL_CTX_set_cert_store(ssl_context, us_get_default_ca_store());
- /* The following are helpers. You may easily implement whatever you want by using the native handle directly */
-
- /* Important option for lowering memory usage, but lowers performance slightly */
- if (options.ssl_prefer_low_memory_usage) {
- SSL_CTX_set_mode(ssl_context, SSL_MODE_RELEASE_BUFFERS);
- }
-
- if (options.passphrase) {
- /* When freeing the CTX we need to check SSL_CTX_get_default_passwd_cb_userdata and
- * free it if set */
- SSL_CTX_set_default_passwd_cb_userdata(ssl_context, (void*)strdup(options.passphrase));
- SSL_CTX_set_default_passwd_cb(ssl_context, passphrase_cb);
+ STACK_OF(X509_NAME) * ca_list;
+ ca_list = SSL_load_client_CA_file(options.ca_file_name);
+ if (ca_list == NULL) {
+ free_ssl_context(ssl_context);
+ return NULL;
}
- /* This one most probably do not need the cert_file_name string to be kept alive */
- if (options.cert_file_name) {
- if (SSL_CTX_use_certificate_chain_file(ssl_context, options.cert_file_name) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- } else if (options.cert && options.cert_count > 0) {
- for (unsigned int i = 0; i < options.cert_count; i++) {
- if (us_ssl_ctx_use_certificate_chain(ssl_context, options.cert[i]) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+ SSL_CTX_set_client_CA_list(ssl_context, ca_list);
+ if (SSL_CTX_load_verify_locations(ssl_context, options.ca_file_name,
+ NULL) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
}
- /* Same as above - we can discard this string afterwards I suppose */
- if (options.key_file_name) {
- if (SSL_CTX_use_PrivateKey_file(ssl_context, options.key_file_name, SSL_FILETYPE_PEM) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- } else if (options.key && options.key_count > 0) {
- for (unsigned int i = 0; i < options.key_count; i++) {
- if (us_ssl_ctx_use_privatekey_content(ssl_context, options.key[i], SSL_FILETYPE_PEM) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- }
+ if (options.reject_unauthorized) {
+ SSL_CTX_set_verify(ssl_context,
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ us_verify_callback);
+ } else {
+ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
}
- if (options.ca_file_name) {
- SSL_CTX_set_cert_store(ssl_context, us_get_default_ca_store());
+ } else if (options.ca && options.ca_count > 0) {
+ X509_STORE *cert_store = NULL;
- STACK_OF(X509_NAME) * ca_list;
- ca_list = SSL_load_client_CA_file(options.ca_file_name);
- if (ca_list == NULL) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+ for (unsigned int i = 0; i < options.ca_count; i++) {
+ if (cert_store == NULL) {
+ cert_store = us_get_default_ca_store();
+ SSL_CTX_set_cert_store(ssl_context, cert_store);
+ }
- SSL_CTX_set_client_CA_list(ssl_context, ca_list);
- if (SSL_CTX_load_verify_locations(ssl_context, options.ca_file_name, NULL) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
-
- if (options.reject_unauthorized) {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, us_verify_callback);
- } else {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
- }
-
- } else if (options.ca && options.ca_count > 0) {
- X509_STORE* cert_store = NULL;
-
- for (unsigned int i = 0; i < options.ca_count; i++) {
- X509* ca_cert = us_ssl_ctx_get_X509_from(ssl_context, options.ca[i]);
- if (ca_cert == NULL) {
- free_ssl_context(ssl_context);
- return NULL;
- }
-
- if (cert_store == NULL) {
- cert_store = us_get_default_ca_store();
- SSL_CTX_set_cert_store(ssl_context, cert_store);
- }
-
- X509_STORE_add_cert(cert_store, ca_cert);
- if (!SSL_CTX_add_client_CA(ssl_context, ca_cert)) {
- free_ssl_context(ssl_context);
- return NULL;
- }
- if (options.reject_unauthorized) {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, us_verify_callback);
- } else {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
- }
- }
+ if (!add_ca_cert_to_ctx_store(ssl_context, options.ca[i], cert_store)) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
+
+ if (options.reject_unauthorized) {
+ SSL_CTX_set_verify(ssl_context,
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ us_verify_callback);
+ } else {
+ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
+ }
+ }
+ } else {
+ if (options.request_cert) {
+ SSL_CTX_set_cert_store(ssl_context, us_get_default_ca_store());
+
+ if (options.reject_unauthorized) {
+ SSL_CTX_set_verify(ssl_context,
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ us_verify_callback);
+ } else {
+ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
+ }
+ }
+ }
+ if (options.dh_params_file_name) {
+ /* Set up ephemeral DH parameters. */
+ DH *dh_2048 = NULL;
+ FILE *paramfile;
+ paramfile = fopen(options.dh_params_file_name, "r");
+
+ if (paramfile) {
+ dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
+ fclose(paramfile);
} else {
- if (options.request_cert) {
- SSL_CTX_set_cert_store(ssl_context, us_get_default_ca_store());
-
- if (options.reject_unauthorized) {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, us_verify_callback);
- } else {
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, us_verify_callback);
- }
- }
+ free_ssl_context(ssl_context);
+ return NULL;
}
- if (options.dh_params_file_name) {
- /* Set up ephemeral DH parameters. */
- DH* dh_2048 = NULL;
- FILE* paramfile;
- paramfile = fopen(options.dh_params_file_name, "r");
-
- if (paramfile) {
- dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
- fclose(paramfile);
- } else {
- free_ssl_context(ssl_context);
- return NULL;
- }
- if (dh_2048 == NULL) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+ if (dh_2048 == NULL) {
+ free_ssl_context(ssl_context);
+ return NULL;
+ }
- const long set_tmp_dh = SSL_CTX_set_tmp_dh(ssl_context, dh_2048);
- DH_free(dh_2048);
+ const long set_tmp_dh = SSL_CTX_set_tmp_dh(ssl_context, dh_2048);
+ DH_free(dh_2048);
- if (set_tmp_dh != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
-
- /* OWASP Cipher String 'A+' (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */
- if (SSL_CTX_set_cipher_list(ssl_context, "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+ if (set_tmp_dh != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
}
- if (options.ssl_ciphers) {
- if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) {
- free_ssl_context(ssl_context);
- return NULL;
- }
+ /* OWASP Cipher String 'A+'
+ * (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */
+ if (SSL_CTX_set_cipher_list(
+ ssl_context,
+ "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-"
+ "AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
}
+ }
- if (options.secure_options) {
- SSL_CTX_set_options(ssl_context, options.secure_options);
+ if (options.ssl_ciphers) {
+ if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) {
+ free_ssl_context(ssl_context);
+ return NULL;
}
+ }
+
+ if (options.secure_options) {
+ SSL_CTX_set_options(ssl_context, options.secure_options);
+ }
- /* This must be free'd with free_ssl_context, not SSL_CTX_free */
- return ssl_context;
+ /* This must be free'd with free_ssl_context, not SSL_CTX_free */
+ return ssl_context;
}
/* Returns a servername's userdata if any */
-void* us_internal_ssl_socket_context_find_server_name_userdata(struct us_internal_ssl_socket_context_t* context, const char* hostname_pattern)
-{
+void *us_internal_ssl_socket_context_find_server_name_userdata(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern) {
- /* We can use sni_find because looking up a "wildcard pattern" will match the exact literal "wildcard pattern" first,
- * before it matches by the very wildcard itself, so it works fine (exact match is the only thing we care for here) */
- SSL_CTX* ssl_context = sni_find(context->sni, hostname_pattern);
+ /* We can use sni_find because looking up a "wildcard pattern" will match the
+ * exact literal "wildcard pattern" first, before it matches by the very
+ * wildcard itself, so it works fine (exact match is the only thing we care
+ * for here) */
+ SSL_CTX *ssl_context = sni_find(context->sni, hostname_pattern);
- if (ssl_context) {
- return SSL_CTX_get_ex_data(ssl_context, 0);
- }
+ if (ssl_context) {
+ return SSL_CTX_get_ex_data(ssl_context, 0);
+ }
- return 0;
+ return 0;
}
-/* Returns either nullptr or the previously set user data attached to this SSL's selected SNI context */
-void* us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t* s)
-{
- return SSL_CTX_get_ex_data(SSL_get_SSL_CTX(s->ssl), 0);
+/* Returns either nullptr or the previously set user data attached to this SSL's
+ * selected SNI context */
+void *
+us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s) {
+ return SSL_CTX_get_ex_data(SSL_get_SSL_CTX(s->ssl), 0);
}
/* Todo: return error on failure? */
-void us_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t* context, const char* hostname_pattern, struct us_socket_context_options_t options, void* user)
-{
+void us_internal_ssl_socket_context_add_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern, struct us_socket_context_options_t options,
+ void *user) {
- /* Try and construct an SSL_CTX from options */
- SSL_CTX* ssl_context = create_ssl_context_from_options(options);
+ /* Try and construct an SSL_CTX from options */
+ SSL_CTX *ssl_context = create_ssl_context_from_options(options);
- /* Attach the user data to this context */
- if (1 != SSL_CTX_set_ex_data(ssl_context, 0, user)) {
- printf("CANNOT SET EX DATA!\n");
- }
+ /* Attach the user data to this context */
+ if (1 != SSL_CTX_set_ex_data(ssl_context, 0, user)) {
+ printf("CANNOT SET EX DATA!\n");
+ }
- /* We do not want to hold any nullptr's in our SNI tree */
- if (ssl_context) {
- if (sni_add(context->sni, hostname_pattern, ssl_context)) {
- /* If we already had that name, ignore */
- free_ssl_context(ssl_context);
- }
+ /* We do not want to hold any nullptr's in our SNI tree */
+ if (ssl_context) {
+ if (sni_add(context->sni, hostname_pattern, ssl_context)) {
+ /* If we already had that name, ignore */
+ free_ssl_context(ssl_context);
}
+ }
}
-void us_bun_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t* context, const char* hostname_pattern, struct us_bun_socket_context_options_t options, void* user)
-{
+void us_bun_internal_ssl_socket_context_add_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern,
+ struct us_bun_socket_context_options_t options, void *user) {
- /* Try and construct an SSL_CTX from options */
- SSL_CTX* ssl_context = create_ssl_context_from_bun_options(options);
+ /* Try and construct an SSL_CTX from options */
+ SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options);
- /* Attach the user data to this context */
- if (1 != SSL_CTX_set_ex_data(ssl_context, 0, user)) {
- printf("CANNOT SET EX DATA!\n");
- }
+ /* Attach the user data to this context */
+ if (1 != SSL_CTX_set_ex_data(ssl_context, 0, user)) {
+ printf("CANNOT SET EX DATA!\n");
+ }
- /* We do not want to hold any nullptr's in our SNI tree */
- if (ssl_context) {
- if (sni_add(context->sni, hostname_pattern, ssl_context)) {
- /* If we already had that name, ignore */
- free_ssl_context(ssl_context);
- }
+ /* We do not want to hold any nullptr's in our SNI tree */
+ if (ssl_context) {
+ if (sni_add(context->sni, hostname_pattern, ssl_context)) {
+ /* If we already had that name, ignore */
+ free_ssl_context(ssl_context);
}
+ }
}
-void us_internal_ssl_socket_context_on_server_name(struct us_internal_ssl_socket_context_t* context, void (*cb)(struct us_internal_ssl_socket_context_t*, const char* hostname))
-{
- context->on_server_name = cb;
+void us_internal_ssl_socket_context_on_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ void (*cb)(struct us_internal_ssl_socket_context_t *,
+ const char *hostname)) {
+ context->on_server_name = cb;
}
-void us_internal_ssl_socket_context_remove_server_name(struct us_internal_ssl_socket_context_t* context, const char* hostname_pattern)
-{
+void us_internal_ssl_socket_context_remove_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern) {
- /* The same thing must happen for sni_free, that's why we have a callback */
- SSL_CTX* sni_node_ssl_context = (SSL_CTX*)sni_remove(context->sni, hostname_pattern);
- free_ssl_context(sni_node_ssl_context);
+ /* The same thing must happen for sni_free, that's why we have a callback */
+ SSL_CTX *sni_node_ssl_context =
+ (SSL_CTX *)sni_remove(context->sni, hostname_pattern);
+ free_ssl_context(sni_node_ssl_context);
}
/* Returns NULL or SSL_CTX. May call missing server name callback */
-SSL_CTX* resolve_context(struct us_internal_ssl_socket_context_t* context, const char* hostname)
-{
-
- /* Try once first */
- void* user = sni_find(context->sni, hostname);
- if (!user) {
- /* Emit missing hostname then try again */
- if (!context->on_server_name) {
- /* We have no callback registered, so fail */
- return NULL;
- }
-
- context->on_server_name(context, hostname);
-
- /* Last try */
- user = sni_find(context->sni, hostname);
- }
-
- return user;
-}
-
-// arg is context
-int sni_cb(SSL* ssl, int* al, void* arg)
-{
-
- if (ssl) {
- const char* hostname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
- if (hostname && hostname[0]) {
- /* Try and resolve (match) required hostname with what we have registered */
- SSL_CTX* resolved_ssl_context = resolve_context((struct us_internal_ssl_socket_context_t*)arg, hostname);
- if (resolved_ssl_context) {
- // printf("Did find matching SNI context for hostname: <%s>!\n", hostname);
- SSL_set_SSL_CTX(ssl, resolved_ssl_context);
- } else {
- /* Call a blocking callback notifying of missing context */
- }
- }
-
- return SSL_TLSEXT_ERR_OK;
- }
-
- /* Can we even come here ever? */
- return SSL_TLSEXT_ERR_NOACK;
-}
+SSL_CTX *resolve_context(struct us_internal_ssl_socket_context_t *context,
+ const char *hostname) {
-struct us_internal_ssl_socket_context_t* us_internal_create_ssl_socket_context(struct us_loop_t* loop, int context_ext_size, struct us_socket_context_options_t options)
-{
- /* If we haven't initialized the loop data yet, do so .
- * This is needed because loop data holds shared OpenSSL data and
- * the function is also responsible for initializing OpenSSL */
- us_internal_init_loop_ssl_data(loop);
-
- /* First of all we try and create the SSL context from options */
- SSL_CTX* ssl_context = create_ssl_context_from_options(options);
- if (!ssl_context) {
- /* We simply fail early if we cannot even create the OpenSSL context */
- return NULL;
+ /* Try once first */
+ void *user = sni_find(context->sni, hostname);
+ if (!user) {
+ /* Emit missing hostname then try again */
+ if (!context->on_server_name) {
+ /* We have no callback registered, so fail */
+ return NULL;
}
- /* Otherwise ee continue by creating a non-SSL context, but with larger ext to hold our SSL stuff */
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_create_socket_context(0, loop, sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size, options);
-
- /* I guess this is the only optional callback */
- context->on_server_name = NULL;
-
- /* Then we extend its SSL parts */
- context->ssl_context = ssl_context; // create_ssl_context_from_options(options);
- context->is_parent = 1;
-
- context->on_handshake = NULL;
- context->handshake_data = NULL;
- /* We, as parent context, may ignore data */
- context->sc.is_low_prio = (int (*)(struct us_socket_t*))ssl_is_low_prio;
-
- /* Parent contexts may use SNI */
- SSL_CTX_set_tlsext_servername_callback(context->ssl_context, sni_cb);
- SSL_CTX_set_tlsext_servername_arg(context->ssl_context, context);
+ context->on_server_name(context, hostname);
- /* Also create the SNI tree */
- context->sni = sni_new();
+ /* Last try */
+ user = sni_find(context->sni, hostname);
+ }
- return context;
+ return user;
}
-struct us_internal_ssl_socket_context_t* us_internal_bun_create_ssl_socket_context(struct us_loop_t* loop, int context_ext_size, struct us_bun_socket_context_options_t options)
-{
- /* If we haven't initialized the loop data yet, do so .
- * This is needed because loop data holds shared OpenSSL data and
- * the function is also responsible for initializing OpenSSL */
- us_internal_init_loop_ssl_data(loop);
- /* First of all we try and create the SSL context from options */
- SSL_CTX* ssl_context = create_ssl_context_from_bun_options(options);
- if (!ssl_context) {
- /* We simply fail early if we cannot even create the OpenSSL context */
- return NULL;
- }
+// arg is context
+int sni_cb(SSL *ssl, int *al, void *arg) {
+
+ if (ssl) {
+ const char *hostname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+ if (hostname && hostname[0]) {
+ /* Try and resolve (match) required hostname with what we have registered
+ */
+ SSL_CTX *resolved_ssl_context = resolve_context(
+ (struct us_internal_ssl_socket_context_t *)arg, hostname);
+ if (resolved_ssl_context) {
+ // printf("Did find matching SNI context for hostname: <%s>!\n",
+ // hostname);
+ SSL_set_SSL_CTX(ssl, resolved_ssl_context);
+ } else {
+ /* Call a blocking callback notifying of missing context */
+ }
+ }
+
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ /* Can we even come here ever? */
+ return SSL_TLSEXT_ERR_NOACK;
+}
+
+struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
+ struct us_loop_t *loop, int context_ext_size,
+ struct us_socket_context_options_t options) {
+ /* If we haven't initialized the loop data yet, do so .
+ * This is needed because loop data holds shared OpenSSL data and
+ * the function is also responsible for initializing OpenSSL */
+ us_internal_init_loop_ssl_data(loop);
+
+ /* First of all we try and create the SSL context from options */
+ SSL_CTX *ssl_context = create_ssl_context_from_options(options);
+ if (!ssl_context) {
+ /* We simply fail early if we cannot even create the OpenSSL context */
+ return NULL;
+ }
+
+ /* Otherwise ee continue by creating a non-SSL context, but with larger ext to
+ * hold our SSL stuff */
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_create_socket_context(
+ 0, loop,
+ sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size,
+ options);
+
+ /* I guess this is the only optional callback */
+ context->on_server_name = NULL;
+
+ /* Then we extend its SSL parts */
+ context->ssl_context =
+ ssl_context; // create_ssl_context_from_options(options);
+ context->is_parent = 1;
+
+ context->on_handshake = NULL;
+ context->handshake_data = NULL;
+ /* We, as parent context, may ignore data */
+ context->sc.is_low_prio = (int (*)(struct us_socket_t *))ssl_is_low_prio;
+
+ /* Parent contexts may use SNI */
+ SSL_CTX_set_tlsext_servername_callback(context->ssl_context, sni_cb);
+ SSL_CTX_set_tlsext_servername_arg(context->ssl_context, context);
+
+ /* Also create the SNI tree */
+ context->sni = sni_new();
+
+ return context;
+}
+struct us_internal_ssl_socket_context_t *
+us_internal_bun_create_ssl_socket_context(
+ struct us_loop_t *loop, int context_ext_size,
+ struct us_bun_socket_context_options_t options) {
+ /* If we haven't initialized the loop data yet, do so .
+ * This is needed because loop data holds shared OpenSSL data and
+ * the function is also responsible for initializing OpenSSL */
+ us_internal_init_loop_ssl_data(loop);
+
+ /* First of all we try and create the SSL context from options */
+ SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options);
+ if (!ssl_context) {
+ /* We simply fail early if we cannot even create the OpenSSL context */
+ return NULL;
+ }
- /* Otherwise ee continue by creating a non-SSL context, but with larger ext to hold our SSL stuff */
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_create_bun_socket_context(0, loop, sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size, options);
+ /* Otherwise ee continue by creating a non-SSL context, but with larger ext to
+ * hold our SSL stuff */
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_create_bun_socket_context(
+ 0, loop,
+ sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size,
+ options);
- /* I guess this is the only optional callback */
- context->on_server_name = NULL;
+ /* I guess this is the only optional callback */
+ context->on_server_name = NULL;
- /* Then we extend its SSL parts */
- context->ssl_context = ssl_context; // create_ssl_context_from_options(options);
- context->is_parent = 1;
+ /* Then we extend its SSL parts */
+ context->ssl_context =
+ ssl_context; // create_ssl_context_from_options(options);
+ context->is_parent = 1;
- context->on_handshake = NULL;
- context->handshake_data = NULL;
- /* We, as parent context, may ignore data */
- context->sc.is_low_prio = (int (*)(struct us_socket_t*))ssl_is_low_prio;
+ context->on_handshake = NULL;
+ context->handshake_data = NULL;
+ /* We, as parent context, may ignore data */
+ context->sc.is_low_prio = (int (*)(struct us_socket_t *))ssl_is_low_prio;
- /* Parent contexts may use SNI */
- SSL_CTX_set_tlsext_servername_callback(context->ssl_context, sni_cb);
- SSL_CTX_set_tlsext_servername_arg(context->ssl_context, context);
+ /* Parent contexts may use SNI */
+ SSL_CTX_set_tlsext_servername_callback(context->ssl_context, sni_cb);
+ SSL_CTX_set_tlsext_servername_arg(context->ssl_context, context);
- /* Also create the SNI tree */
- context->sni = sni_new();
+ /* Also create the SNI tree */
+ context->sni = sni_new();
- return context;
+ return context;
}
/* Our destructor for hostnames, used below */
-void sni_hostname_destructor(void* user)
-{
- /* Some nodes hold null, so this one must ignore this case */
- free_ssl_context((SSL_CTX*)user);
-}
-
-void us_internal_ssl_socket_context_free(struct us_internal_ssl_socket_context_t* context)
-{
- /* If we are parent then we need to free our OpenSSL context */
- if (context->is_parent) {
- free_ssl_context(context->ssl_context);
-
- /* Here we need to register a temporary callback for all still-existing hostnames
- * and their contexts. Only parents have an SNI tree */
- sni_free(context->sni, sni_hostname_destructor);
- }
-
- us_socket_context_free(0, &context->sc);
-}
-
-struct us_listen_socket_t* us_internal_ssl_socket_context_listen(struct us_internal_ssl_socket_context_t* context, const char* host, int port, int options, int socket_ext_size)
-{
- return us_socket_context_listen(0, &context->sc, host, port, options, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + socket_ext_size);
-}
-
-struct us_listen_socket_t* us_internal_ssl_socket_context_listen_unix(struct us_internal_ssl_socket_context_t* context, const char* path, int options, int socket_ext_size)
-{
- return us_socket_context_listen_unix(0, &context->sc, path, options, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + socket_ext_size);
-}
-
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_context_connect(struct us_internal_ssl_socket_context_t* context, const char* host, int port, const char* source_host, int options, int socket_ext_size)
-{
- return (struct us_internal_ssl_socket_t*)us_socket_context_connect(0, &context->sc, host, port, source_host, options, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + socket_ext_size);
-}
-
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_context_connect_unix(struct us_internal_ssl_socket_context_t* context, const char* server_path, int options, int socket_ext_size)
-{
- return (struct us_internal_ssl_socket_t*)us_socket_context_connect_unix(0, &context->sc, server_path, options, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + socket_ext_size);
-}
-
-void us_internal_ssl_socket_context_on_open(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_open)(struct us_internal_ssl_socket_t* s, int is_client, char* ip, int ip_length))
-{
- us_socket_context_on_open(0, &context->sc, (struct us_socket_t * (*)(struct us_socket_t*, int, char*, int)) ssl_on_open);
- context->on_open = on_open;
-}
-
-void us_internal_ssl_socket_context_on_close(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_close)(struct us_internal_ssl_socket_t* s, int code, void* reason))
-{
- us_socket_context_on_close(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*, int, void*)) ssl_on_close);
- context->on_close = on_close;
-}
-
-void us_internal_ssl_socket_context_on_data(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_data)(struct us_internal_ssl_socket_t* s, char* data, int length))
-{
- us_socket_context_on_data(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*, char*, int)) ssl_on_data);
- context->on_data = on_data;
-}
-
-void us_internal_ssl_socket_context_on_writable(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_writable)(struct us_internal_ssl_socket_t* s))
-{
- us_socket_context_on_writable(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_on_writable);
- context->on_writable = on_writable;
-}
-
-void us_internal_ssl_socket_context_on_timeout(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_timeout)(struct us_internal_ssl_socket_t* s))
-{
- us_socket_context_on_timeout(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*)) on_timeout);
-}
-
-void us_internal_ssl_socket_context_on_long_timeout(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_long_timeout)(struct us_internal_ssl_socket_t* s))
-{
- us_socket_context_on_long_timeout(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*)) on_long_timeout);
-}
-
-/* We do not really listen to passed FIN-handler, we entirely override it with our handler since SSL doesn't really have support for half-closed sockets */
-void us_internal_ssl_socket_context_on_end(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_end)(struct us_internal_ssl_socket_t*))
-{
- us_socket_context_on_end(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_on_end);
-}
-
-void us_internal_ssl_socket_context_on_connect_error(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* (*on_connect_error)(struct us_internal_ssl_socket_t*, int code))
-{
- us_socket_context_on_connect_error(0, (struct us_socket_context_t*)context, (struct us_socket_t * (*)(struct us_socket_t*, int)) on_connect_error);
-}
-
-void* us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t* context)
-{
- return context + 1;
+void sni_hostname_destructor(void *user) {
+ /* Some nodes hold null, so this one must ignore this case */
+ free_ssl_context((SSL_CTX *)user);
+}
+
+void us_internal_ssl_socket_context_free(
+ struct us_internal_ssl_socket_context_t *context) {
+ /* If we are parent then we need to free our OpenSSL context */
+ if (context->is_parent) {
+ free_ssl_context(context->ssl_context);
+
+ /* Here we need to register a temporary callback for all still-existing
+ * hostnames and their contexts. Only parents have an SNI tree */
+ sni_free(context->sni, sni_hostname_destructor);
+ }
+
+ us_socket_context_free(0, &context->sc);
+}
+
+struct us_listen_socket_t *us_internal_ssl_socket_context_listen(
+ struct us_internal_ssl_socket_context_t *context, const char *host,
+ int port, int options, int socket_ext_size) {
+ return us_socket_context_listen(0, &context->sc, host, port, options,
+ sizeof(struct us_internal_ssl_socket_t) -
+ sizeof(struct us_socket_t) +
+ socket_ext_size);
+}
+
+struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
+ struct us_internal_ssl_socket_context_t *context, const char *path,
+ int options, int socket_ext_size) {
+ return us_socket_context_listen_unix(0, &context->sc, path, options,
+ sizeof(struct us_internal_ssl_socket_t) -
+ sizeof(struct us_socket_t) +
+ socket_ext_size);
+}
+
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect(
+ struct us_internal_ssl_socket_context_t *context, const char *host,
+ int port, const char *source_host, int options, int socket_ext_size) {
+ return (struct us_internal_ssl_socket_t *)us_socket_context_connect(
+ 0, &context->sc, host, port, source_host, options,
+ sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
+ socket_ext_size);
+}
+
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
+ struct us_internal_ssl_socket_context_t *context, const char *server_path,
+ int options, int socket_ext_size) {
+ return (struct us_internal_ssl_socket_t *)us_socket_context_connect_unix(
+ 0, &context->sc, server_path, options,
+ sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
+ socket_ext_size);
+}
+
+void us_internal_ssl_socket_context_on_open(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_open)(
+ struct us_internal_ssl_socket_t *s, int is_client, char *ip,
+ int ip_length)) {
+ us_socket_context_on_open(
+ 0, &context->sc,
+ (struct us_socket_t * (*)(struct us_socket_t *, int, char *, int))
+ ssl_on_open);
+ context->on_open = on_open;
+}
+
+void us_internal_ssl_socket_context_on_close(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_close)(
+ struct us_internal_ssl_socket_t *s, int code, void *reason)) {
+ us_socket_context_on_close(
+ 0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *, int, void *))
+ ssl_on_close);
+ context->on_close = on_close;
+}
+
+void us_internal_ssl_socket_context_on_data(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_data)(
+ struct us_internal_ssl_socket_t *s, char *data, int length)) {
+ us_socket_context_on_data(
+ 0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *, char *, int))
+ ssl_on_data);
+ context->on_data = on_data;
+}
+
+void us_internal_ssl_socket_context_on_writable(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_writable)(
+ struct us_internal_ssl_socket_t *s)) {
+ us_socket_context_on_writable(0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_on_writable);
+ context->on_writable = on_writable;
+}
+
+void us_internal_ssl_socket_context_on_timeout(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_timeout)(
+ struct us_internal_ssl_socket_t *s)) {
+ us_socket_context_on_timeout(0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ on_timeout);
+}
+
+void us_internal_ssl_socket_context_on_long_timeout(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_long_timeout)(
+ struct us_internal_ssl_socket_t *s)) {
+ us_socket_context_on_long_timeout(
+ 0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *)) on_long_timeout);
+}
+
+/* We do not really listen to passed FIN-handler, we entirely override it with
+ * our handler since SSL doesn't really have support for half-closed sockets */
+void us_internal_ssl_socket_context_on_end(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_end)(
+ struct us_internal_ssl_socket_t *)) {
+ us_socket_context_on_end(0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_on_end);
+}
+
+void us_internal_ssl_socket_context_on_connect_error(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_connect_error)(
+ struct us_internal_ssl_socket_t *, int code)) {
+ us_socket_context_on_connect_error(
+ 0, (struct us_socket_context_t *)context,
+ (struct us_socket_t * (*)(struct us_socket_t *, int)) on_connect_error);
+}
+
+void *us_internal_ssl_socket_context_ext(
+ struct us_internal_ssl_socket_context_t *context) {
+ return context + 1;
}
/* Per socket functions */
-void* us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t* s)
-{
- return s->ssl;
+void *
+us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s) {
+ return s->ssl;
}
-int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t* s, const char* data, int length, int msg_more)
-{
+int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
+ const char *data, int length,
+ int msg_more) {
- if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
- return 0;
- }
- return us_socket_write(0, &s->s, data, length, msg_more);
-}
-
-int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t* s, const char* data, int length, int msg_more)
-{
-
- if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
- return 0;
- }
-
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
-
- struct us_loop_t* loop = us_socket_context_loop(0, &context->sc);
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
-
- // it makes literally no sense to touch this here! it should start at 0 and ONLY be set and reset by the on_data function!
- // the way is is now, triggering a write from a read will essentially delete all input data!
- // what we need to do is to check if this ever is non-zero and print a warning
-
- loop_ssl_data->ssl_read_input_length = 0;
-
- loop_ssl_data->ssl_socket = &s->s;
- loop_ssl_data->msg_more = msg_more;
- loop_ssl_data->last_write_was_msg_more = 0;
- // printf("Calling SSL_write\n");
- int written = SSL_write(s->ssl, data, length);
- // printf("Returning from SSL_write\n");
- loop_ssl_data->msg_more = 0;
-
- if (loop_ssl_data->last_write_was_msg_more && !msg_more) {
- us_socket_flush(0, &s->s);
- }
-
- if (written > 0) {
- return written;
- } else {
- int err = SSL_get_error(s->ssl, written);
- if (err == SSL_ERROR_WANT_READ) {
- // here we need to trigger writable event next ssl_read!
- s->ssl_write_wants_read = 1;
- } else if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
- // these two errors may add to the error queue, which is per thread and must be cleared
- ERR_clear_error();
-
- // all errors here except for want write are critical and should not happen
- }
-
- return 0;
- }
-}
-
-void* us_internal_ssl_socket_ext(struct us_internal_ssl_socket_t* s)
-{
- return s + 1;
-}
-
-int us_internal_ssl_socket_is_shut_down(struct us_internal_ssl_socket_t* s)
-{
- return us_socket_is_shut_down(0, &s->s) || SSL_get_shutdown(s->ssl) & SSL_SENT_SHUTDOWN;
+ if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
+ return 0;
+ }
+ return us_socket_write(0, &s->s, data, length, msg_more);
}
-void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t* s)
-{
- if (!us_socket_is_closed(0, &s->s) && !us_internal_ssl_socket_is_shut_down(s)) {
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_loop_t* loop = us_socket_context_loop(0, &context->sc);
- struct loop_ssl_data* loop_ssl_data = (struct loop_ssl_data*)loop->data.ssl_data;
-
- // also makes no sense to touch this here!
- // however the idea is that if THIS socket is not the same as ssl_socket then this data is not for me
- // but this is not correct as it is currently anyways, any data available should be properly reset
- loop_ssl_data->ssl_read_input_length = 0;
+int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,
+ const char *data, int length, int msg_more) {
- // essentially we need two of these: one for CURRENT CALL and one for CURRENT SOCKET WITH DATA
- // if those match in the BIO function then you may read, if not then you may not read
- // we need ssl_read_socket to be set in on_data and checked in the BIO
- loop_ssl_data->ssl_socket = &s->s;
+ if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
+ return 0;
+ }
- loop_ssl_data->msg_more = 0;
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
- // sets SSL_SENT_SHUTDOWN no matter what (not actually true if error!)
- int ret = SSL_shutdown(s->ssl);
- if (ret == 0) {
- ret = SSL_shutdown(s->ssl);
- }
+ struct us_loop_t *loop = us_socket_context_loop(0, &context->sc);
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
- if (ret < 0) {
+ // it makes literally no sense to touch this here! it should start at 0 and
+ // ONLY be set and reset by the on_data function! the way is is now,
+ // triggering a write from a read will essentially delete all input data! what
+ // we need to do is to check if this ever is non-zero and print a warning
- int err = SSL_get_error(s->ssl, ret);
- if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
- // clear
- ERR_clear_error();
- }
+ loop_ssl_data->ssl_read_input_length = 0;
- // we get here if we are shutting down while still in init
- us_socket_shutdown(0, &s->s);
- }
- }
-}
-
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_context_adopt_socket(struct us_internal_ssl_socket_context_t* context, struct us_internal_ssl_socket_t* s, int ext_size)
-{
- // todo: this is completely untested
- return (struct us_internal_ssl_socket_t*)us_socket_context_adopt_socket(0, &context->sc, &s->s, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + ext_size);
-}
+ loop_ssl_data->ssl_socket = &s->s;
+ loop_ssl_data->msg_more = msg_more;
+ loop_ssl_data->last_write_was_msg_more = 0;
+ // printf("Calling SSL_write\n");
+ int written = SSL_write(s->ssl, data, length);
+ // printf("Returning from SSL_write\n");
+ loop_ssl_data->msg_more = 0;
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_close(struct us_internal_ssl_socket_t* s, int code, void* reason)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
+ if (loop_ssl_data->last_write_was_msg_more && !msg_more) {
+ us_socket_flush(0, &s->s);
+ }
- if (wrapped_context->events.on_close) {
- wrapped_context->events.on_close((struct us_socket_t*)s, code, reason);
- }
+ if (written > 0) {
+ return written;
+ } else {
+ int err = SSL_get_error(s->ssl, written);
+ if (err == SSL_ERROR_WANT_READ) {
+ // here we need to trigger writable event next ssl_read!
+ s->ssl_write_wants_read = 1;
+ } else if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
+ // these two errors may add to the error queue, which is per thread and
+ // must be cleared
+ ERR_clear_error();
- // writting here can cause the context to not be writable anymore but its the user responsability to check for that
- if (wrapped_context->old_events.on_close) {
- wrapped_context->old_events.on_close((struct us_socket_t*)s, code, reason);
+ // all errors here except for want write are critical and should not
+ // happen
}
- return s;
+ return 0;
+ }
}
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_writable(struct us_internal_ssl_socket_t* s)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
-
- if (wrapped_context->events.on_writable) {
- wrapped_context->events.on_writable((struct us_socket_t*)s);
- }
-
- // writting here can cause the context to not be writable anymore but its the user responsability to check for that
- if (wrapped_context->old_events.on_writable) {
- wrapped_context->old_events.on_writable((struct us_socket_t*)s);
- }
-
- return s;
+void *us_internal_ssl_socket_ext(struct us_internal_ssl_socket_t *s) {
+ return s + 1;
}
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_data(struct us_internal_ssl_socket_t* s, char* data, int length)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
- // raw data if needed
- if (wrapped_context->old_events.on_data) {
- wrapped_context->old_events.on_data((struct us_socket_t*)s, data, length);
- }
- // ssl wrapped data
- return ssl_on_data(s, data, length);
+int us_internal_ssl_socket_is_shut_down(struct us_internal_ssl_socket_t *s) {
+ return us_socket_is_shut_down(0, &s->s) ||
+ SSL_get_shutdown(s->ssl) & SSL_SENT_SHUTDOWN;
}
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_timeout(struct us_internal_ssl_socket_t* s)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
+void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t *s) {
+ if (!us_socket_is_closed(0, &s->s) &&
+ !us_internal_ssl_socket_is_shut_down(s)) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_loop_t *loop = us_socket_context_loop(0, &context->sc);
+ struct loop_ssl_data *loop_ssl_data =
+ (struct loop_ssl_data *)loop->data.ssl_data;
- if (wrapped_context->events.on_timeout) {
- wrapped_context->events.on_timeout((struct us_socket_t*)s);
- }
-
- if (wrapped_context->old_events.on_timeout) {
- wrapped_context->old_events.on_timeout((struct us_socket_t*)s);
- }
-
- return s;
-}
+ // also makes no sense to touch this here!
+ // however the idea is that if THIS socket is not the same as ssl_socket
+ // then this data is not for me but this is not correct as it is currently
+ // anyways, any data available should be properly reset
+ loop_ssl_data->ssl_read_input_length = 0;
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_long_timeout(struct us_internal_ssl_socket_t* s)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
+ // essentially we need two of these: one for CURRENT CALL and one for
+ // CURRENT SOCKET WITH DATA if those match in the BIO function then you may
+ // read, if not then you may not read we need ssl_read_socket to be set in
+ // on_data and checked in the BIO
+ loop_ssl_data->ssl_socket = &s->s;
- if (wrapped_context->events.on_long_timeout) {
- wrapped_context->events.on_long_timeout((struct us_socket_t*)s);
- }
+ loop_ssl_data->msg_more = 0;
- if (wrapped_context->old_events.on_long_timeout) {
- wrapped_context->old_events.on_long_timeout((struct us_socket_t*)s);
- }
+ // sets SSL_SENT_SHUTDOWN no matter what (not actually true if error!)
+ int ret = SSL_shutdown(s->ssl);
+ if (ret == 0) {
+ ret = SSL_shutdown(s->ssl);
+ }
+
+ if (ret < 0) {
- return s;
+ int err = SSL_get_error(s->ssl, ret);
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
+ // clear
+ ERR_clear_error();
+ }
+
+ // we get here if we are shutting down while still in init
+ us_socket_shutdown(0, &s->s);
+ }
+ }
+}
+
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *s, int ext_size) {
+ // todo: this is completely untested
+ return (struct us_internal_ssl_socket_t *)us_socket_context_adopt_socket(
+ 0, &context->sc, &s->s,
+ sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
+ ext_size);
}
-struct us_internal_ssl_socket_t* ssl_wrapped_context_on_end(struct us_internal_ssl_socket_t* s)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
-
- if (wrapped_context->events.on_end) {
- wrapped_context->events.on_end((struct us_socket_t*)s);
- }
-
- if (wrapped_context->old_events.on_end) {
- wrapped_context->old_events.on_end((struct us_socket_t*)s);
- }
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_close(struct us_internal_ssl_socket_t *s, int code,
+ void *reason) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_close) {
+ wrapped_context->events.on_close((struct us_socket_t *)s, code, reason);
+ }
+
+ // writting here can cause the context to not be writable anymore but its the
+ // user responsability to check for that
+ if (wrapped_context->old_events.on_close) {
+ wrapped_context->old_events.on_close((struct us_socket_t *)s, code, reason);
+ }
+
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_writable(struct us_internal_ssl_socket_t *s) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_writable) {
+ wrapped_context->events.on_writable((struct us_socket_t *)s);
+ }
+
+ // writting here can cause the context to not be writable anymore but its the
+ // user responsability to check for that
+ if (wrapped_context->old_events.on_writable) {
+ wrapped_context->old_events.on_writable((struct us_socket_t *)s);
+ }
+
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_data(struct us_internal_ssl_socket_t *s, char *data,
+ int length) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+ // raw data if needed
+ if (wrapped_context->old_events.on_data) {
+ wrapped_context->old_events.on_data((struct us_socket_t *)s, data, length);
+ }
+ // ssl wrapped data
+ return ssl_on_data(s, data, length);
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_timeout(struct us_internal_ssl_socket_t *s) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_timeout) {
+ wrapped_context->events.on_timeout((struct us_socket_t *)s);
+ }
+
+ if (wrapped_context->old_events.on_timeout) {
+ wrapped_context->old_events.on_timeout((struct us_socket_t *)s);
+ }
+
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_long_timeout(struct us_internal_ssl_socket_t *s) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_long_timeout) {
+ wrapped_context->events.on_long_timeout((struct us_socket_t *)s);
+ }
+
+ if (wrapped_context->old_events.on_long_timeout) {
+ wrapped_context->old_events.on_long_timeout((struct us_socket_t *)s);
+ }
+
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_context_on_end(struct us_internal_ssl_socket_t *s) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_end) {
+ wrapped_context->events.on_end((struct us_socket_t *)s);
+ }
+
+ if (wrapped_context->old_events.on_end) {
+ wrapped_context->old_events.on_end((struct us_socket_t *)s);
+ }
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+ssl_wrapped_on_connect_error(struct us_internal_ssl_socket_t *s, int code) {
+ struct us_internal_ssl_socket_context_t *context =
+ (struct us_internal_ssl_socket_context_t *)us_socket_context(0, &s->s);
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ context);
+
+ if (wrapped_context->events.on_connect_error) {
+ wrapped_context->events.on_connect_error((struct us_socket_t *)s, code);
+ }
+
+ if (wrapped_context->old_events.on_connect_error) {
+ wrapped_context->old_events.on_connect_error((struct us_socket_t *)s, code);
+ }
+ return s;
+}
+
+struct us_internal_ssl_socket_t *
+us_internal_ssl_socket_open(struct us_internal_ssl_socket_t *s, int is_client,
+ char *ip, int ip_length) {
+ // closed
+ if (us_socket_is_closed(0, &s->s)) {
return s;
-}
-
-struct us_internal_ssl_socket_t* ssl_wrapped_on_connect_error(struct us_internal_ssl_socket_t* s, int code)
-{
- struct us_internal_ssl_socket_context_t* context = (struct us_internal_ssl_socket_context_t*)us_socket_context(0, &s->s);
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(context);
-
- if (wrapped_context->events.on_connect_error) {
- wrapped_context->events.on_connect_error((struct us_socket_t*)s, code);
- }
-
- if (wrapped_context->old_events.on_connect_error) {
- wrapped_context->old_events.on_connect_error((struct us_socket_t*)s, code);
- }
+ }
+ // already opened
+ if (s->ssl)
return s;
-}
-
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_open(struct us_internal_ssl_socket_t* s, int is_client, char* ip, int ip_length)
-{
- // closed
- if (us_socket_is_closed(0, &s->s)) {
- return s;
- }
- // already opened
- if (s->ssl)
- return s;
- // start SSL open
- return ssl_on_open(s, is_client, ip, ip_length);
+ // start SSL open
+ return ssl_on_open(s, is_client, ip, ip_length);
}
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_wrap_with_tls(struct us_socket_t* s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size)
-{
- /* Cannot wrap a closed socket */
- if (us_socket_is_closed(0, s)) {
- return NULL;
- }
-
- struct us_socket_context_t* old_context = us_socket_context(0, s);
-
- struct us_socket_context_t* context = us_create_bun_socket_context(1, old_context->loop, sizeof(struct us_wrapped_socket_context_t), options);
- struct us_internal_ssl_socket_context_t* tls_context = (struct us_internal_ssl_socket_context_t*)context;
-
- struct us_wrapped_socket_context_t* wrapped_context = (struct us_wrapped_socket_context_t*)us_internal_ssl_socket_context_ext(tls_context);
- // we need to fire this events on the old context
- struct us_socket_events_t old_events = (struct us_socket_events_t) {
- .on_close = old_context->on_close,
- .on_data = old_context->on_data,
- .on_writable = old_context->on_writable,
- .on_timeout = old_context->on_socket_timeout,
- .on_long_timeout = old_context->on_socket_long_timeout,
- .on_end = old_context->on_end,
- .on_connect_error = old_context->on_connect_error,
- };
- wrapped_context->old_events = old_events;
- wrapped_context->events = events;
-
- // no need to wrap open because socket is already open (only new context will be called so we can configure hostname and ssl stuff normally here before handshake)
- tls_context->on_open = (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t*, int, char*, int)) events.on_open;
-
- // on handshake is not available on the old context so we just add this
- if (events.on_handshake) {
- us_internal_on_ssl_handshake(tls_context, (void (*)(struct us_internal_ssl_socket_t*, int, struct us_bun_verify_error_t, void*))events.on_handshake, NULL);
- }
-
- // we need to wrap these events because we need to call the old context events as well
- us_socket_context_on_connect_error(0, context, (struct us_socket_t * (*)(struct us_socket_t*, int)) ssl_wrapped_on_connect_error);
- us_socket_context_on_end(0, context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_wrapped_context_on_end);
- us_socket_context_on_long_timeout(0, context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_wrapped_context_on_long_timeout);
- us_socket_context_on_timeout(0, context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_wrapped_context_on_timeout);
-
- // special case this will be called after ssl things are done
-
- // called from ssl_on_data handler is called inside ssl_wrapped_context_on_data
- tls_context->on_data = (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t*, char*, int)) events.on_data;
- us_socket_context_on_data(0, context, (struct us_socket_t * (*)(struct us_socket_t*, char*, int)) ssl_wrapped_context_on_data);
-
- // here is the inverse of the above ssl_on_writable will call ssl_wrapped_context_on_writable
- tls_context->on_writable = ssl_wrapped_context_on_writable;
- us_socket_context_on_writable(0, context, (struct us_socket_t * (*)(struct us_socket_t*)) ssl_on_writable);
-
- tls_context->on_close = ssl_wrapped_context_on_close;
- us_socket_context_on_close(0, context, (struct us_socket_t * (*)(struct us_socket_t*, int, void*)) ssl_on_close);
-
- // will resize to tls + ext size
- struct us_internal_ssl_socket_t* socket = (struct us_internal_ssl_socket_t*)us_socket_context_adopt_socket(0, context, s, sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) + socket_ext_size);
- socket->ssl = NULL;
- socket->ssl_write_wants_read = 0;
- socket->ssl_read_wants_write = 0;
-
- return socket;
-}
-
-#endif
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
+ struct us_socket_t *s, struct us_bun_socket_context_options_t options,
+ struct us_socket_events_t events, int socket_ext_size) {
+ /* Cannot wrap a closed socket */
+ if (us_socket_is_closed(0, s)) {
+ return NULL;
+ }
+
+ struct us_socket_context_t *old_context = us_socket_context(0, s);
+
+ struct us_socket_context_t *context = us_create_bun_socket_context(
+ 1, old_context->loop, sizeof(struct us_wrapped_socket_context_t),
+ options);
+ struct us_internal_ssl_socket_context_t *tls_context =
+ (struct us_internal_ssl_socket_context_t *)context;
+
+ struct us_wrapped_socket_context_t *wrapped_context =
+ (struct us_wrapped_socket_context_t *)us_internal_ssl_socket_context_ext(
+ tls_context);
+ // we need to fire this events on the old context
+ struct us_socket_events_t old_events = (struct us_socket_events_t){
+ .on_close = old_context->on_close,
+ .on_data = old_context->on_data,
+ .on_writable = old_context->on_writable,
+ .on_timeout = old_context->on_socket_timeout,
+ .on_long_timeout = old_context->on_socket_long_timeout,
+ .on_end = old_context->on_end,
+ .on_connect_error = old_context->on_connect_error,
+ };
+ wrapped_context->old_events = old_events;
+ wrapped_context->events = events;
+
+ // no need to wrap open because socket is already open (only new context will
+ // be called so we can configure hostname and ssl stuff normally here before
+ // handshake)
+ tls_context->on_open =
+ (struct us_internal_ssl_socket_t *
+ (*)(struct us_internal_ssl_socket_t *, int, char *, int)) events.on_open;
+
+ // on handshake is not available on the old context so we just add this
+ if (events.on_handshake) {
+ us_internal_on_ssl_handshake(
+ tls_context,
+ (void (*)(struct us_internal_ssl_socket_t *, int,
+ struct us_bun_verify_error_t, void *))events.on_handshake,
+ NULL);
+ }
+
+ // we need to wrap these events because we need to call the old context events
+ // as well
+ us_socket_context_on_connect_error(
+ 0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *, int))
+ ssl_wrapped_on_connect_error);
+ us_socket_context_on_end(0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_wrapped_context_on_end);
+ us_socket_context_on_long_timeout(
+ 0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_wrapped_context_on_long_timeout);
+ us_socket_context_on_timeout(0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_wrapped_context_on_timeout);
+
+ // special case this will be called after ssl things are done
+
+ // called from ssl_on_data handler is called inside
+ // ssl_wrapped_context_on_data
+ tls_context->on_data =
+ (struct us_internal_ssl_socket_t *
+ (*)(struct us_internal_ssl_socket_t *, char *, int)) events.on_data;
+ us_socket_context_on_data(
+ 0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *, char *, int))
+ ssl_wrapped_context_on_data);
+
+ // here is the inverse of the above ssl_on_writable will call
+ // ssl_wrapped_context_on_writable
+ tls_context->on_writable = ssl_wrapped_context_on_writable;
+ us_socket_context_on_writable(0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *))
+ ssl_on_writable);
+
+ tls_context->on_close = ssl_wrapped_context_on_close;
+ us_socket_context_on_close(
+ 0, context,
+ (struct us_socket_t * (*)(struct us_socket_t *, int, void *))
+ ssl_on_close);
+
+ // will resize to tls + ext size
+ struct us_internal_ssl_socket_t *socket =
+ (struct us_internal_ssl_socket_t *)us_socket_context_adopt_socket(
+ 0, context, s,
+ sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
+ socket_ext_size);
+ socket->ssl = NULL;
+ socket->ssl_write_wants_read = 0;
+ socket->ssl_read_wants_write = 0;
+
+ return socket;
+}
+
+#endif \ No newline at end of file
diff --git a/packages/bun-usockets/src/internal/internal.h b/packages/bun-usockets/src/internal/internal.h
index d6c5d3140..0f1ede24b 100644
--- a/packages/bun-usockets/src/internal/internal.h
+++ b/packages/bun-usockets/src/internal/internal.h
@@ -18,7 +18,6 @@
#ifndef INTERNAL_H
#define INTERNAL_H
-
#if defined(_MSC_VER)
#ifndef __cplusplus
#define alignas(x) __declspec(align(x))
@@ -34,7 +33,11 @@
#if defined(LIBUS_USE_EPOLL) || defined(LIBUS_USE_KQUEUE)
#define LIBUS_MAX_READY_POLLS 1024
-void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop, struct us_poll_t *old_poll, struct us_poll_t *new_poll, int old_events, int new_events);
+void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop,
+ struct us_poll_t *old_poll,
+ struct us_poll_t *new_poll,
+ int old_events,
+ int new_events);
#endif
/* We only have one networking implementation so far */
@@ -51,33 +54,41 @@ void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop, struct
/* Poll type and what it polls for */
enum {
- /* Two first bits */
- POLL_TYPE_SOCKET = 0,
- POLL_TYPE_SOCKET_SHUT_DOWN = 1,
- POLL_TYPE_SEMI_SOCKET = 2,
- POLL_TYPE_CALLBACK = 3,
-
- /* Two last bits */
- POLL_TYPE_POLLING_OUT = 4,
- POLL_TYPE_POLLING_IN = 8
+ /* Two first bits */
+ POLL_TYPE_SOCKET = 0,
+ POLL_TYPE_SOCKET_SHUT_DOWN = 1,
+ POLL_TYPE_SEMI_SOCKET = 2,
+ POLL_TYPE_CALLBACK = 3,
+
+ /* Two last bits */
+ POLL_TYPE_POLLING_OUT = 4,
+ POLL_TYPE_POLLING_IN = 8
};
/* Loop related */
-void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events);
+void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error,
+ int events);
void us_internal_timer_sweep(struct us_loop_t *loop);
void us_internal_free_closed_sockets(struct us_loop_t *loop);
-void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context);
-void us_internal_loop_unlink(struct us_loop_t *loop, struct us_socket_context_t *context);
-void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop),
- void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop));
+void us_internal_loop_link(struct us_loop_t *loop,
+ struct us_socket_context_t *context);
+void us_internal_loop_unlink(struct us_loop_t *loop,
+ struct us_socket_context_t *context);
+void us_internal_loop_data_init(struct us_loop_t *loop,
+ void (*wakeup_cb)(struct us_loop_t *loop),
+ void (*pre_cb)(struct us_loop_t *loop),
+ void (*post_cb)(struct us_loop_t *loop));
void us_internal_loop_data_free(struct us_loop_t *loop);
void us_internal_loop_pre(struct us_loop_t *loop);
void us_internal_loop_post(struct us_loop_t *loop);
/* Asyncs (old) */
-struct us_internal_async *us_internal_create_async(struct us_loop_t *loop, int fallthrough, unsigned int ext_size);
+struct us_internal_async *us_internal_create_async(struct us_loop_t *loop,
+ int fallthrough,
+ unsigned int ext_size);
void us_internal_async_close(struct us_internal_async *a);
-void us_internal_async_set(struct us_internal_async *a, void (*cb)(struct us_internal_async *));
+void us_internal_async_set(struct us_internal_async *a,
+ void (*cb)(struct us_internal_async *));
void us_internal_async_wakeup(struct us_internal_async *a);
/* Eventing related */
@@ -90,44 +101,48 @@ void us_internal_init_loop_ssl_data(struct us_loop_t *loop);
void us_internal_free_loop_ssl_data(struct us_loop_t *loop);
/* Socket context related */
-void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s);
-void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s);
+void us_internal_socket_context_link_socket(struct us_socket_context_t *context,
+ struct us_socket_t *s);
+void us_internal_socket_context_unlink_socket(
+ struct us_socket_context_t *context, struct us_socket_t *s);
/* Sockets are polls */
struct us_socket_t {
- alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p; // 4 bytes
- unsigned char timeout; // 1 byte
- unsigned char long_timeout; // 1 byte
- unsigned short low_prio_state; /* 0 = not in low-prio queue, 1 = is in low-prio queue, 2 = was in low-prio queue in this iteration */
- struct us_socket_context_t *context;
- struct us_socket_t *prev, *next;
+ alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p; // 4 bytes
+ unsigned char timeout; // 1 byte
+ unsigned char long_timeout; // 1 byte
+ unsigned short
+ low_prio_state; /* 0 = not in low-prio queue, 1 = is in low-prio queue, 2
+ = was in low-prio queue in this iteration */
+ struct us_socket_context_t *context;
+ struct us_socket_t *prev, *next;
};
struct us_wrapped_socket_context_t {
- struct us_socket_events_t events;
- struct us_socket_events_t old_events;
+ struct us_socket_events_t events;
+ struct us_socket_events_t old_events;
};
#if defined(LIBUS_USE_KQUEUE)
/* Internal callback types are polls just like sockets */
struct us_internal_callback_t {
- alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
- struct us_loop_t *loop;
- int cb_expects_the_loop;
- int leave_poll_ready;
- void (*cb)(struct us_internal_callback_t *cb);
- mach_port_t port;
- void* machport_buf;
+ alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
+ struct us_loop_t *loop;
+ int cb_expects_the_loop;
+ int leave_poll_ready;
+ void (*cb)(struct us_internal_callback_t *cb);
+ mach_port_t port;
+ void *machport_buf;
};
#else
struct us_internal_callback_t {
- alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
- struct us_loop_t *loop;
- int cb_expects_the_loop;
- int leave_poll_ready;
- void (*cb)(struct us_internal_callback_t *cb);
+ alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
+ struct us_loop_t *loop;
+ int cb_expects_the_loop;
+ int leave_poll_ready;
+ void (*cb)(struct us_internal_callback_t *cb);
};
#endif
@@ -135,7 +150,7 @@ struct us_internal_callback_t {
#if __cplusplus
extern "C" {
#endif
-int us_internal_raw_root_certs(struct us_cert_string_t** out);
+int us_internal_raw_root_certs(struct us_cert_string_t **out);
#if __cplusplus
}
@@ -143,34 +158,37 @@ int us_internal_raw_root_certs(struct us_cert_string_t** out);
/* Listen sockets are sockets */
struct us_listen_socket_t {
- alignas(LIBUS_EXT_ALIGNMENT) struct us_socket_t s;
- unsigned int socket_ext_size;
+ alignas(LIBUS_EXT_ALIGNMENT) struct us_socket_t s;
+ unsigned int socket_ext_size;
};
/* Listen sockets are keps in their own list */
-void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *s);
-void us_internal_socket_context_unlink_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *s);
+void us_internal_socket_context_link_listen_socket(
+ struct us_socket_context_t *context, struct us_listen_socket_t *s);
+void us_internal_socket_context_unlink_listen_socket(
+ struct us_socket_context_t *context, struct us_listen_socket_t *s);
struct us_socket_context_t {
- alignas(LIBUS_EXT_ALIGNMENT) struct us_loop_t *loop;
- uint32_t global_tick;
- unsigned char timestamp;
- unsigned char long_timestamp;
- struct us_socket_t *head_sockets;
- struct us_listen_socket_t *head_listen_sockets;
- struct us_socket_t *iterator;
- struct us_socket_context_t *prev, *next;
-
- struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length);
- struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
- struct us_socket_t *(*on_writable)(struct us_socket_t *);
- struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
- //void (*on_timeout)(struct us_socket_context *);
- struct us_socket_t *(*on_socket_timeout)(struct us_socket_t *);
- struct us_socket_t *(*on_socket_long_timeout)(struct us_socket_t *);
- struct us_socket_t *(*on_end)(struct us_socket_t *);
- struct us_socket_t *(*on_connect_error)(struct us_socket_t *, int code);
- int (*is_low_prio)(struct us_socket_t *);
+ alignas(LIBUS_EXT_ALIGNMENT) struct us_loop_t *loop;
+ uint32_t global_tick;
+ unsigned char timestamp;
+ unsigned char long_timestamp;
+ struct us_socket_t *head_sockets;
+ struct us_listen_socket_t *head_listen_sockets;
+ struct us_socket_t *iterator;
+ struct us_socket_context_t *prev, *next;
+
+ struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip,
+ int ip_length);
+ struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
+ struct us_socket_t *(*on_writable)(struct us_socket_t *);
+ struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
+ // void (*on_timeout)(struct us_socket_context *);
+ struct us_socket_t *(*on_socket_timeout)(struct us_socket_t *);
+ struct us_socket_t *(*on_socket_long_timeout)(struct us_socket_t *);
+ struct us_socket_t *(*on_end)(struct us_socket_t *);
+ struct us_socket_t *(*on_connect_error)(struct us_socket_t *, int code);
+ int (*is_low_prio)(struct us_socket_t *);
};
/* Internal SSL interface */
@@ -178,84 +196,142 @@ struct us_socket_context_t {
struct us_internal_ssl_socket_context_t;
struct us_internal_ssl_socket_t;
-typedef void (*us_internal_on_handshake_t)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data);
+typedef void (*us_internal_on_handshake_t)(
+ struct us_internal_ssl_socket_t *, int success,
+ struct us_bun_verify_error_t verify_error, void *custom_data);
/* SNI functions */
-void us_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user);
-void us_bun_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern, struct us_bun_socket_context_options_t options, void *user);
-void us_internal_ssl_socket_context_remove_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern);
-void us_internal_ssl_socket_context_on_server_name(struct us_internal_ssl_socket_context_t *context, void (*cb)(struct us_internal_ssl_socket_context_t *, const char *));
-void *us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s);
-void *us_internal_ssl_socket_context_find_server_name_userdata(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern);
-
-void *us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s);
-void *us_internal_ssl_socket_context_get_native_handle(struct us_internal_ssl_socket_context_t *context);
-struct us_bun_verify_error_t us_internal_verify_error(struct us_internal_ssl_socket_t *s);
-struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(struct us_loop_t *loop,
- int context_ext_size, struct us_socket_context_options_t options);
-struct us_internal_ssl_socket_context_t *us_internal_bun_create_ssl_socket_context(struct us_loop_t *loop,
- int context_ext_size, struct us_bun_socket_context_options_t options);
-
-void us_internal_ssl_socket_context_free(struct us_internal_ssl_socket_context_t *context);
-void us_internal_ssl_socket_context_on_open(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_open)(struct us_internal_ssl_socket_t *s, int is_client, char *ip, int ip_length));
-
-void us_internal_ssl_socket_context_on_close(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_close)(struct us_internal_ssl_socket_t *s, int code, void *reason));
-
-void us_internal_ssl_socket_context_on_data(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_data)(struct us_internal_ssl_socket_t *s, char *data, int length));
-
-void us_internal_ssl_handshake(struct us_internal_ssl_socket_t *s, us_internal_on_handshake_t on_handshake, void* custom_data);
-void us_internal_on_ssl_handshake(struct us_internal_ssl_socket_context_t * context, us_internal_on_handshake_t on_handshake, void* custom_data);
-
-void us_internal_ssl_socket_context_on_writable(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_writable)(struct us_internal_ssl_socket_t *s));
-
-void us_internal_ssl_socket_context_on_timeout(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_timeout)(struct us_internal_ssl_socket_t *s));
-
-void us_internal_ssl_socket_context_on_long_timeout(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_timeout)(struct us_internal_ssl_socket_t *s));
-
-void us_internal_ssl_socket_context_on_end(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_end)(struct us_internal_ssl_socket_t *s));
-
-void us_internal_ssl_socket_context_on_connect_error(struct us_internal_ssl_socket_context_t *context,
- struct us_internal_ssl_socket_t *(*on_connect_error)(struct us_internal_ssl_socket_t *s, int code));
-
-struct us_listen_socket_t *us_internal_ssl_socket_context_listen(struct us_internal_ssl_socket_context_t *context,
- const char *host, int port, int options, int socket_ext_size);
-
-struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(struct us_internal_ssl_socket_context_t *context,
- const char *path, int options, int socket_ext_size);
-
-struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect(struct us_internal_ssl_socket_context_t *context,
- const char *host, int port, const char *source_host, int options, int socket_ext_size);
-
-
-struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(struct us_internal_ssl_socket_context_t *context,
- const char *server_path, int options, int socket_ext_size);
-
-int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s, const char *data, int length, int msg_more);
-int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s, const char *data, int length, int msg_more);
-
-void us_internal_ssl_socket_timeout(struct us_internal_ssl_socket_t *s, unsigned int seconds);
-void *us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t *s);
-struct us_internal_ssl_socket_context_t *us_internal_ssl_socket_get_context(struct us_internal_ssl_socket_t *s);
+void us_internal_ssl_socket_context_add_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern, struct us_socket_context_options_t options,
+ void *user);
+void us_bun_internal_ssl_socket_context_add_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern,
+ struct us_bun_socket_context_options_t options, void *user);
+void us_internal_ssl_socket_context_remove_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern);
+void us_internal_ssl_socket_context_on_server_name(
+ struct us_internal_ssl_socket_context_t *context,
+ void (*cb)(struct us_internal_ssl_socket_context_t *, const char *));
+void *
+us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s);
+void *us_internal_ssl_socket_context_find_server_name_userdata(
+ struct us_internal_ssl_socket_context_t *context,
+ const char *hostname_pattern);
+
+void *
+us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s);
+void *us_internal_ssl_socket_context_get_native_handle(
+ struct us_internal_ssl_socket_context_t *context);
+struct us_bun_verify_error_t
+us_internal_verify_error(struct us_internal_ssl_socket_t *s);
+struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
+ struct us_loop_t *loop, int context_ext_size,
+ struct us_socket_context_options_t options);
+struct us_internal_ssl_socket_context_t *
+us_internal_bun_create_ssl_socket_context(
+ struct us_loop_t *loop, int context_ext_size,
+ struct us_bun_socket_context_options_t options);
+
+void us_internal_ssl_socket_context_free(
+ struct us_internal_ssl_socket_context_t *context);
+void us_internal_ssl_socket_context_on_open(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_open)(
+ struct us_internal_ssl_socket_t *s, int is_client, char *ip,
+ int ip_length));
+
+void us_internal_ssl_socket_context_on_close(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_close)(
+ struct us_internal_ssl_socket_t *s, int code, void *reason));
+
+void us_internal_ssl_socket_context_on_data(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_data)(
+ struct us_internal_ssl_socket_t *s, char *data, int length));
+
+void us_internal_ssl_handshake(struct us_internal_ssl_socket_t *s);
+void us_internal_on_ssl_handshake(
+ struct us_internal_ssl_socket_context_t *context,
+ us_internal_on_handshake_t onhandshake, void *custom_data);
+
+void us_internal_ssl_socket_context_on_writable(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_writable)(
+ struct us_internal_ssl_socket_t *s));
+
+void us_internal_ssl_socket_context_on_timeout(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_timeout)(
+ struct us_internal_ssl_socket_t *s));
+
+void us_internal_ssl_socket_context_on_long_timeout(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_timeout)(
+ struct us_internal_ssl_socket_t *s));
+
+void us_internal_ssl_socket_context_on_end(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_end)(
+ struct us_internal_ssl_socket_t *s));
+
+void us_internal_ssl_socket_context_on_connect_error(
+ struct us_internal_ssl_socket_context_t *context,
+ struct us_internal_ssl_socket_t *(*on_connect_error)(
+ struct us_internal_ssl_socket_t *s, int code));
+
+struct us_listen_socket_t *us_internal_ssl_socket_context_listen(
+ struct us_internal_ssl_socket_context_t *context, const char *host,
+ int port, int options, int socket_ext_size);
+
+struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
+ struct us_internal_ssl_socket_context_t *context, const char *path,
+ int options, int socket_ext_size);
+
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect(
+ struct us_internal_ssl_socket_context_t *context, const char *host,
+ int port, const char *source_host, int options, int socket_ext_size);
+
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
+ struct us_internal_ssl_socket_context_t *context, const char *server_path,
+ int options, int socket_ext_size);
+
+int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,
+ const char *data, int length, int msg_more);
+int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
+ const char *data, int length,
+ int msg_more);
+
+void us_internal_ssl_socket_timeout(struct us_internal_ssl_socket_t *s,
+ unsigned int seconds);
+void *
+us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t *s);
+struct us_internal_ssl_socket_context_t *
+us_internal_ssl_socket_get_context(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_ext(struct us_internal_ssl_socket_t *s);
int us_internal_ssl_socket_is_shut_down(struct us_internal_ssl_socket_t *s);
void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t *s);
-struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(struct us_internal_ssl_socket_context_t *context,
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(
+ struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *s, int ext_size);
-struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(struct us_socket_t *s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size);
-struct us_internal_ssl_socket_context_t *us_internal_create_child_ssl_socket_context(struct us_internal_ssl_socket_context_t *context, int context_ext_size);
-struct us_loop_t *us_internal_ssl_socket_context_loop(struct us_internal_ssl_socket_context_t *context);
-struct us_internal_ssl_socket_t* us_internal_ssl_socket_open(struct us_internal_ssl_socket_t * s, int is_client, char* ip, int ip_length);
-
-int us_raw_root_certs(struct us_cert_string_t**out);
+struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
+ struct us_socket_t *s, struct us_bun_socket_context_options_t options,
+ struct us_socket_events_t events, int socket_ext_size);
+struct us_internal_ssl_socket_context_t *
+us_internal_create_child_ssl_socket_context(
+ struct us_internal_ssl_socket_context_t *context, int context_ext_size);
+struct us_loop_t *us_internal_ssl_socket_context_loop(
+ struct us_internal_ssl_socket_context_t *context);
+struct us_internal_ssl_socket_t *
+us_internal_ssl_socket_open(struct us_internal_ssl_socket_t *s, int is_client,
+ char *ip, int ip_length);
+
+int us_raw_root_certs(struct us_cert_string_t **out);
#endif
#endif // INTERNAL_H