`ptls_openssl_get_async_fd` assumes particular type of implementation; use a callback to generalize the concept
diff --git a/include/picotls.h b/include/picotls.h
index 9762dad..343cf65 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -654,6 +654,10 @@
  */
 typedef struct st_ptls_async_job_t {
     void (*destroy_)(struct st_ptls_async_job_t *self);
+    /**
+     * optional callback returning a file descriptor that becomes readable when the job is complete
+     */
+    int (*get_fd)(struct st_ptls_async_job_t *self);
 } ptls_async_job_t;
 /**
  * When gerenating CertificateVerify, the core calls the callback to sign the handshake context using the certificate. This callback
diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h
index cc7ec4e..a892f9b 100644
--- a/include/picotls/openssl.h
+++ b/include/picotls/openssl.h
@@ -125,13 +125,6 @@
  */
 int ptls_openssl_create_key_exchange(ptls_key_exchange_context_t **ctx, EVP_PKEY *pkey);
 
-#if PTLS_OPENSSL_HAVE_ASYNC
-/**
- * Returns the file descriptor of the asynchronous operation in flight.
- */
-OSSL_ASYNC_FD ptls_openssl_get_async_fd(ptls_t *ptls);
-#endif
-
 typedef struct st_ptls_openssl_signature_scheme_t {
     uint16_t scheme_id;
     const EVP_MD *(*scheme_md)(void);
diff --git a/lib/openssl.c b/lib/openssl.c
index ac3a114..71b33ae 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -738,6 +738,18 @@
     free(self);
 }
 
+int async_sign_ctx_get_fd(ptls_async_job_t *_self)
+{
+    struct async_sign_ctx *self = (void *)_self;
+    OSSL_ASYNC_FD fds[1];
+    size_t numfds;
+
+    ASYNC_WAIT_CTX_get_all_fds(self->waitctx, NULL, &numfds);
+    assert(numfds == 1);
+    ASYNC_WAIT_CTX_get_all_fds(self->waitctx, fds, &numfds);
+    return (int)fds[0];
+}
+
 static ptls_async_job_t *async_sign_ctx_new(const ptls_openssl_signature_scheme_t *scheme, EVP_MD_CTX *ctx, size_t siglen)
 {
     struct async_sign_ctx *self;
@@ -745,7 +757,7 @@
     if ((self = malloc(offsetof(struct async_sign_ctx, sig) + siglen)) == NULL)
         return NULL;
 
-    self->super = (ptls_async_job_t){async_sign_ctx_free};
+    self->super = (ptls_async_job_t){async_sign_ctx_free, async_sign_ctx_get_fd};
     self->scheme = scheme;
     self->ctx = ctx;
     self->waitctx = ASYNC_WAIT_CTX_new();
@@ -756,18 +768,6 @@
     return &self->super;
 }
 
-OSSL_ASYNC_FD ptls_openssl_get_async_fd(ptls_t *ptls)
-{
-    OSSL_ASYNC_FD fds[1];
-    size_t numfds;
-    struct async_sign_ctx *async = (void *)ptls_get_async_job(ptls);
-    assert(async != NULL);
-    ASYNC_WAIT_CTX_get_all_fds(async->waitctx, NULL, &numfds);
-    assert(numfds == 1);
-    ASYNC_WAIT_CTX_get_all_fds(async->waitctx, fds, &numfds);
-    return fds[0];
-}
-
 static int do_sign_async_job(void *_async)
 {
     struct async_sign_ctx *async = *(struct async_sign_ctx **)_async;