1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* This must be the first #include file */ 11e1051a39Sopenharmony_ci#include "async_local.h" 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <openssl/err.h> 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ciASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void) 16e1051a39Sopenharmony_ci{ 17e1051a39Sopenharmony_ci return OPENSSL_zalloc(sizeof(ASYNC_WAIT_CTX)); 18e1051a39Sopenharmony_ci} 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_civoid ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx) 21e1051a39Sopenharmony_ci{ 22e1051a39Sopenharmony_ci struct fd_lookup_st *curr; 23e1051a39Sopenharmony_ci struct fd_lookup_st *next; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci if (ctx == NULL) 26e1051a39Sopenharmony_ci return; 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ci curr = ctx->fds; 29e1051a39Sopenharmony_ci while (curr != NULL) { 30e1051a39Sopenharmony_ci if (!curr->del) { 31e1051a39Sopenharmony_ci /* Only try and cleanup if it hasn't been marked deleted */ 32e1051a39Sopenharmony_ci if (curr->cleanup != NULL) 33e1051a39Sopenharmony_ci curr->cleanup(ctx, curr->key, curr->fd, curr->custom_data); 34e1051a39Sopenharmony_ci } 35e1051a39Sopenharmony_ci /* Always free the fd_lookup_st */ 36e1051a39Sopenharmony_ci next = curr->next; 37e1051a39Sopenharmony_ci OPENSSL_free(curr); 38e1051a39Sopenharmony_ci curr = next; 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_ci OPENSSL_free(ctx); 42e1051a39Sopenharmony_ci} 43e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, 44e1051a39Sopenharmony_ci OSSL_ASYNC_FD fd, void *custom_data, 45e1051a39Sopenharmony_ci void (*cleanup)(ASYNC_WAIT_CTX *, const void *, 46e1051a39Sopenharmony_ci OSSL_ASYNC_FD, void *)) 47e1051a39Sopenharmony_ci{ 48e1051a39Sopenharmony_ci struct fd_lookup_st *fdlookup; 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) { 51e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 52e1051a39Sopenharmony_ci return 0; 53e1051a39Sopenharmony_ci } 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci fdlookup->key = key; 56e1051a39Sopenharmony_ci fdlookup->fd = fd; 57e1051a39Sopenharmony_ci fdlookup->custom_data = custom_data; 58e1051a39Sopenharmony_ci fdlookup->cleanup = cleanup; 59e1051a39Sopenharmony_ci fdlookup->add = 1; 60e1051a39Sopenharmony_ci fdlookup->next = ctx->fds; 61e1051a39Sopenharmony_ci ctx->fds = fdlookup; 62e1051a39Sopenharmony_ci ctx->numadd++; 63e1051a39Sopenharmony_ci return 1; 64e1051a39Sopenharmony_ci} 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, 67e1051a39Sopenharmony_ci OSSL_ASYNC_FD *fd, void **custom_data) 68e1051a39Sopenharmony_ci{ 69e1051a39Sopenharmony_ci struct fd_lookup_st *curr; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci curr = ctx->fds; 72e1051a39Sopenharmony_ci while (curr != NULL) { 73e1051a39Sopenharmony_ci if (curr->del) { 74e1051a39Sopenharmony_ci /* This one has been marked deleted so do nothing */ 75e1051a39Sopenharmony_ci curr = curr->next; 76e1051a39Sopenharmony_ci continue; 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci if (curr->key == key) { 79e1051a39Sopenharmony_ci *fd = curr->fd; 80e1051a39Sopenharmony_ci *custom_data = curr->custom_data; 81e1051a39Sopenharmony_ci return 1; 82e1051a39Sopenharmony_ci } 83e1051a39Sopenharmony_ci curr = curr->next; 84e1051a39Sopenharmony_ci } 85e1051a39Sopenharmony_ci return 0; 86e1051a39Sopenharmony_ci} 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, 89e1051a39Sopenharmony_ci size_t *numfds) 90e1051a39Sopenharmony_ci{ 91e1051a39Sopenharmony_ci struct fd_lookup_st *curr; 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci curr = ctx->fds; 94e1051a39Sopenharmony_ci *numfds = 0; 95e1051a39Sopenharmony_ci while (curr != NULL) { 96e1051a39Sopenharmony_ci if (curr->del) { 97e1051a39Sopenharmony_ci /* This one has been marked deleted so do nothing */ 98e1051a39Sopenharmony_ci curr = curr->next; 99e1051a39Sopenharmony_ci continue; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci if (fd != NULL) { 102e1051a39Sopenharmony_ci *fd = curr->fd; 103e1051a39Sopenharmony_ci fd++; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci (*numfds)++; 106e1051a39Sopenharmony_ci curr = curr->next; 107e1051a39Sopenharmony_ci } 108e1051a39Sopenharmony_ci return 1; 109e1051a39Sopenharmony_ci} 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, 112e1051a39Sopenharmony_ci size_t *numaddfds, OSSL_ASYNC_FD *delfd, 113e1051a39Sopenharmony_ci size_t *numdelfds) 114e1051a39Sopenharmony_ci{ 115e1051a39Sopenharmony_ci struct fd_lookup_st *curr; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci *numaddfds = ctx->numadd; 118e1051a39Sopenharmony_ci *numdelfds = ctx->numdel; 119e1051a39Sopenharmony_ci if (addfd == NULL && delfd == NULL) 120e1051a39Sopenharmony_ci return 1; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci curr = ctx->fds; 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci while (curr != NULL) { 125e1051a39Sopenharmony_ci /* We ignore fds that have been marked as both added and deleted */ 126e1051a39Sopenharmony_ci if (curr->del && !curr->add && (delfd != NULL)) { 127e1051a39Sopenharmony_ci *delfd = curr->fd; 128e1051a39Sopenharmony_ci delfd++; 129e1051a39Sopenharmony_ci } 130e1051a39Sopenharmony_ci if (curr->add && !curr->del && (addfd != NULL)) { 131e1051a39Sopenharmony_ci *addfd = curr->fd; 132e1051a39Sopenharmony_ci addfd++; 133e1051a39Sopenharmony_ci } 134e1051a39Sopenharmony_ci curr = curr->next; 135e1051a39Sopenharmony_ci } 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci return 1; 138e1051a39Sopenharmony_ci} 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key) 141e1051a39Sopenharmony_ci{ 142e1051a39Sopenharmony_ci struct fd_lookup_st *curr, *prev; 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci curr = ctx->fds; 145e1051a39Sopenharmony_ci prev = NULL; 146e1051a39Sopenharmony_ci while (curr != NULL) { 147e1051a39Sopenharmony_ci if (curr->del == 1) { 148e1051a39Sopenharmony_ci /* This one has been marked deleted already so do nothing */ 149e1051a39Sopenharmony_ci prev = curr; 150e1051a39Sopenharmony_ci curr = curr->next; 151e1051a39Sopenharmony_ci continue; 152e1051a39Sopenharmony_ci } 153e1051a39Sopenharmony_ci if (curr->key == key) { 154e1051a39Sopenharmony_ci /* If fd has just been added, remove it from the list */ 155e1051a39Sopenharmony_ci if (curr->add == 1) { 156e1051a39Sopenharmony_ci if (ctx->fds == curr) { 157e1051a39Sopenharmony_ci ctx->fds = curr->next; 158e1051a39Sopenharmony_ci } else { 159e1051a39Sopenharmony_ci prev->next = curr->next; 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci /* It is responsibility of the caller to cleanup before calling 163e1051a39Sopenharmony_ci * ASYNC_WAIT_CTX_clear_fd 164e1051a39Sopenharmony_ci */ 165e1051a39Sopenharmony_ci OPENSSL_free(curr); 166e1051a39Sopenharmony_ci ctx->numadd--; 167e1051a39Sopenharmony_ci return 1; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci /* 171e1051a39Sopenharmony_ci * Mark it as deleted. We don't call cleanup if explicitly asked 172e1051a39Sopenharmony_ci * to clear an fd. We assume the caller is going to do that (if 173e1051a39Sopenharmony_ci * appropriate). 174e1051a39Sopenharmony_ci */ 175e1051a39Sopenharmony_ci curr->del = 1; 176e1051a39Sopenharmony_ci ctx->numdel++; 177e1051a39Sopenharmony_ci return 1; 178e1051a39Sopenharmony_ci } 179e1051a39Sopenharmony_ci prev = curr; 180e1051a39Sopenharmony_ci curr = curr->next; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci return 0; 183e1051a39Sopenharmony_ci} 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx, 186e1051a39Sopenharmony_ci ASYNC_callback_fn callback, 187e1051a39Sopenharmony_ci void *callback_arg) 188e1051a39Sopenharmony_ci{ 189e1051a39Sopenharmony_ci if (ctx == NULL) 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci ctx->callback = callback; 193e1051a39Sopenharmony_ci ctx->callback_arg = callback_arg; 194e1051a39Sopenharmony_ci return 1; 195e1051a39Sopenharmony_ci} 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx, 198e1051a39Sopenharmony_ci ASYNC_callback_fn *callback, 199e1051a39Sopenharmony_ci void **callback_arg) 200e1051a39Sopenharmony_ci{ 201e1051a39Sopenharmony_ci if (ctx->callback == NULL) 202e1051a39Sopenharmony_ci return 0; 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci *callback = ctx->callback; 205e1051a39Sopenharmony_ci *callback_arg = ctx->callback_arg; 206e1051a39Sopenharmony_ci return 1; 207e1051a39Sopenharmony_ci} 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status) 210e1051a39Sopenharmony_ci{ 211e1051a39Sopenharmony_ci ctx->status = status; 212e1051a39Sopenharmony_ci return 1; 213e1051a39Sopenharmony_ci} 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ciint ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx) 216e1051a39Sopenharmony_ci{ 217e1051a39Sopenharmony_ci return ctx->status; 218e1051a39Sopenharmony_ci} 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_civoid async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx) 221e1051a39Sopenharmony_ci{ 222e1051a39Sopenharmony_ci struct fd_lookup_st *curr, *prev = NULL; 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci ctx->numadd = 0; 225e1051a39Sopenharmony_ci ctx->numdel = 0; 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ci curr = ctx->fds; 228e1051a39Sopenharmony_ci 229e1051a39Sopenharmony_ci while (curr != NULL) { 230e1051a39Sopenharmony_ci if (curr->del) { 231e1051a39Sopenharmony_ci if (prev == NULL) 232e1051a39Sopenharmony_ci ctx->fds = curr->next; 233e1051a39Sopenharmony_ci else 234e1051a39Sopenharmony_ci prev->next = curr->next; 235e1051a39Sopenharmony_ci OPENSSL_free(curr); 236e1051a39Sopenharmony_ci if (prev == NULL) 237e1051a39Sopenharmony_ci curr = ctx->fds; 238e1051a39Sopenharmony_ci else 239e1051a39Sopenharmony_ci curr = prev->next; 240e1051a39Sopenharmony_ci continue; 241e1051a39Sopenharmony_ci } 242e1051a39Sopenharmony_ci if (curr->add) { 243e1051a39Sopenharmony_ci curr->add = 0; 244e1051a39Sopenharmony_ci } 245e1051a39Sopenharmony_ci prev = curr; 246e1051a39Sopenharmony_ci curr = curr->next; 247e1051a39Sopenharmony_ci } 248e1051a39Sopenharmony_ci} 249