1 /* 2 * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "quic_obj_local.h" 11 #include "quic_local.h" 12 #include "internal/ssl_unwrap.h" 13 14 static int obj_update_cache(QUIC_OBJ *obj); 15 16 int ossl_quic_obj_init(QUIC_OBJ *obj, 17 SSL_CTX *ctx, 18 int type, 19 SSL *parent_obj, 20 QUIC_ENGINE *engine, 21 QUIC_PORT *port) 22 { 23 int is_event_leader = (engine != NULL); 24 int is_port_leader = (port != NULL); 25 26 if (!ossl_assert(obj != NULL && !obj->init_done && SSL_TYPE_IS_QUIC(type) 27 && (parent_obj == NULL || IS_QUIC(parent_obj)))) 28 return 0; 29 30 /* Event leader is always the root object. */ 31 if (!ossl_assert(!is_event_leader || parent_obj == NULL)) 32 return 0; 33 34 if (!ossl_ssl_init(&obj->ssl, ctx, ctx->method, type)) 35 goto err; 36 37 obj->domain_flags = ctx->domain_flags; 38 obj->parent_obj = (QUIC_OBJ *)parent_obj; 39 obj->is_event_leader = is_event_leader; 40 obj->is_port_leader = is_port_leader; 41 obj->engine = engine; 42 obj->port = port; 43 obj->req_blocking_mode = QUIC_BLOCKING_MODE_INHERIT; 44 if (!obj_update_cache(obj)) 45 goto err; 46 47 obj->init_done = 1; 48 return 1; 49 50 err: 51 obj->is_event_leader = 0; 52 obj->is_port_leader = 0; 53 return 0; 54 } 55 56 static int obj_update_cache(QUIC_OBJ *obj) 57 { 58 QUIC_OBJ *p; 59 60 for (p = obj; p != NULL && !p->is_event_leader; 61 p = p->parent_obj) 62 if (!ossl_assert(p == obj || p->init_done)) 63 return 0; 64 65 if (!ossl_assert(p != NULL)) 66 return 0; 67 68 /* 69 * Offset of ->ssl is guaranteed to be 0 but the NULL check makes ubsan 70 * happy. 71 */ 72 obj->cached_event_leader = p; 73 obj->engine = p->engine; 74 75 for (p = obj; p != NULL && !p->is_port_leader; 76 p = p->parent_obj); 77 78 obj->cached_port_leader = p; 79 obj->port = (p != NULL) ? p->port : NULL; 80 return 1; 81 } 82 83 SSL_CONNECTION *ossl_quic_obj_get0_handshake_layer(QUIC_OBJ *obj) 84 { 85 assert(obj != NULL && obj->init_done); 86 87 if (obj->ssl.type != SSL_TYPE_QUIC_CONNECTION) 88 return NULL; 89 90 return SSL_CONNECTION_FROM_SSL_ONLY(((QUIC_CONNECTION *)obj)->tls); 91 } 92 93 /* (Returns a cached result.) */ 94 int ossl_quic_obj_can_support_blocking(const QUIC_OBJ *obj) 95 { 96 QUIC_REACTOR *rtor; 97 98 assert(obj != NULL); 99 rtor = ossl_quic_obj_get0_reactor(obj); 100 101 if ((obj->domain_flags 102 & (SSL_DOMAIN_FLAG_LEGACY_BLOCKING | SSL_DOMAIN_FLAG_BLOCKING)) == 0) 103 return 0; 104 105 return ossl_quic_reactor_can_poll_r(rtor) 106 || ossl_quic_reactor_can_poll_w(rtor); 107 } 108 109 int ossl_quic_obj_desires_blocking(const QUIC_OBJ *obj) 110 { 111 unsigned int req_blocking_mode; 112 113 assert(obj != NULL); 114 for (; (req_blocking_mode = obj->req_blocking_mode) == QUIC_BLOCKING_MODE_INHERIT 115 && obj->parent_obj != NULL; obj = obj->parent_obj); 116 117 return req_blocking_mode != QUIC_BLOCKING_MODE_NONBLOCKING; 118 } 119 120 int ossl_quic_obj_blocking(const QUIC_OBJ *obj) 121 { 122 assert(obj != NULL); 123 124 if (!ossl_quic_obj_desires_blocking(obj)) 125 return 0; 126 127 ossl_quic_engine_update_poll_descriptors(ossl_quic_obj_get0_engine(obj), 128 /*force=*/0); 129 return ossl_quic_obj_can_support_blocking(obj); 130 } 131 132 void ossl_quic_obj_set_blocking_mode(QUIC_OBJ *obj, unsigned int mode) 133 { 134 assert(obj != NULL); 135 136 obj->req_blocking_mode = mode; 137 } 138