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