Author: brane
Date: Fri Jul 25 11:04:38 2025
New Revision: 1927464
Log:
Add an asyncrhonous connection creation API. This is likely to be the most
common use of the asyncrhonous resolver.
* serf.h
(serf_connection_created_t): Callback type for serf_connection_create_async.
(serf_connection_create_async): New.
* src/outgoing.c
(async_create_baton): New; baton for asyncrhonous address resolution.
(async_conn_create): New; callback for same, actually creates the connection.
(serf_connection_create_async): Implement.
* test/test_util.c
(async_reolved_baton, address_resolved): Removed.
(conn_created): New callback.
(use_new_async_connection): Use serf_connection_create_async.
Modified:
serf/trunk/serf.h
serf/trunk/src/outgoing.c
serf/trunk/test/test_util.c
Modified: serf/trunk/serf.h
==============================================================================
--- serf/trunk/serf.h Fri Jul 25 10:20:01 2025 (r1927463)
+++ serf/trunk/serf.h Fri Jul 25 11:04:38 2025 (r1927464)
@@ -546,7 +546,7 @@ apr_status_t serf_connection_create3(
* The @a ctx and @a resolved_baton arguments are the same that were passed
* to serf_address_resolve_async().
*
- * @a status contains the result of the address resolution. If it is notably
+ * @a status contains the result of the address resolution. If it is not
* @c APR_SUCCESS, then @a host_address is invalid and should be ignored.
*
* The resolved @a host_address is ephemeral, allocated iun @a pool and lives
@@ -592,6 +592,56 @@ apr_status_t serf_address_resolve_async(
apr_pool_t *pool);
+/**
+ * Notification callback when a connection hae been created.
+ *
+ * The @a ctx and @a created_baton arguments are the same that were passed
+ * to serf_connection_create_async().
+ *
+ * @a status contains the result of the connection creation. If it is not
+ * @c APR_SUCCESS, then @a conn is invalid and should be ignored.
+ *
+ * The created @a conn is allocated in the pool that was passed to
+ * serf_connection_create_async(); this is @b not the same as @a pool.
+ *
+ * All temporary allocations should be made in @a pool.
+ *
+ * @since New in 1.4.
+ */
+/* FIXME: EXPERIMENTAL */
+typedef void (*serf_connection_created_t)(
+ serf_context_t *ctx,
+ void *created_baton,
+ serf_connection_t *conn,
+ apr_status_t status,
+ apr_pool_t *pool);
+
+/**
+ * Asyncchronously create a new connection associated with
+ * the @a ctx serf context.
+ *
+ * Like serf_connection_create3() with @a host_address set to @c NULL,
+ * except that address resolution is performed asynchronously, similarly to
+ * serf_address_resolve_async().
+ *
+ * The @a created callback with @a created_baton is called when the connection
+ * is created but before it is opened.
+ *
+ * @since New in 1.4.
+ */
+/* FIXME: EXPERIMENTAL */
+apr_status_t serf_connection_create_async(
+ serf_context_t *ctx,
+ apr_uri_t host_info,
+ serf_connection_created_t created,
+ void *created_baton,
+ serf_connection_setup_t setup,
+ void *setup_baton,
+ serf_connection_closed_t closed,
+ void *closed_baton,
+ apr_pool_t *pool);
+
+
typedef apr_status_t (*serf_accept_client_t)(
serf_context_t *ctx,
serf_listener_t *l,
Modified: serf/trunk/src/outgoing.c
==============================================================================
--- serf/trunk/src/outgoing.c Fri Jul 25 10:20:01 2025 (r1927463)
+++ serf/trunk/src/outgoing.c Fri Jul 25 11:04:38 2025 (r1927464)
@@ -1362,6 +1362,78 @@ apr_status_t serf_connection_create3(
return status;
}
+
+struct async_create_baton
+{
+ apr_uri_t host_info;
+ serf_connection_created_t created;
+ void *created_baton;
+ serf_connection_setup_t setup;
+ void *setup_baton;
+ serf_connection_closed_t closed;
+ void *closed_baton;
+ apr_pool_t *conn_pool;
+};
+
+static void async_conn_create(serf_context_t *ctx,
+ void *resolved_baton,
+ apr_sockaddr_t *host_address,
+ apr_status_t status,
+ apr_pool_t *scratch_pool)
+{
+ struct async_create_baton *const baton = resolved_baton;
+ serf_connection_t *conn = NULL;
+
+ if (status == APR_SUCCESS)
+ {
+ status = apr_sockaddr_info_copy(&host_address, host_address,
+ baton->conn_pool);
+ if (status == APR_SUCCESS) {
+ status = serf_connection_create3(&conn, ctx,
+ baton->host_info,
+ host_address,
+ baton->setup, baton->setup_baton,
+ baton->closed,
baton->closed_baton,
+ baton->conn_pool);
+ }
+ }
+
+ baton->created(ctx, baton->created_baton, conn, status, scratch_pool);
+}
+
+apr_status_t serf_connection_create_async(
+ serf_context_t *ctx,
+ apr_uri_t host_info,
+ serf_connection_created_t created,
+ void *created_baton,
+ serf_connection_setup_t setup,
+ void *setup_baton,
+ serf_connection_closed_t closed,
+ void *closed_baton,
+ apr_pool_t *pool)
+{
+ apr_pool_t *scratch_pool;
+ apr_status_t status;
+
+ struct async_create_baton *const baton = apr_palloc(pool, sizeof(*baton));
+ baton->host_info = host_info;
+ baton->created = created;
+ baton->created_baton = created_baton;
+ baton->setup = setup;
+ baton->setup_baton = setup_baton;
+ baton->closed = closed;
+ baton->closed_baton = closed_baton;
+ baton->conn_pool = pool;
+
+ apr_pool_create(&scratch_pool, pool);
+ status = serf_address_resolve_async(ctx, host_info,
+ async_conn_create, baton,
+ scratch_pool);
+ apr_pool_destroy(scratch_pool);
+ return status;
+}
+
+
apr_status_t serf_connection_reset(
serf_connection_t *conn)
{
Modified: serf/trunk/test/test_util.c
==============================================================================
--- serf/trunk/test/test_util.c Fri Jul 25 10:20:01 2025 (r1927463)
+++ serf/trunk/test/test_util.c Fri Jul 25 11:04:38 2025 (r1927464)
@@ -142,44 +142,22 @@ apr_status_t use_new_connection(test_bat
return status;
}
-struct async_reolved_baton
+static void conn_created(serf_context_t *ctx,
+ void *resolved_baton,
+ serf_connection_t *conn,
+ apr_status_t status,
+ apr_pool_t *unused_scratch_pool)
{
- test_baton_t *tb;
- apr_uri_t url;
-};
-
-static void address_resolved(serf_context_t *ctx,
- void *resolved_baton,
- apr_sockaddr_t *host_address,
- apr_status_t status,
- apr_pool_t *unused_scratch_pool)
-{
- struct async_reolved_baton *baton = resolved_baton;
- test_baton_t *tb = baton->tb;
- serf_connection_t *conn;
- apr_pool_t *conn_pool = tb->pool;
+ test_baton_t *tb = resolved_baton;
if (tb->context != ctx)
REPORT_TEST_SUITE_ERROR();
if (status == APR_SUCCESS)
{
- status = apr_sockaddr_info_copy(&host_address, host_address,
conn_pool);
- if (status == APR_SUCCESS)
- status = serf_connection_create3(&conn, ctx,
- baton->url,
- host_address,
- tb->conn_setup,
- tb,
- default_closed_connection,
- tb,
- conn_pool);
- if (status == APR_SUCCESS)
- {
- tb->connection = conn;
- apr_pool_cleanup_register(conn_pool, tb->connection, cleanup_conn,
- apr_pool_cleanup_null);
- }
+ tb->connection = conn;
+ apr_pool_cleanup_register(tb->pool, tb->connection, cleanup_conn,
+ apr_pool_cleanup_null);
}
tb->user_status = status;
@@ -190,7 +168,6 @@ apr_status_t use_new_async_connection(te
{
apr_uri_t url;
apr_status_t status;
- struct async_reolved_baton *baton;
if (tb->connection)
cleanup_conn(tb->connection);
@@ -200,12 +177,12 @@ apr_status_t use_new_async_connection(te
if (status != APR_SUCCESS)
return status;
- baton = apr_palloc(pool, sizeof(*baton));
- baton->tb = tb;
- baton->url = url;
tb->user_status = APR_SUCCESS;
- return serf_address_resolve_async(tb->context, url,
- address_resolved, baton, pool);
+ return serf_connection_create_async(tb->context, url,
+ conn_created, tb,
+ tb->conn_setup, tb,
+ default_closed_connection, tb,
+ tb->pool);
}
static test_baton_t *initTestCtx(CuTest *tc, apr_pool_t *pool)