Loading Makefile.am +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ lib_LTLIBRARIES = \ libtlmsp_cfg_la_SOURCES = \ libtlmsp-cfg/api.c \ libtlmsp-cfg/format.c \ libtlmsp-cfg/openssl.c \ libtlmsp-cfg/parse.c \ libtlmsp-cfg/print.c libtlmsp_cfg_la_LIBADD = \ Loading Loading @@ -95,6 +96,7 @@ tlmsp_server_LDADD = \ pkginclude_HEADERS = \ libtlmsp-cfg/libtlmsp-cfg.h \ libtlmsp-cfg/libtlmsp-cfg-openssl.h \ libtlmsp-util/libtlmsp-util.h Loading client/client.c +110 −57 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <inttypes.h> #include <libgen.h> #include <libtlmsp-cfg.h> #include <libtlmsp-cfg-openssl.h> #include <libtlmsp-util.h> #include <stdbool.h> #include <stdio.h> Loading Loading @@ -61,7 +62,8 @@ static void free_client_cb(void *app_data); static bool new_connection(struct client_state *client, const TLMSP_ReconnectState *reconnect_state); static void show_connection_info(void *app_data); static int validate_discovery_results(SSL *ssl, void *arg); static int validate_discovery_results(SSL *ssl, void *arg, TLMSP_Middleboxes *middleboxes); static void free_connection_cb(void *app_data); static void connection_died(struct demo_connection *conn); static void conn_cb(EV_P_ ev_io *w, int revents); Loading Loading @@ -240,7 +242,7 @@ new_connection(struct client_state *client, { struct connection_state *conn_state; struct demo_connection *conn; struct sockaddr *addr; struct sockaddr *addr = NULL; socklen_t addr_len; uint8_t *first_hop_addr = NULL; char *first_hop_addr_str; Loading Loading @@ -351,9 +353,11 @@ new_connection(struct client_state *client, demo_print_errno("Connect failed"); goto error; } free(addr); addr = NULL; if (!demo_connection_init_io(conn, client->ssl_ctx, sock, client->loop, (demo_connection_failed_cb_t)connection_died, conn_cb, EV_WRITE)) connection_died, NULL, conn_cb, EV_WRITE)) goto error; SSL_set_connect_state(conn->ssl); Loading @@ -366,7 +370,6 @@ new_connection(struct client_state *client, demo_print_error_ssl_errq("Failed to set reconnect state"); goto error; } TLMSP_reconnect_state_free(reconnect_state); } demo_connection_start_io(conn); Loading @@ -374,6 +377,7 @@ new_connection(struct client_state *client, return (true); error: free(addr); OPENSSL_free(first_hop_addr); demo_connection_free(conn); return (false); Loading @@ -394,23 +398,19 @@ free_connection_cb(void *app_data) struct connection_state *conn_state = app_data; TLMSP_reconnect_state_free(conn_state->reconnect_state); free(conn_state->read_buffer); free(conn_state); } static int validate_discovery_results(SSL *ssl, void *arg) validate_discovery_results(SSL *ssl, void *arg, TLMSP_Middleboxes *middleboxes) { struct demo_connection *conn = arg; const struct tlmsp_cfg *cfg = conn->app->cfg; TLMSP_Middleboxes *middleboxes; int result; middleboxes = TLMSP_get_middleboxes_instance(conn->ssl); if (middleboxes == NULL) return (0); result = tlmsp_cfg_validate_middlebox_list_client_openssl(cfg, middleboxes); TLMSP_middleboxes_free(middleboxes); return (result); } Loading Loading @@ -440,11 +440,67 @@ static void conn_cb(EV_P_ ev_io *w, int revents) { struct demo_connection *conn = w->data; struct connection_state *conn_state = conn->app_data; int result; int ssl_error; bool pending_writes; demo_connection_pause_io(conn); demo_connection_events_arrived(conn, revents); switch (conn->phase) { case DEMO_CONNECTION_PHASE_HANDSHAKE: result = SSL_connect(conn->ssl); switch (result) { case 0: demo_conn_print_error(conn, "Handshake terminated by protocol"); connection_died(conn); return; break; case 1: demo_conn_log(1, conn, "Handshake complete"); demo_connection_wait_for(conn, EV_READ); if (!demo_connection_handshake_complete(conn)) { connection_died(conn); return; } break; default: ssl_error = SSL_get_error(conn->ssl, result); switch (ssl_error) { case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); /* * Re-establish outbound connection and * re-enter handshake. */ conn_state->reconnect_state = TLMSP_get_reconnect_state(conn->ssl); if (conn_state->reconnect_state == NULL) demo_conn_print_error_ssl_errq(conn, "Reconnect state retrieval failed"); connection_died(conn); return; break; case SSL_ERROR_WANT_READ: demo_conn_log(5, conn, "SSL_ERROR_WANT_READ"); demo_connection_wait_for(conn, EV_READ); break; case SSL_ERROR_WANT_WRITE: demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; default: demo_conn_print_error_ssl(conn, ssl_error, "Handshake terminated due to fatal error"); connection_died(conn); return; break; } break; } break; case DEMO_CONNECTION_PHASE_APPLICATION: /* * The general approach is that we prioritize writes over * reads - we work on pending write data until it is all Loading Loading @@ -488,6 +544,14 @@ conn_cb(EV_P_ ev_io *w, int revents) */ if (demo_connection_wait_events(conn) == 0) demo_connection_wait_for(conn, EV_READ); break; default: demo_conn_print_error(conn, "Unexpected connection phase %d", conn->phase); connection_died(conn); return; break; } demo_connection_resume_io(conn); } Loading Loading @@ -546,7 +610,7 @@ read_containers(struct demo_connection *conn) } else if (!TLMSP_container_readable(container)) { demo_conn_print_error(conn, "Opaque container unexpectedly received in " "context %d using containe API", context_id); "context %d using container API", context_id); TLMSP_container_free(ssl, container); return (false); } else { Loading Loading @@ -577,12 +641,6 @@ read_containers(struct demo_connection *conn) demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); conn_state->reconnect_state = TLMSP_get_reconnect_state(ssl); result = false; break; default: demo_conn_print_error_ssl(conn, ssl_error, "Connection terminated due to fatal read error"); Loading Loading @@ -665,11 +723,6 @@ write_containers(struct demo_connection *conn) demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); conn_state->reconnect_state = TLMSP_get_reconnect_state(ssl); result = false; break; default: demo_conn_print_error_ssl(conn, ssl_error, "Connection terminated due to fatal write error"); Loading libdemo/activity.c +56 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ struct match_groups { }; struct demo_activity_match_state { bool contexts[TLMSP_CONTEXT_ID_MAX + 1]; bool contexts[TLMSP_UTIL_CONTEXT_ID_LUT_SIZE]; struct tlmsp_cfg_activity *activity; struct container_queue_range match_range; size_t match_offset; Loading Loading @@ -95,6 +95,9 @@ static bool demo_activity_queue_payload(struct demo_connection *conn, struct tlmsp_cfg_payload *payload, struct match_groups *match_groups, bool present); static bool demo_activity_queue_alert(struct demo_connection *conn, struct tlmsp_cfg_alert *alert, bool present); static void demo_activity_time_triggered_cb(EV_P_ ev_timer *w, int revents); static bool demo_activity_get_payload_data(struct demo_connection *conn, struct tlmsp_cfg_payload *payload, Loading Loading @@ -351,6 +354,42 @@ demo_activity_queue_payload(struct demo_connection *conn, return (result); } static bool demo_activity_queue_alert(struct demo_connection *conn, struct tlmsp_cfg_alert *alert, bool present) { struct container_queue *q = &conn->write_queue; SSL *ssl = q->conn->ssl; TLMSP_Container *container; tlmsp_context_id_t context_id; context_id = alert->context ? alert->context->id : 0; if (present) demo_conn_present(conn, "Sending %s alert %d in context %u", alert->level == TLMSP_CFG_ACTION_ALERT_LEVEL_WARNING ? "warning" : "fatal", alert->description, context_id); if (!TLMSP_container_create_alert(ssl, &container, context_id, (alert->level << 8) | alert->description)) { demo_conn_print_error_ssl_errq(conn, "Failed to create container for alert"); return (false); } if (!container_queue_add(q, container)) { demo_conn_print_error(conn, "Failed to add alert container to queue"); TLMSP_container_free(ssl, container); return (false); } demo_conn_log(2, conn, "Sending %s alert %d in context %u", alert->level == TLMSP_CFG_ACTION_ALERT_LEVEL_WARNING ? "warning" : "fatal", alert->description, context_id); return (true); } static void demo_activity_time_triggered_cb(EV_P_ ev_timer *w, int revents) { Loading Loading @@ -1357,12 +1396,28 @@ demo_activity_apply_actions(struct demo_connection *activity_conn, if (!demo_activity_queue_payload(outbound_conn, &action->send, match_groups, activity->present)) return (false); } else if (action->alert.level != TLMSP_CFG_ACTION_ALERT_LEVEL_NONE) { if (!demo_activity_queue_alert(send_conn, &action->alert, activity->present)) return (false); } else if (action->renegotiate) { if (!SSL_renegotiate_abbreviated(activity_conn->ssl)) { demo_conn_print_error_ssl_errq(activity_conn, "Failed to schedule a renegotiation"); return (false); } } else if (action->shutdown) { /* * This will put the SSL into a state where our next * attempt to read a container will return the * appropriate WANT_WRITE, and we will transition into * flushing the write part of the BIO. Therefore, we * just ignore any error here. * * We could narrow it to just ignore the expected * errors. */ (void)SSL_shutdown(activity_conn->ssl); } } Loading libdemo/connection.c +27 −19 Original line number Diff line number Diff line Loading @@ -71,8 +71,11 @@ void demo_connection_shutdown(struct demo_connection *conn) { if (conn->is_connected) if (conn->is_connected && !conn->is_shut_down) { demo_conn_log(1, conn, "Shutting down writes"); shutdown(conn->socket, SHUT_WR); conn->is_shut_down = true; } } void Loading @@ -86,7 +89,8 @@ demo_connection_set_phase(struct demo_connection *conn, bool demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock, struct ev_loop *loop, demo_connection_failed_cb_t fail_cb, demo_connection_cb_t cb, int initial_events) demo_connection_connected_cb_t connected_cb, demo_connection_cb_t cb, int initial_events) { conn->ssl = SSL_new(ssl_ctx); Loading @@ -97,7 +101,7 @@ demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock conn->socket = sock; conn->loop = loop; conn->fail_cb = fail_cb; conn->cb_data = conn; conn->connected_cb = connected_cb; ev_io_init(&conn->connected_watcher, demo_conn_connected_cb, conn->socket, EV_WRITE); Loading @@ -116,7 +120,7 @@ demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock conn->queues_initialized = true; ev_io_init(&conn->watcher, cb, conn->socket, conn->wait_events); conn->watcher.data = conn->cb_data; conn->watcher.data = conn; return (true); } Loading @@ -126,6 +130,7 @@ demo_connection_start_io(struct demo_connection *conn) { struct ev_loop *loop = conn->loop; demo_connection_set_phase(conn, DEMO_CONNECTION_PHASE_HANDSHAKE); ev_io_start(EV_A_ &conn->connected_watcher); return (true); Loading @@ -137,20 +142,21 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) struct demo_connection *conn = w->data; socklen_t len; if (conn->connected_cb) conn->connected_cb(conn); len = sizeof(conn->local_name); if (getsockname(conn->socket, (struct sockaddr *)&conn->local_name, &len) == -1) { demo_conn_print_errno(conn, "Could not get local address"); conn->io_error = true; conn->fail_cb(conn->cb_data); conn->fail_cb(conn); return; } len = sizeof(conn->remote_name); if (getpeername(conn->socket, (struct sockaddr *)&conn->remote_name, &len) == -1) { demo_conn_print_errno(conn, "Could not get remote address"); conn->io_error = true; conn->fail_cb(conn->cb_data); conn->fail_cb(conn); return; } demo_conn_log_sockaddr(1, conn, "Local address is ", Loading @@ -158,13 +164,6 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) demo_conn_log_sockaddr(1, conn, "Remote address is ", (struct sockaddr *)&conn->remote_name); /* * XXX Once the client and server are structured to detect handshake * complete, this will move to that point in client/server. */ if (!conn->splice) demo_connection_handshake_complete(conn); conn->is_connected = true; ev_io_stop(EV_A_ &conn->connected_watcher); ev_io_start(EV_A_ &conn->watcher); Loading @@ -173,6 +172,14 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) bool demo_connection_handshake_complete(struct demo_connection *conn) { demo_connection_set_phase(conn, DEMO_CONNECTION_PHASE_APPLICATION); if (conn->initial_handshake_complete) return (true); conn->initial_handshake_complete = true; if (!demo_activity_conn_queue_initial(conn)) { demo_conn_print_error(conn, "Failed to queue initial send data for write"); Loading Loading @@ -283,7 +290,7 @@ void demo_connection_free(struct demo_connection *conn) { demo_conn_log(1, conn, "Shutting down"); demo_conn_log(1, conn, "Closing"); if (!conn->app->uses_splices) demo_app_remove_connection(conn->app, conn); Loading @@ -301,6 +308,7 @@ demo_connection_free(struct demo_connection *conn) demo_activity_conn_tear_down_time_triggered(conn); free(conn->activity_states); free(conn); } Loading libdemo/connection.h +9 −5 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ struct demo_app; struct demo_splice; struct tlmsp_cfg_activity; struct demo_connection; typedef void (*demo_connection_connected_cb_t)(struct demo_connection *conn); typedef void (*demo_connection_cb_t)(EV_P_ struct ev_io *w, int revents); typedef void (*demo_connection_failed_cb_t)(void *cb_data); typedef void (*demo_connection_free_cb_t)(void *); typedef void (*demo_connection_show_info_cb_t)(void *); typedef void (*demo_connection_failed_cb_t)(struct demo_connection *conn); typedef void (*demo_connection_free_cb_t)(void *app_data); typedef void (*demo_connection_show_info_cb_t)(void *app_data); enum demo_connection_phase { DEMO_CONNECTION_PHASE_UNKNOWN, Loading @@ -37,13 +39,14 @@ struct demo_connection { struct demo_app *app; void *app_data; demo_connection_failed_cb_t fail_cb; void *cb_data; demo_connection_connected_cb_t connected_cb; struct demo_splice *splice; /* only used by middlebox */ struct demo_connection *other_side; /* only used when there is a splice */ bool to_client; /* only used when there is a splice */ bool is_connected; bool initial_handshake_complete; bool is_shut_down; bool read_eof; /* read returned SSL_ERROR_ZERO_RETURN */ bool io_error; /* other than eof */ struct sockaddr_storage local_name; struct sockaddr_storage remote_name; uint64_t id; Loading Loading @@ -92,6 +95,7 @@ bool demo_connection_handshake_complete(struct demo_connection *conn); bool demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock, struct ev_loop *loop, demo_connection_failed_cb_t fail_cb, demo_connection_connected_cb_t connected_cb, demo_connection_cb_t cb, int initial_events); bool demo_connection_start_io(struct demo_connection *conn); void demo_connection_pause_io(struct demo_connection *conn); Loading Loading
Makefile.am +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ lib_LTLIBRARIES = \ libtlmsp_cfg_la_SOURCES = \ libtlmsp-cfg/api.c \ libtlmsp-cfg/format.c \ libtlmsp-cfg/openssl.c \ libtlmsp-cfg/parse.c \ libtlmsp-cfg/print.c libtlmsp_cfg_la_LIBADD = \ Loading Loading @@ -95,6 +96,7 @@ tlmsp_server_LDADD = \ pkginclude_HEADERS = \ libtlmsp-cfg/libtlmsp-cfg.h \ libtlmsp-cfg/libtlmsp-cfg-openssl.h \ libtlmsp-util/libtlmsp-util.h Loading
client/client.c +110 −57 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <inttypes.h> #include <libgen.h> #include <libtlmsp-cfg.h> #include <libtlmsp-cfg-openssl.h> #include <libtlmsp-util.h> #include <stdbool.h> #include <stdio.h> Loading Loading @@ -61,7 +62,8 @@ static void free_client_cb(void *app_data); static bool new_connection(struct client_state *client, const TLMSP_ReconnectState *reconnect_state); static void show_connection_info(void *app_data); static int validate_discovery_results(SSL *ssl, void *arg); static int validate_discovery_results(SSL *ssl, void *arg, TLMSP_Middleboxes *middleboxes); static void free_connection_cb(void *app_data); static void connection_died(struct demo_connection *conn); static void conn_cb(EV_P_ ev_io *w, int revents); Loading Loading @@ -240,7 +242,7 @@ new_connection(struct client_state *client, { struct connection_state *conn_state; struct demo_connection *conn; struct sockaddr *addr; struct sockaddr *addr = NULL; socklen_t addr_len; uint8_t *first_hop_addr = NULL; char *first_hop_addr_str; Loading Loading @@ -351,9 +353,11 @@ new_connection(struct client_state *client, demo_print_errno("Connect failed"); goto error; } free(addr); addr = NULL; if (!demo_connection_init_io(conn, client->ssl_ctx, sock, client->loop, (demo_connection_failed_cb_t)connection_died, conn_cb, EV_WRITE)) connection_died, NULL, conn_cb, EV_WRITE)) goto error; SSL_set_connect_state(conn->ssl); Loading @@ -366,7 +370,6 @@ new_connection(struct client_state *client, demo_print_error_ssl_errq("Failed to set reconnect state"); goto error; } TLMSP_reconnect_state_free(reconnect_state); } demo_connection_start_io(conn); Loading @@ -374,6 +377,7 @@ new_connection(struct client_state *client, return (true); error: free(addr); OPENSSL_free(first_hop_addr); demo_connection_free(conn); return (false); Loading @@ -394,23 +398,19 @@ free_connection_cb(void *app_data) struct connection_state *conn_state = app_data; TLMSP_reconnect_state_free(conn_state->reconnect_state); free(conn_state->read_buffer); free(conn_state); } static int validate_discovery_results(SSL *ssl, void *arg) validate_discovery_results(SSL *ssl, void *arg, TLMSP_Middleboxes *middleboxes) { struct demo_connection *conn = arg; const struct tlmsp_cfg *cfg = conn->app->cfg; TLMSP_Middleboxes *middleboxes; int result; middleboxes = TLMSP_get_middleboxes_instance(conn->ssl); if (middleboxes == NULL) return (0); result = tlmsp_cfg_validate_middlebox_list_client_openssl(cfg, middleboxes); TLMSP_middleboxes_free(middleboxes); return (result); } Loading Loading @@ -440,11 +440,67 @@ static void conn_cb(EV_P_ ev_io *w, int revents) { struct demo_connection *conn = w->data; struct connection_state *conn_state = conn->app_data; int result; int ssl_error; bool pending_writes; demo_connection_pause_io(conn); demo_connection_events_arrived(conn, revents); switch (conn->phase) { case DEMO_CONNECTION_PHASE_HANDSHAKE: result = SSL_connect(conn->ssl); switch (result) { case 0: demo_conn_print_error(conn, "Handshake terminated by protocol"); connection_died(conn); return; break; case 1: demo_conn_log(1, conn, "Handshake complete"); demo_connection_wait_for(conn, EV_READ); if (!demo_connection_handshake_complete(conn)) { connection_died(conn); return; } break; default: ssl_error = SSL_get_error(conn->ssl, result); switch (ssl_error) { case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); /* * Re-establish outbound connection and * re-enter handshake. */ conn_state->reconnect_state = TLMSP_get_reconnect_state(conn->ssl); if (conn_state->reconnect_state == NULL) demo_conn_print_error_ssl_errq(conn, "Reconnect state retrieval failed"); connection_died(conn); return; break; case SSL_ERROR_WANT_READ: demo_conn_log(5, conn, "SSL_ERROR_WANT_READ"); demo_connection_wait_for(conn, EV_READ); break; case SSL_ERROR_WANT_WRITE: demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; default: demo_conn_print_error_ssl(conn, ssl_error, "Handshake terminated due to fatal error"); connection_died(conn); return; break; } break; } break; case DEMO_CONNECTION_PHASE_APPLICATION: /* * The general approach is that we prioritize writes over * reads - we work on pending write data until it is all Loading Loading @@ -488,6 +544,14 @@ conn_cb(EV_P_ ev_io *w, int revents) */ if (demo_connection_wait_events(conn) == 0) demo_connection_wait_for(conn, EV_READ); break; default: demo_conn_print_error(conn, "Unexpected connection phase %d", conn->phase); connection_died(conn); return; break; } demo_connection_resume_io(conn); } Loading Loading @@ -546,7 +610,7 @@ read_containers(struct demo_connection *conn) } else if (!TLMSP_container_readable(container)) { demo_conn_print_error(conn, "Opaque container unexpectedly received in " "context %d using containe API", context_id); "context %d using container API", context_id); TLMSP_container_free(ssl, container); return (false); } else { Loading Loading @@ -577,12 +641,6 @@ read_containers(struct demo_connection *conn) demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); conn_state->reconnect_state = TLMSP_get_reconnect_state(ssl); result = false; break; default: demo_conn_print_error_ssl(conn, ssl_error, "Connection terminated due to fatal read error"); Loading Loading @@ -665,11 +723,6 @@ write_containers(struct demo_connection *conn) demo_conn_log(5, conn, "SSL_ERROR_WANT_WRITE"); demo_connection_wait_for(conn, EV_WRITE); break; case SSL_ERROR_WANT_RECONNECT: demo_conn_log(5, conn, "SSL_ERROR_WANT_RECONNECT"); conn_state->reconnect_state = TLMSP_get_reconnect_state(ssl); result = false; break; default: demo_conn_print_error_ssl(conn, ssl_error, "Connection terminated due to fatal write error"); Loading
libdemo/activity.c +56 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ struct match_groups { }; struct demo_activity_match_state { bool contexts[TLMSP_CONTEXT_ID_MAX + 1]; bool contexts[TLMSP_UTIL_CONTEXT_ID_LUT_SIZE]; struct tlmsp_cfg_activity *activity; struct container_queue_range match_range; size_t match_offset; Loading Loading @@ -95,6 +95,9 @@ static bool demo_activity_queue_payload(struct demo_connection *conn, struct tlmsp_cfg_payload *payload, struct match_groups *match_groups, bool present); static bool demo_activity_queue_alert(struct demo_connection *conn, struct tlmsp_cfg_alert *alert, bool present); static void demo_activity_time_triggered_cb(EV_P_ ev_timer *w, int revents); static bool demo_activity_get_payload_data(struct demo_connection *conn, struct tlmsp_cfg_payload *payload, Loading Loading @@ -351,6 +354,42 @@ demo_activity_queue_payload(struct demo_connection *conn, return (result); } static bool demo_activity_queue_alert(struct demo_connection *conn, struct tlmsp_cfg_alert *alert, bool present) { struct container_queue *q = &conn->write_queue; SSL *ssl = q->conn->ssl; TLMSP_Container *container; tlmsp_context_id_t context_id; context_id = alert->context ? alert->context->id : 0; if (present) demo_conn_present(conn, "Sending %s alert %d in context %u", alert->level == TLMSP_CFG_ACTION_ALERT_LEVEL_WARNING ? "warning" : "fatal", alert->description, context_id); if (!TLMSP_container_create_alert(ssl, &container, context_id, (alert->level << 8) | alert->description)) { demo_conn_print_error_ssl_errq(conn, "Failed to create container for alert"); return (false); } if (!container_queue_add(q, container)) { demo_conn_print_error(conn, "Failed to add alert container to queue"); TLMSP_container_free(ssl, container); return (false); } demo_conn_log(2, conn, "Sending %s alert %d in context %u", alert->level == TLMSP_CFG_ACTION_ALERT_LEVEL_WARNING ? "warning" : "fatal", alert->description, context_id); return (true); } static void demo_activity_time_triggered_cb(EV_P_ ev_timer *w, int revents) { Loading Loading @@ -1357,12 +1396,28 @@ demo_activity_apply_actions(struct demo_connection *activity_conn, if (!demo_activity_queue_payload(outbound_conn, &action->send, match_groups, activity->present)) return (false); } else if (action->alert.level != TLMSP_CFG_ACTION_ALERT_LEVEL_NONE) { if (!demo_activity_queue_alert(send_conn, &action->alert, activity->present)) return (false); } else if (action->renegotiate) { if (!SSL_renegotiate_abbreviated(activity_conn->ssl)) { demo_conn_print_error_ssl_errq(activity_conn, "Failed to schedule a renegotiation"); return (false); } } else if (action->shutdown) { /* * This will put the SSL into a state where our next * attempt to read a container will return the * appropriate WANT_WRITE, and we will transition into * flushing the write part of the BIO. Therefore, we * just ignore any error here. * * We could narrow it to just ignore the expected * errors. */ (void)SSL_shutdown(activity_conn->ssl); } } Loading
libdemo/connection.c +27 −19 Original line number Diff line number Diff line Loading @@ -71,8 +71,11 @@ void demo_connection_shutdown(struct demo_connection *conn) { if (conn->is_connected) if (conn->is_connected && !conn->is_shut_down) { demo_conn_log(1, conn, "Shutting down writes"); shutdown(conn->socket, SHUT_WR); conn->is_shut_down = true; } } void Loading @@ -86,7 +89,8 @@ demo_connection_set_phase(struct demo_connection *conn, bool demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock, struct ev_loop *loop, demo_connection_failed_cb_t fail_cb, demo_connection_cb_t cb, int initial_events) demo_connection_connected_cb_t connected_cb, demo_connection_cb_t cb, int initial_events) { conn->ssl = SSL_new(ssl_ctx); Loading @@ -97,7 +101,7 @@ demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock conn->socket = sock; conn->loop = loop; conn->fail_cb = fail_cb; conn->cb_data = conn; conn->connected_cb = connected_cb; ev_io_init(&conn->connected_watcher, demo_conn_connected_cb, conn->socket, EV_WRITE); Loading @@ -116,7 +120,7 @@ demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock conn->queues_initialized = true; ev_io_init(&conn->watcher, cb, conn->socket, conn->wait_events); conn->watcher.data = conn->cb_data; conn->watcher.data = conn; return (true); } Loading @@ -126,6 +130,7 @@ demo_connection_start_io(struct demo_connection *conn) { struct ev_loop *loop = conn->loop; demo_connection_set_phase(conn, DEMO_CONNECTION_PHASE_HANDSHAKE); ev_io_start(EV_A_ &conn->connected_watcher); return (true); Loading @@ -137,20 +142,21 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) struct demo_connection *conn = w->data; socklen_t len; if (conn->connected_cb) conn->connected_cb(conn); len = sizeof(conn->local_name); if (getsockname(conn->socket, (struct sockaddr *)&conn->local_name, &len) == -1) { demo_conn_print_errno(conn, "Could not get local address"); conn->io_error = true; conn->fail_cb(conn->cb_data); conn->fail_cb(conn); return; } len = sizeof(conn->remote_name); if (getpeername(conn->socket, (struct sockaddr *)&conn->remote_name, &len) == -1) { demo_conn_print_errno(conn, "Could not get remote address"); conn->io_error = true; conn->fail_cb(conn->cb_data); conn->fail_cb(conn); return; } demo_conn_log_sockaddr(1, conn, "Local address is ", Loading @@ -158,13 +164,6 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) demo_conn_log_sockaddr(1, conn, "Remote address is ", (struct sockaddr *)&conn->remote_name); /* * XXX Once the client and server are structured to detect handshake * complete, this will move to that point in client/server. */ if (!conn->splice) demo_connection_handshake_complete(conn); conn->is_connected = true; ev_io_stop(EV_A_ &conn->connected_watcher); ev_io_start(EV_A_ &conn->watcher); Loading @@ -173,6 +172,14 @@ demo_conn_connected_cb(EV_P_ ev_io *w, int revents) bool demo_connection_handshake_complete(struct demo_connection *conn) { demo_connection_set_phase(conn, DEMO_CONNECTION_PHASE_APPLICATION); if (conn->initial_handshake_complete) return (true); conn->initial_handshake_complete = true; if (!demo_activity_conn_queue_initial(conn)) { demo_conn_print_error(conn, "Failed to queue initial send data for write"); Loading Loading @@ -283,7 +290,7 @@ void demo_connection_free(struct demo_connection *conn) { demo_conn_log(1, conn, "Shutting down"); demo_conn_log(1, conn, "Closing"); if (!conn->app->uses_splices) demo_app_remove_connection(conn->app, conn); Loading @@ -301,6 +308,7 @@ demo_connection_free(struct demo_connection *conn) demo_activity_conn_tear_down_time_triggered(conn); free(conn->activity_states); free(conn); } Loading
libdemo/connection.h +9 −5 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ struct demo_app; struct demo_splice; struct tlmsp_cfg_activity; struct demo_connection; typedef void (*demo_connection_connected_cb_t)(struct demo_connection *conn); typedef void (*demo_connection_cb_t)(EV_P_ struct ev_io *w, int revents); typedef void (*demo_connection_failed_cb_t)(void *cb_data); typedef void (*demo_connection_free_cb_t)(void *); typedef void (*demo_connection_show_info_cb_t)(void *); typedef void (*demo_connection_failed_cb_t)(struct demo_connection *conn); typedef void (*demo_connection_free_cb_t)(void *app_data); typedef void (*demo_connection_show_info_cb_t)(void *app_data); enum demo_connection_phase { DEMO_CONNECTION_PHASE_UNKNOWN, Loading @@ -37,13 +39,14 @@ struct demo_connection { struct demo_app *app; void *app_data; demo_connection_failed_cb_t fail_cb; void *cb_data; demo_connection_connected_cb_t connected_cb; struct demo_splice *splice; /* only used by middlebox */ struct demo_connection *other_side; /* only used when there is a splice */ bool to_client; /* only used when there is a splice */ bool is_connected; bool initial_handshake_complete; bool is_shut_down; bool read_eof; /* read returned SSL_ERROR_ZERO_RETURN */ bool io_error; /* other than eof */ struct sockaddr_storage local_name; struct sockaddr_storage remote_name; uint64_t id; Loading Loading @@ -92,6 +95,7 @@ bool demo_connection_handshake_complete(struct demo_connection *conn); bool demo_connection_init_io(struct demo_connection *conn, SSL_CTX *ssl_ctx, int sock, struct ev_loop *loop, demo_connection_failed_cb_t fail_cb, demo_connection_connected_cb_t connected_cb, demo_connection_cb_t cb, int initial_events); bool demo_connection_start_io(struct demo_connection *conn); void demo_connection_pause_io(struct demo_connection *conn); Loading