11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* This must be the first #include file */ 111cb0ef41Sopenharmony_ci#include "async_local.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include <openssl/err.h> 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void) 161cb0ef41Sopenharmony_ci{ 171cb0ef41Sopenharmony_ci return OPENSSL_zalloc(sizeof(ASYNC_WAIT_CTX)); 181cb0ef41Sopenharmony_ci} 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_civoid ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx) 211cb0ef41Sopenharmony_ci{ 221cb0ef41Sopenharmony_ci struct fd_lookup_st *curr; 231cb0ef41Sopenharmony_ci struct fd_lookup_st *next; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci if (ctx == NULL) 261cb0ef41Sopenharmony_ci return; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci curr = ctx->fds; 291cb0ef41Sopenharmony_ci while (curr != NULL) { 301cb0ef41Sopenharmony_ci if (!curr->del) { 311cb0ef41Sopenharmony_ci /* Only try and cleanup if it hasn't been marked deleted */ 321cb0ef41Sopenharmony_ci if (curr->cleanup != NULL) 331cb0ef41Sopenharmony_ci curr->cleanup(ctx, curr->key, curr->fd, curr->custom_data); 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci /* Always free the fd_lookup_st */ 361cb0ef41Sopenharmony_ci next = curr->next; 371cb0ef41Sopenharmony_ci OPENSSL_free(curr); 381cb0ef41Sopenharmony_ci curr = next; 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci OPENSSL_free(ctx); 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, 441cb0ef41Sopenharmony_ci OSSL_ASYNC_FD fd, void *custom_data, 451cb0ef41Sopenharmony_ci void (*cleanup)(ASYNC_WAIT_CTX *, const void *, 461cb0ef41Sopenharmony_ci OSSL_ASYNC_FD, void *)) 471cb0ef41Sopenharmony_ci{ 481cb0ef41Sopenharmony_ci struct fd_lookup_st *fdlookup; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) { 511cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 521cb0ef41Sopenharmony_ci return 0; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci fdlookup->key = key; 561cb0ef41Sopenharmony_ci fdlookup->fd = fd; 571cb0ef41Sopenharmony_ci fdlookup->custom_data = custom_data; 581cb0ef41Sopenharmony_ci fdlookup->cleanup = cleanup; 591cb0ef41Sopenharmony_ci fdlookup->add = 1; 601cb0ef41Sopenharmony_ci fdlookup->next = ctx->fds; 611cb0ef41Sopenharmony_ci ctx->fds = fdlookup; 621cb0ef41Sopenharmony_ci ctx->numadd++; 631cb0ef41Sopenharmony_ci return 1; 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, 671cb0ef41Sopenharmony_ci OSSL_ASYNC_FD *fd, void **custom_data) 681cb0ef41Sopenharmony_ci{ 691cb0ef41Sopenharmony_ci struct fd_lookup_st *curr; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci curr = ctx->fds; 721cb0ef41Sopenharmony_ci while (curr != NULL) { 731cb0ef41Sopenharmony_ci if (curr->del) { 741cb0ef41Sopenharmony_ci /* This one has been marked deleted so do nothing */ 751cb0ef41Sopenharmony_ci curr = curr->next; 761cb0ef41Sopenharmony_ci continue; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci if (curr->key == key) { 791cb0ef41Sopenharmony_ci *fd = curr->fd; 801cb0ef41Sopenharmony_ci *custom_data = curr->custom_data; 811cb0ef41Sopenharmony_ci return 1; 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci curr = curr->next; 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci return 0; 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, 891cb0ef41Sopenharmony_ci size_t *numfds) 901cb0ef41Sopenharmony_ci{ 911cb0ef41Sopenharmony_ci struct fd_lookup_st *curr; 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci curr = ctx->fds; 941cb0ef41Sopenharmony_ci *numfds = 0; 951cb0ef41Sopenharmony_ci while (curr != NULL) { 961cb0ef41Sopenharmony_ci if (curr->del) { 971cb0ef41Sopenharmony_ci /* This one has been marked deleted so do nothing */ 981cb0ef41Sopenharmony_ci curr = curr->next; 991cb0ef41Sopenharmony_ci continue; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci if (fd != NULL) { 1021cb0ef41Sopenharmony_ci *fd = curr->fd; 1031cb0ef41Sopenharmony_ci fd++; 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci (*numfds)++; 1061cb0ef41Sopenharmony_ci curr = curr->next; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci return 1; 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, 1121cb0ef41Sopenharmony_ci size_t *numaddfds, OSSL_ASYNC_FD *delfd, 1131cb0ef41Sopenharmony_ci size_t *numdelfds) 1141cb0ef41Sopenharmony_ci{ 1151cb0ef41Sopenharmony_ci struct fd_lookup_st *curr; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci *numaddfds = ctx->numadd; 1181cb0ef41Sopenharmony_ci *numdelfds = ctx->numdel; 1191cb0ef41Sopenharmony_ci if (addfd == NULL && delfd == NULL) 1201cb0ef41Sopenharmony_ci return 1; 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci curr = ctx->fds; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci while (curr != NULL) { 1251cb0ef41Sopenharmony_ci /* We ignore fds that have been marked as both added and deleted */ 1261cb0ef41Sopenharmony_ci if (curr->del && !curr->add && (delfd != NULL)) { 1271cb0ef41Sopenharmony_ci *delfd = curr->fd; 1281cb0ef41Sopenharmony_ci delfd++; 1291cb0ef41Sopenharmony_ci } 1301cb0ef41Sopenharmony_ci if (curr->add && !curr->del && (addfd != NULL)) { 1311cb0ef41Sopenharmony_ci *addfd = curr->fd; 1321cb0ef41Sopenharmony_ci addfd++; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci curr = curr->next; 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci return 1; 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key) 1411cb0ef41Sopenharmony_ci{ 1421cb0ef41Sopenharmony_ci struct fd_lookup_st *curr, *prev; 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci curr = ctx->fds; 1451cb0ef41Sopenharmony_ci prev = NULL; 1461cb0ef41Sopenharmony_ci while (curr != NULL) { 1471cb0ef41Sopenharmony_ci if (curr->del == 1) { 1481cb0ef41Sopenharmony_ci /* This one has been marked deleted already so do nothing */ 1491cb0ef41Sopenharmony_ci prev = curr; 1501cb0ef41Sopenharmony_ci curr = curr->next; 1511cb0ef41Sopenharmony_ci continue; 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci if (curr->key == key) { 1541cb0ef41Sopenharmony_ci /* If fd has just been added, remove it from the list */ 1551cb0ef41Sopenharmony_ci if (curr->add == 1) { 1561cb0ef41Sopenharmony_ci if (ctx->fds == curr) { 1571cb0ef41Sopenharmony_ci ctx->fds = curr->next; 1581cb0ef41Sopenharmony_ci } else { 1591cb0ef41Sopenharmony_ci prev->next = curr->next; 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci /* It is responsibility of the caller to cleanup before calling 1631cb0ef41Sopenharmony_ci * ASYNC_WAIT_CTX_clear_fd 1641cb0ef41Sopenharmony_ci */ 1651cb0ef41Sopenharmony_ci OPENSSL_free(curr); 1661cb0ef41Sopenharmony_ci ctx->numadd--; 1671cb0ef41Sopenharmony_ci return 1; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci /* 1711cb0ef41Sopenharmony_ci * Mark it as deleted. We don't call cleanup if explicitly asked 1721cb0ef41Sopenharmony_ci * to clear an fd. We assume the caller is going to do that (if 1731cb0ef41Sopenharmony_ci * appropriate). 1741cb0ef41Sopenharmony_ci */ 1751cb0ef41Sopenharmony_ci curr->del = 1; 1761cb0ef41Sopenharmony_ci ctx->numdel++; 1771cb0ef41Sopenharmony_ci return 1; 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci prev = curr; 1801cb0ef41Sopenharmony_ci curr = curr->next; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci return 0; 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx, 1861cb0ef41Sopenharmony_ci ASYNC_callback_fn callback, 1871cb0ef41Sopenharmony_ci void *callback_arg) 1881cb0ef41Sopenharmony_ci{ 1891cb0ef41Sopenharmony_ci if (ctx == NULL) 1901cb0ef41Sopenharmony_ci return 0; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci ctx->callback = callback; 1931cb0ef41Sopenharmony_ci ctx->callback_arg = callback_arg; 1941cb0ef41Sopenharmony_ci return 1; 1951cb0ef41Sopenharmony_ci} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx, 1981cb0ef41Sopenharmony_ci ASYNC_callback_fn *callback, 1991cb0ef41Sopenharmony_ci void **callback_arg) 2001cb0ef41Sopenharmony_ci{ 2011cb0ef41Sopenharmony_ci if (ctx->callback == NULL) 2021cb0ef41Sopenharmony_ci return 0; 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci *callback = ctx->callback; 2051cb0ef41Sopenharmony_ci *callback_arg = ctx->callback_arg; 2061cb0ef41Sopenharmony_ci return 1; 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status) 2101cb0ef41Sopenharmony_ci{ 2111cb0ef41Sopenharmony_ci ctx->status = status; 2121cb0ef41Sopenharmony_ci return 1; 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ciint ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx) 2161cb0ef41Sopenharmony_ci{ 2171cb0ef41Sopenharmony_ci return ctx->status; 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_civoid async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx) 2211cb0ef41Sopenharmony_ci{ 2221cb0ef41Sopenharmony_ci struct fd_lookup_st *curr, *prev = NULL; 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci ctx->numadd = 0; 2251cb0ef41Sopenharmony_ci ctx->numdel = 0; 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci curr = ctx->fds; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci while (curr != NULL) { 2301cb0ef41Sopenharmony_ci if (curr->del) { 2311cb0ef41Sopenharmony_ci if (prev == NULL) 2321cb0ef41Sopenharmony_ci ctx->fds = curr->next; 2331cb0ef41Sopenharmony_ci else 2341cb0ef41Sopenharmony_ci prev->next = curr->next; 2351cb0ef41Sopenharmony_ci OPENSSL_free(curr); 2361cb0ef41Sopenharmony_ci if (prev == NULL) 2371cb0ef41Sopenharmony_ci curr = ctx->fds; 2381cb0ef41Sopenharmony_ci else 2391cb0ef41Sopenharmony_ci curr = prev->next; 2401cb0ef41Sopenharmony_ci continue; 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci if (curr->add) { 2431cb0ef41Sopenharmony_ci curr->add = 0; 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci prev = curr; 2461cb0ef41Sopenharmony_ci curr = curr->next; 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci} 249