| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-11-26 22:18:57 +08:00
										 |  |  |  * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-06 20:18:31 +08:00
										 |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-05-18 02:24:46 +08:00
										 |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This must be the first #include file */ | 
					
						
							| 
									
										
										
										
											2019-09-28 06:45:40 +08:00
										 |  |  | #include "async_local.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <openssl/err.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return OPENSSL_zalloc(sizeof(ASYNC_WAIT_CTX)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *curr; | 
					
						
							| 
									
										
										
										
											2016-03-21 07:00:13 +08:00
										 |  |  |     struct fd_lookup_st *next; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (ctx == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							| 
									
										
										
										
											2016-03-21 07:00:13 +08:00
										 |  |  |         if (!curr->del) { | 
					
						
							|  |  |  |             /* Only try and cleanup if it hasn't been marked deleted */ | 
					
						
							|  |  |  |             if (curr->cleanup != NULL) | 
					
						
							|  |  |  |                 curr->cleanup(ctx, curr->key, curr->fd, curr->custom_data); | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-03-21 07:00:13 +08:00
										 |  |  |         /* Always free the fd_lookup_st */ | 
					
						
							|  |  |  |         next = curr->next; | 
					
						
							|  |  |  |         OPENSSL_free(curr); | 
					
						
							|  |  |  |         curr = next; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_free(ctx); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-12-03 13:15:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, | 
					
						
							|  |  |  |                                OSSL_ASYNC_FD fd, void *custom_data, | 
					
						
							|  |  |  |                                void (*cleanup)(ASYNC_WAIT_CTX *, const void *, | 
					
						
							|  |  |  |                                                OSSL_ASYNC_FD, void *)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *fdlookup; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 19:57:34 +08:00
										 |  |  |     if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fdlookup->key = key; | 
					
						
							|  |  |  |     fdlookup->fd = fd; | 
					
						
							|  |  |  |     fdlookup->custom_data = custom_data; | 
					
						
							|  |  |  |     fdlookup->cleanup = cleanup; | 
					
						
							|  |  |  |     fdlookup->add = 1; | 
					
						
							|  |  |  |     fdlookup->next = ctx->fds; | 
					
						
							|  |  |  |     ctx->fds = fdlookup; | 
					
						
							|  |  |  |     ctx->numadd++; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, | 
					
						
							|  |  |  |                           OSSL_ASYNC_FD *fd, void **custom_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *curr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							|  |  |  |         if (curr->del) { | 
					
						
							|  |  |  |             /* This one has been marked deleted so do nothing */ | 
					
						
							|  |  |  |             curr = curr->next; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (curr->key == key) { | 
					
						
							|  |  |  |             *fd = curr->fd; | 
					
						
							|  |  |  |             *custom_data = curr->custom_data; | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         curr = curr->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, | 
					
						
							|  |  |  |                                size_t *numfds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *curr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							|  |  |  |     *numfds = 0; | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							|  |  |  |         if (curr->del) { | 
					
						
							|  |  |  |             /* This one has been marked deleted so do nothing */ | 
					
						
							|  |  |  |             curr = curr->next; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (fd != NULL) { | 
					
						
							|  |  |  |             *fd = curr->fd; | 
					
						
							|  |  |  |             fd++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         (*numfds)++; | 
					
						
							|  |  |  |         curr = curr->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, | 
					
						
							|  |  |  |                                    size_t *numaddfds, OSSL_ASYNC_FD *delfd, | 
					
						
							|  |  |  |                                    size_t *numdelfds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *curr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *numaddfds = ctx->numadd; | 
					
						
							|  |  |  |     *numdelfds = ctx->numdel; | 
					
						
							|  |  |  |     if (addfd == NULL && delfd == NULL) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							|  |  |  |         /* We ignore fds that have been marked as both added and deleted */ | 
					
						
							|  |  |  |         if (curr->del && !curr->add && (delfd != NULL)) { | 
					
						
							|  |  |  |             *delfd = curr->fd; | 
					
						
							|  |  |  |             delfd++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (curr->add && !curr->del && (addfd != NULL)) { | 
					
						
							|  |  |  |             *addfd = curr->fd; | 
					
						
							|  |  |  |             addfd++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         curr = curr->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |     struct fd_lookup_st *curr, *prev; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |     prev = NULL; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |     while (curr != NULL) { | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |         if (curr->del == 1) { | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |             /* This one has been marked deleted already so do nothing */ | 
					
						
							| 
									
										
										
										
											2017-10-27 22:54:14 +08:00
										 |  |  |             prev = curr; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |             curr = curr->next; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (curr->key == key) { | 
					
						
							| 
									
										
										
										
											2017-02-03 13:46:17 +08:00
										 |  |  |             /* If fd has just been added, remove it from the list */ | 
					
						
							|  |  |  |             if (curr->add == 1) { | 
					
						
							|  |  |  |                 if (ctx->fds == curr) { | 
					
						
							|  |  |  |                     ctx->fds = curr->next; | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2017-02-03 13:46:17 +08:00
										 |  |  |                     prev->next = curr->next; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |                 /* It is responsibility of the caller to cleanup before calling
 | 
					
						
							|  |  |  |                  * ASYNC_WAIT_CTX_clear_fd | 
					
						
							| 
									
										
										
										
											2017-02-03 13:46:17 +08:00
										 |  |  |                  */ | 
					
						
							|  |  |  |                 OPENSSL_free(curr); | 
					
						
							|  |  |  |                 ctx->numadd--; | 
					
						
							|  |  |  |                 return 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |             /*
 | 
					
						
							|  |  |  |              * Mark it as deleted. We don't call cleanup if explicitly asked | 
					
						
							| 
									
										
										
										
											2016-02-29 20:15:27 +08:00
										 |  |  |              * to clear an fd. We assume the caller is going to do that (if | 
					
						
							|  |  |  |              * appropriate). | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |              */ | 
					
						
							|  |  |  |             curr->del = 1; | 
					
						
							|  |  |  |             ctx->numdel++; | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-10 18:23:21 +08:00
										 |  |  |         prev = curr; | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  |         curr = curr->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-06 04:41:01 +08:00
										 |  |  | int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx, | 
					
						
							|  |  |  |                                 ASYNC_callback_fn callback, | 
					
						
							|  |  |  |                                 void *callback_arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |       if (ctx == NULL) | 
					
						
							|  |  |  |           return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ctx->callback = callback; | 
					
						
							|  |  |  |       ctx->callback_arg = callback_arg; | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx, | 
					
						
							|  |  |  |                                 ASYNC_callback_fn *callback, | 
					
						
							|  |  |  |                                 void **callback_arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |       if (ctx->callback == NULL) | 
					
						
							|  |  |  |           return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *callback = ctx->callback; | 
					
						
							|  |  |  |       *callback_arg = ctx->callback_arg; | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |       ctx->status = status; | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |       return ctx->status; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 23:28:57 +08:00
										 |  |  | void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct fd_lookup_st *curr, *prev = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctx->numadd = 0; | 
					
						
							|  |  |  |     ctx->numdel = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     curr = ctx->fds; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							|  |  |  |         if (curr->del) { | 
					
						
							|  |  |  |             if (prev == NULL) | 
					
						
							|  |  |  |                 ctx->fds = curr->next; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 prev->next = curr->next; | 
					
						
							|  |  |  |             OPENSSL_free(curr); | 
					
						
							|  |  |  |             if (prev == NULL) | 
					
						
							|  |  |  |                 curr = ctx->fds; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 curr = prev->next; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (curr->add) { | 
					
						
							|  |  |  |             curr->add = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         prev = curr; | 
					
						
							|  |  |  |         curr = curr->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |