1*e7be843bSPierre Pronchery /* 2*e7be843bSPierre Pronchery * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. 3*e7be843bSPierre Pronchery * 4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at 7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html 8*e7be843bSPierre Pronchery */ 9*e7be843bSPierre Pronchery #ifndef OSSL_QUIC_PORT_H 10*e7be843bSPierre Pronchery # define OSSL_QUIC_PORT_H 11*e7be843bSPierre Pronchery 12*e7be843bSPierre Pronchery # include <openssl/ssl.h> 13*e7be843bSPierre Pronchery # include "internal/quic_types.h" 14*e7be843bSPierre Pronchery # include "internal/quic_reactor.h" 15*e7be843bSPierre Pronchery # include "internal/quic_demux.h" 16*e7be843bSPierre Pronchery # include "internal/quic_predef.h" 17*e7be843bSPierre Pronchery # include "internal/thread_arch.h" 18*e7be843bSPierre Pronchery 19*e7be843bSPierre Pronchery # ifndef OPENSSL_NO_QUIC 20*e7be843bSPierre Pronchery 21*e7be843bSPierre Pronchery /* 22*e7be843bSPierre Pronchery * QUIC Port 23*e7be843bSPierre Pronchery * ========= 24*e7be843bSPierre Pronchery * 25*e7be843bSPierre Pronchery * A QUIC Port (QUIC_PORT) represents a single UDP network socket and contains 26*e7be843bSPierre Pronchery * zero or more subsidiary QUIC_CHANNEL instances, each of which represents a 27*e7be843bSPierre Pronchery * single QUIC connection. All QUIC_CHANNEL instances must belong to a 28*e7be843bSPierre Pronchery * QUIC_PORT. 29*e7be843bSPierre Pronchery * 30*e7be843bSPierre Pronchery * A QUIC port is responsible for managing a set of channels which all use the 31*e7be843bSPierre Pronchery * same UDP socket, and (in future) for automatically creating new channels when 32*e7be843bSPierre Pronchery * incoming connections are received. 33*e7be843bSPierre Pronchery * 34*e7be843bSPierre Pronchery * In order to retain compatibility with QUIC_TSERVER, it also supports a point 35*e7be843bSPierre Pronchery * of legacy compatibility where a caller can create an incoming (server role) 36*e7be843bSPierre Pronchery * channel and that channel will be automatically be bound to the next incoming 37*e7be843bSPierre Pronchery * connection. In the future this will go away once QUIC_TSERVER is removed. 38*e7be843bSPierre Pronchery * 39*e7be843bSPierre Pronchery * All QUIC_PORT instances are created by a QUIC_ENGINE. 40*e7be843bSPierre Pronchery */ 41*e7be843bSPierre Pronchery typedef struct quic_port_args_st { 42*e7be843bSPierre Pronchery /* The engine which the QUIC port is to be a child of. */ 43*e7be843bSPierre Pronchery QUIC_ENGINE *engine; 44*e7be843bSPierre Pronchery 45*e7be843bSPierre Pronchery /* 46*e7be843bSPierre Pronchery * This callback allows port_new_handshake_layer to pre-create a quic 47*e7be843bSPierre Pronchery * connection object for the incoming channel 48*e7be843bSPierre Pronchery * user_ssl_arg is expected to point to a quic listener object 49*e7be843bSPierre Pronchery */ 50*e7be843bSPierre Pronchery SSL *(*get_conn_user_ssl)(QUIC_CHANNEL *ch, void *arg); 51*e7be843bSPierre Pronchery void *user_ssl_arg; 52*e7be843bSPierre Pronchery 53*e7be843bSPierre Pronchery /* 54*e7be843bSPierre Pronchery * This SSL_CTX will be used when constructing the handshake layer object 55*e7be843bSPierre Pronchery * inside newly created channels. 56*e7be843bSPierre Pronchery */ 57*e7be843bSPierre Pronchery SSL_CTX *channel_ctx; 58*e7be843bSPierre Pronchery 59*e7be843bSPierre Pronchery /* 60*e7be843bSPierre Pronchery * If 1, this port is to be used for multiple connections, so 61*e7be843bSPierre Pronchery * non-zero-length CIDs should be used. If 0, this port will only be used 62*e7be843bSPierre Pronchery * for a single connection, so a zero-length local CID can be used. 63*e7be843bSPierre Pronchery */ 64*e7be843bSPierre Pronchery int is_multi_conn; 65*e7be843bSPierre Pronchery 66*e7be843bSPierre Pronchery /* 67*e7be843bSPierre Pronchery * if 1, this port should do server address validation 68*e7be843bSPierre Pronchery */ 69*e7be843bSPierre Pronchery int do_addr_validation; 70*e7be843bSPierre Pronchery } QUIC_PORT_ARGS; 71*e7be843bSPierre Pronchery 72*e7be843bSPierre Pronchery /* Only QUIC_ENGINE should use this function. */ 73*e7be843bSPierre Pronchery QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args); 74*e7be843bSPierre Pronchery 75*e7be843bSPierre Pronchery void ossl_quic_port_free(QUIC_PORT *port); 76*e7be843bSPierre Pronchery 77*e7be843bSPierre Pronchery /* 78*e7be843bSPierre Pronchery * Operations 79*e7be843bSPierre Pronchery * ========== 80*e7be843bSPierre Pronchery */ 81*e7be843bSPierre Pronchery 82*e7be843bSPierre Pronchery /* Create an outgoing channel using this port. */ 83*e7be843bSPierre Pronchery QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls); 84*e7be843bSPierre Pronchery 85*e7be843bSPierre Pronchery /* 86*e7be843bSPierre Pronchery * Create an incoming channel using this port. 87*e7be843bSPierre Pronchery * 88*e7be843bSPierre Pronchery * TODO(QUIC FUTURE): temporary TSERVER use only - will be removed. 89*e7be843bSPierre Pronchery */ 90*e7be843bSPierre Pronchery QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls); 91*e7be843bSPierre Pronchery 92*e7be843bSPierre Pronchery /* 93*e7be843bSPierre Pronchery * Pop an incoming channel from the incoming channel queue. Returns NULL if 94*e7be843bSPierre Pronchery * there are no pending incoming channels. 95*e7be843bSPierre Pronchery */ 96*e7be843bSPierre Pronchery QUIC_CHANNEL *ossl_quic_port_pop_incoming(QUIC_PORT *port); 97*e7be843bSPierre Pronchery 98*e7be843bSPierre Pronchery /* Returns 1 if there is at least one connection incoming. */ 99*e7be843bSPierre Pronchery int ossl_quic_port_have_incoming(QUIC_PORT *port); 100*e7be843bSPierre Pronchery 101*e7be843bSPierre Pronchery /* 102*e7be843bSPierre Pronchery * Delete any channels which are pending acceptance. 103*e7be843bSPierre Pronchery */ 104*e7be843bSPierre Pronchery void ossl_quic_port_drop_incoming(QUIC_PORT *port); 105*e7be843bSPierre Pronchery 106*e7be843bSPierre Pronchery /* 107*e7be843bSPierre Pronchery * Queries and Accessors 108*e7be843bSPierre Pronchery * ===================== 109*e7be843bSPierre Pronchery */ 110*e7be843bSPierre Pronchery 111*e7be843bSPierre Pronchery /* Gets/sets the underlying network read and write BIO. */ 112*e7be843bSPierre Pronchery BIO *ossl_quic_port_get_net_rbio(QUIC_PORT *port); 113*e7be843bSPierre Pronchery BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port); 114*e7be843bSPierre Pronchery int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio); 115*e7be843bSPierre Pronchery int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio); 116*e7be843bSPierre Pronchery SSL_CTX *ossl_quic_port_get_channel_ctx(QUIC_PORT *port); 117*e7be843bSPierre Pronchery 118*e7be843bSPierre Pronchery /* 119*e7be843bSPierre Pronchery * Re-poll the network BIOs already set to determine if their support for 120*e7be843bSPierre Pronchery * polling has changed. If force is 0, only check again if the BIOs have been 121*e7be843bSPierre Pronchery * changed. 122*e7be843bSPierre Pronchery */ 123*e7be843bSPierre Pronchery int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port, int force); 124*e7be843bSPierre Pronchery 125*e7be843bSPierre Pronchery /* Gets the engine which this port is a child of. */ 126*e7be843bSPierre Pronchery QUIC_ENGINE *ossl_quic_port_get0_engine(QUIC_PORT *port); 127*e7be843bSPierre Pronchery 128*e7be843bSPierre Pronchery /* Gets the reactor which can be used to tick/poll on the port. */ 129*e7be843bSPierre Pronchery QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port); 130*e7be843bSPierre Pronchery 131*e7be843bSPierre Pronchery /* Gets the demuxer belonging to the port. */ 132*e7be843bSPierre Pronchery QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port); 133*e7be843bSPierre Pronchery 134*e7be843bSPierre Pronchery /* Gets the mutex used by the port. */ 135*e7be843bSPierre Pronchery CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port); 136*e7be843bSPierre Pronchery 137*e7be843bSPierre Pronchery /* Gets the current time. */ 138*e7be843bSPierre Pronchery OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port); 139*e7be843bSPierre Pronchery 140*e7be843bSPierre Pronchery int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port); 141*e7be843bSPierre Pronchery int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port); 142*e7be843bSPierre Pronchery 143*e7be843bSPierre Pronchery /* Returns 1 if the port is running/healthy, 0 if it has failed. */ 144*e7be843bSPierre Pronchery int ossl_quic_port_is_running(const QUIC_PORT *port); 145*e7be843bSPierre Pronchery 146*e7be843bSPierre Pronchery /* 147*e7be843bSPierre Pronchery * Restores port-level error to the error stack. To be called only if 148*e7be843bSPierre Pronchery * the port is no longer running. 149*e7be843bSPierre Pronchery */ 150*e7be843bSPierre Pronchery void ossl_quic_port_restore_err_state(const QUIC_PORT *port); 151*e7be843bSPierre Pronchery 152*e7be843bSPierre Pronchery /* For use by QUIC_ENGINE. You should not need to call this directly. */ 153*e7be843bSPierre Pronchery void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *r, 154*e7be843bSPierre Pronchery uint32_t flags); 155*e7be843bSPierre Pronchery 156*e7be843bSPierre Pronchery /* Returns the number of queued incoming channels. */ 157*e7be843bSPierre Pronchery size_t ossl_quic_port_get_num_incoming_channels(const QUIC_PORT *port); 158*e7be843bSPierre Pronchery 159*e7be843bSPierre Pronchery /* Sets if incoming connections should currently be allowed. */ 160*e7be843bSPierre Pronchery void ossl_quic_port_set_allow_incoming(QUIC_PORT *port, int allow_incoming); 161*e7be843bSPierre Pronchery 162*e7be843bSPierre Pronchery /* Returns 1 if we are using addressed mode on the read side. */ 163*e7be843bSPierre Pronchery int ossl_quic_port_is_addressed_r(const QUIC_PORT *port); 164*e7be843bSPierre Pronchery 165*e7be843bSPierre Pronchery /* Returns 1 if we are using addressed mode on the write side. */ 166*e7be843bSPierre Pronchery int ossl_quic_port_is_addressed_w(const QUIC_PORT *port); 167*e7be843bSPierre Pronchery 168*e7be843bSPierre Pronchery /* Returns 1 if we are using addressed mode. */ 169*e7be843bSPierre Pronchery int ossl_quic_port_is_addressed(const QUIC_PORT *port); 170*e7be843bSPierre Pronchery 171*e7be843bSPierre Pronchery /* 172*e7be843bSPierre Pronchery * Returns the current network BIO epoch. This increments whenever the network 173*e7be843bSPierre Pronchery * BIO configuration changes. 174*e7be843bSPierre Pronchery */ 175*e7be843bSPierre Pronchery uint64_t ossl_quic_port_get_net_bio_epoch(const QUIC_PORT *port); 176*e7be843bSPierre Pronchery 177*e7be843bSPierre Pronchery /* 178*e7be843bSPierre Pronchery * Events 179*e7be843bSPierre Pronchery * ====== 180*e7be843bSPierre Pronchery */ 181*e7be843bSPierre Pronchery 182*e7be843bSPierre Pronchery /* 183*e7be843bSPierre Pronchery * Called if a permanent network error occurs. Terminates all channels 184*e7be843bSPierre Pronchery * immediately. triggering_ch is an optional argument designating 185*e7be843bSPierre Pronchery * a channel which encountered the network error. 186*e7be843bSPierre Pronchery */ 187*e7be843bSPierre Pronchery void ossl_quic_port_raise_net_error(QUIC_PORT *port, 188*e7be843bSPierre Pronchery QUIC_CHANNEL *triggering_ch); 189*e7be843bSPierre Pronchery 190*e7be843bSPierre Pronchery # endif 191*e7be843bSPierre Pronchery 192*e7be843bSPierre Pronchery #endif 193