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