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