ASYNC_WAIT_CTX_NEW(3ossl)

πŸ“¦
version 15.1 Β· 2 versions
, in freebsd 15.1

🌸 ASYNC_WAIT_CTX_NEW β€” the OpenSSL 3ossl manual, bestie edition πŸŽ€

okay so. this whole page lives in the OpenSSL 3ossl manual section, and it's basically the entire friend group of ASYNC_WAIT_CTX functions. pull up a chair πŸ’–


✨ NAME ✨

okay so here's the whole squad, all of them, in one giant roll call β€” these are the functions that manage waiting for asynchronous jobs to complete:

  • ASYNC_WAIT_CTX_new
  • ASYNC_WAIT_CTX_free
  • ASYNC_WAIT_CTX_set_wait_fd
  • ASYNC_WAIT_CTX_get_fd
  • ASYNC_WAIT_CTX_get_all_fds
  • ASYNC_WAIT_CTX_get_changed_fds
  • ASYNC_WAIT_CTX_clear_fd
  • ASYNC_WAIT_CTX_set_callback
  • ASYNC_WAIT_CTX_get_callback
  • ASYNC_WAIT_CTX_set_status
  • ASYNC_WAIT_CTX_get_status
  • ASYNC_callback_fn
  • ASYNC_STATUS_UNSUPPORTED
  • ASYNC_STATUS_ERR
  • ASYNC_STATUS_OK
  • ASYNC_STATUS_EAGAIN

literally all of them. no cap, that's the list. πŸ’…


🌈 SYNOPSIS 🌈

here's the tea, exactly as written, don't touch the formatting or it gets mad:

#include <openssl/async.h>

#define ASYNC_STATUS_UNSUPPORTED    0
#define ASYNC_STATUS_ERR            1
#define ASYNC_STATUS_OK             2
#define ASYNC_STATUS_EAGAIN         3
typedef int (*ASYNC_callback_fn)(void *arg);
ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void);
void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx);
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 *));
int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key,
                          OSSL_ASYNC_FD *fd, void **custom_data);
int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd,
                               size_t *numfds);
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);
int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx,
                                ASYNC_callback_fn callback,
                                void *callback_arg);
int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx,
                                ASYNC_callback_fn *callback,
                                void **callback_arg);
int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status);
int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx);

πŸ¦‹ DESCRIPTION πŸ¦‹

so. if you want the full lore on how asynchronous operations actually work in OpenSSL, go read ASYNC_start_job(3) β€” that's the origin story. this page is about one specific little object. 🫢

an ASYNC_WAIT_CTX object represents an asynchronous "session", meaning a related set of crypto operations. like, in SSL terms? it's a strict one-to-one correspondence with an SSL connection. one wait ctx, one SSL connection, they're bonded like that. ✨

here's how you're supposed to use it:

application code must create an ASYNC_WAIT_CTX using the ASYNC_WAIT_CTX_new() function before calling ASYNC_start_job() (again β€” see ASYNC_start_job(3) for that one). when the job starts, it gets associated with the ASYNC_WAIT_CTX for the whole duration of that job. πŸ’–

⚠️ one ASYNC_WAIT_CTX should only be used for one ASYNC_JOB at any one time. but bestie, it's reusable! once an ASYNC_JOB has finished, you can use the same ctx for a subsequent ASYNC_JOB.

when the session is complete (say the SSL connection gets closed), application code cleans up with ASYNC_WAIT_CTX_free(). tidy. iconic. periodt. πŸŽ€

πŸ’… the "wait" file descriptors

ASYNC_WAIT_CTXs can have "wait" file descriptors associated with them. here's how you get at them:

call ASYNC_WAIT_CTX_get_all_fds() and pass in a pointer to an ASYNC_WAIT_CTX in the ctx parameter, and it'll return the wait file descriptors associated with that job in *fd. the number of file descriptors returned gets stored in *numfds. πŸ“‹

πŸ”₯ and this part is on you: it is the caller's responsibility to make sure enough memory has been allocated in *fd to receive all the file descriptors. nobody's doing that for you, bestie.

calling ASYNC_WAIT_CTX_get_all_fds() with a NULL fd value returns no file descriptors at all, but it will still populate *numfds. so the typical move for application code is to call this function twice: once to get the number of fds, and then again after you've allocated sufficient memory. classic two-step, iykyk. 🩰

  • if only one asynchronous engine is being used, then normally this call will only ever return one fd
  • if multiple asynchronous engines are being used, then more could be returned

🌸 spotting fd changes

the function ASYNC_WAIT_CTX_get_changed_fds() can be used to detect if any fds have changed since the last time ASYNC_start_job() returned ASYNC_PAUSE β€” or, if no ASYNC_PAUSE result has been received, since the ASYNC_WAIT_CTX was created. πŸ‘‘

the numaddfds and numdelfds parameters get populated with the number of fds added or deleted respectively. *addfd and *delfd get populated with the list of added and deleted fds respectively. and similarly to ASYNC_WAIT_CTX_get_all_fds(), either of these can be NULL β€” but if they're not NULL, then the caller is responsible for ensuring sufficient memory is allocated. same rule, different day. πŸ’€

🧚 a note for the engine girlies

implementers of async aware code (e.g. engines) are encouraged to return a stable fd for the lifetime of the ASYNC_WAIT_CTX, to reduce the "churn" of regularly changing fds β€” although no guarantees of this are provided to applications. so like, it's a nice-to-have, not a promise. πŸ™ˆ

applications can wait for the file descriptor to be ready for "read" using a system function call such as select or poll β€” and being ready for "read" indicates that the job should be resumed. if no file descriptor is made available, then an application will have to periodically "poll" the job by attempting to restart it to see if it's ready to continue. annoying, but valid. πŸ’«

async aware code (e.g. engines) can grab the current ASYNC_WAIT_CTX from the job via ASYNC_get_wait_ctx(3) and provide a file descriptor to use for waiting on by calling ASYNC_WAIT_CTX_set_wait_fd(). typically this is done by an engine immediately prior to calling ASYNC_pause_job() β€” and not by end user code. know your lane, bestie. βœ‹

an existing association with a file descriptor can be obtained using ASYNC_WAIT_CTX_get_fd() and cleared using ASYNC_WAIT_CTX_clear_fd(). both of these functions require a key value which is unique to the async aware code. it could be any unique value, but a good candidate might be the ENGINE * for the engine. πŸ—οΈ

the custom_data parameter can be any value, and will be returned in a subsequent call to ASYNC_WAIT_CTX_get_fd().

the ASYNC_WAIT_CTX_set_wait_fd() function also expects a pointer to a "cleanup" routine. this can be NULL, but if provided it will automatically get called when the ASYNC_WAIT_CTX is freed, and gives the engine the opportunity to close the fd or any other resources.

πŸ’€ NOTE: the "cleanup" routine does not get called if the fd is cleared directly via a call to ASYNC_WAIT_CTX_clear_fd(). like, at all. so don't come crying to me when your resources leak, okay?

πŸŽ€ a typical usage example

an example of typical usage might be an async capable engine. user code would initiate cryptographic operations. the engine would initiate those operations asynchronously and then call ASYNC_WAIT_CTX_set_wait_fd() followed by ASYNC_pause_job() to return control to the user code. πŸ”

the user code can then perform other tasks, or wait for the job to be ready by calling select or other similar function on the wait file descriptor. the engine can signal to the user code that the job should be resumed by making the wait file descriptor "readable". once resumed, the engine should clear the wake signal on the wait file descriptor. ✨ clean handoff, main character energy.

Okay bestie, legal era β€” but like, the important kind, so pay attention πŸ’…

Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.

That's the whole squad holding it down from 2016 all the way through 2024 β€” respect the longevity, honestly πŸ‘‘

And here's the licensing tea β˜• β€” this file is dropped under the Apache License 2.0 (yup, "the License"), and the rules are giving very much read before you touch 😭:

  • You may not use this file except in compliance with the License. No cap β€” that's not a suggestion, that's the whole vibe check 🫢
  • Need the full text? You can obtain a copy in the file LICENSE in the source distribution, or at <https://www.openssl.org/source/license.html> ✨

So like, go read it, it's literally right there. Free knowledge, iconic behaviour 🌈


And that's a wrap on the whole page, bestie β€” you ate πŸ’– This little beauty comes from the source/version 3.5.6, dated 2026-04-07, and it's filed under ASYNC_WAIT_CTX_NEW(3ossl). Go forth and async_wait_ctx responsibly, mwah πŸŽ€πŸ¦‹πŸ’œ

πŸ“¦ where this page comes from