Author: dsahlberg
Date: Sun Dec 14 17:04:51 2025
New Revision: 1930563
Log:
On the SERF-195-branch: sync with trunk @ 1930562
Added:
serf/branches/SERF-195/test/manual/
- copied from r1930562, serf/trunk/test/manual/
Modified:
serf/branches/SERF-195/ (props changed)
serf/branches/SERF-195/auth/auth_basic.c
serf/branches/SERF-195/serf.h
serf/branches/SERF-195/src/outgoing.c
serf/branches/SERF-195/src/resolve.c
serf/branches/SERF-195/test/serf_get.c
Modified: serf/branches/SERF-195/auth/auth_basic.c
==============================================================================
--- serf/branches/SERF-195/auth/auth_basic.c Sun Dec 14 16:02:14 2025
(r1930562)
+++ serf/branches/SERF-195/auth/auth_basic.c Sun Dec 14 17:04:51 2025
(r1930563)
@@ -45,8 +45,6 @@ serf__handle_basic_auth(const serf__auth
const char *auth_attr,
apr_pool_t *pool)
{
- const char *tmp;
- apr_size_t tmp_len;
serf_connection_t *conn = request->conn;
serf_context_t *ctx = conn->ctx;
serf__authn_info_t *authn_info;
@@ -55,6 +53,7 @@ serf__handle_basic_auth(const serf__auth
apr_pool_t *scratch_pool;
apr_hash_t *attr_dict;
char *username, *password;
+ const char *basic_creds;
const char *realm_name, *realm = NULL;
/* Can't do Basic authentication if there's no callback to get
@@ -93,14 +92,11 @@ serf__handle_basic_auth(const serf__auth
return status;
}
- tmp = apr_pstrcat(conn->pool, username, ":", password, NULL);
- tmp_len = strlen(tmp);
- apr_pool_destroy(scratch_pool);
-
- serf__encode_auth_header(&basic_info->value,
- scheme->name,
- tmp, tmp_len, pool);
+ basic_creds = apr_pstrcat(scratch_pool, username, ":", password, NULL);
+ serf__encode_auth_header(&basic_info->value, scheme->name,
+ basic_creds, strlen(basic_creds), pool);
basic_info->header = SERF__HEADER_FROM_CODE(code);
+ apr_pool_destroy(scratch_pool);
return APR_SUCCESS;
}
Modified: serf/branches/SERF-195/serf.h
==============================================================================
--- serf/branches/SERF-195/serf.h Sun Dec 14 16:02:14 2025
(r1930562)
+++ serf/branches/SERF-195/serf.h Sun Dec 14 17:04:51 2025
(r1930563)
@@ -54,12 +54,6 @@ typedef struct serf_incoming_request_t s
typedef struct serf_request_t serf_request_t;
-#if 0
-typedef struct serf_connection_type_t serf_connection_type_t;
-typedef struct serf_protocol_t serf_protocol_t;
-typedef struct serf_protocol_type_t serf_protocol_type_t;
-#endif /* Connection and protocol API v2 */
-
typedef struct serf_config_t serf_config_t;
/**
@@ -470,15 +464,17 @@ typedef apr_status_t (*serf_credentials_
* destroying this pool will close the connection, and terminate any
* outstanding requests or responses.
*
+ * The @a setup callback will be invoked, and @a setup_baton passed to it,
+ * once the connection is actually established. @see serf_connection_setup_t.
+ *
* When the connection is closed (upon request or because of an error),
* then the @a closed callback is invoked, and @a closed_baton is passed.
*
- * ### doc on setup(_baton). tweak below comment re: acceptor.
- * NULL may be passed for @a acceptor and @a closed; default implementations
+ * NULL may be passed for @a setup and @a closed; default implementations
* will be used.
*
- * @note The connection is not made immediately. It will be opened on
- * the next call to @see serf_context_run.
+ * @note the connection is not made immediately. It will be opened
+ * asynchronously on the next call to serf_context_run().
*/
serf_connection_t *serf_connection_create(
serf_context_t *ctx,
@@ -492,59 +488,37 @@ serf_connection_t *serf_connection_creat
/**
* Create a new connection associated with the @a ctx serf context.
*
- * Like @see serf_connection_create3 but with @a host_address set to @c NULL.
- */
-apr_status_t serf_connection_create2(
- serf_connection_t **conn,
- serf_context_t *ctx,
- apr_uri_t host_info,
- serf_connection_setup_t setup,
- void *setup_baton,
- serf_connection_closed_t closed,
- void *closed_baton,
- apr_pool_t *pool);
-
-
-/**
- * Create a new connection associated with the @a ctx serf context.
- *
* A connection will be created to (eventually) connect to the address
- * specified by @a address. The address must live at least as long as
- * @a pool (thus, as long as the connection object).
- *
- * If @a host_address is @c NULL, the host address will be looked up
- * based on the hostname in @a host_info; otherwise @a host_address
- * will be used to connect and @a host_info will only be used for
- * setting request headers.
+ * specified by @a host_info (either directly or through a proxy), which
+ * must live at least as long as @a pool (thus, as long as the connection
+ * object). The @a host_info will also be used for setting request headers.
*
* The connection object will be allocated within @a pool. Clearing or
* destroying this pool will close the connection, and terminate any
* outstanding requests or responses.
*
+ * The @a setup callback will be invoked, and @a setup_baton passed to it,
+ * once the connection is actually established. @see serf_connection_setup_t.
+ *
* When the connection is closed (upon request or because of an error),
* then the @a closed callback is invoked, and @a closed_baton is passed.
*
- * ### doc on setup(_baton). tweak below comment re: acceptor.
- * NULL may be passed for @a acceptor and @a closed; default implementations
+ * NULL may be passed for @a setup and @a closed; default implementations
* will be used.
*
- * @note the connection is not made immediately. It will be opened on
- * the next call to @see serf_context_run.
- *
- * @since New in 1.4.
+ * @note The connection is not made immediately. It will be opened
+ * asynchronously on the next call to serf_context_run().
*/
-apr_status_t serf_connection_create3(
+apr_status_t serf_connection_create2(
serf_connection_t **conn,
serf_context_t *ctx,
apr_uri_t host_info,
- apr_sockaddr_t *host_address,
serf_connection_setup_t setup,
void *setup_baton,
serf_connection_closed_t closed,
void *closed_baton,
apr_pool_t *pool);
-
/**
* Notification callback when an address hae been resolved.
*
@@ -574,8 +548,11 @@ typedef void (*serf_address_resolved_t)(
* Asynchronously resolve an address.
*
* The address represented by @a host_info is intended to be used to create
- * new connections in @a ctx; proxy configuration will be taken into account
- * during resolution. See, for example, serf_connection_create3().
+ * new connections in @a ctx; see, for example, serf_connection_create().
+ * However, unlike in the connection creation functions, the address will be
+ * resolved regardless of proxy configuration. In order to avoid unnecessary
+ * address resolution, use serf_connection_create_async(), which does take
+ * proxy configuration into account.
*
* The @a resolve callback will be called during a subsequent call to
* serf_context_run() or serf_context_prerun() and will receive the same
@@ -625,14 +602,15 @@ typedef void (*serf_connection_created_t
* 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().
+ * Like serf_connection_create2() except that address resolution is performed
+ * asynchronously, similarly to serf_address_resolve_async(). Address
resolution
+ * will be skipped if a proxy is configured; in this case, the function becomes
+ * synchronous and effectively equivalent to serf_connection_create2().
*
* The @a created callback with @a created_baton is called when the connection
* is created but before it is opened. Note that depending on the configuration
- * of @a ctx,the connection may be created and this callback be invoked
- * synchronously during the scope of this function call.
+ * of @a ctx and @a host_info, the connection may be created and this callback
+ * be invoked synchronously during the scope of this function call.
*
* @since New in 1.4.
*/
@@ -1040,8 +1018,8 @@ serf_bucket_t *serf_context_bucket_socke
* settings.
*
* This function will set following header(s):
- * - Host: if the connection was created with @see serf_connection_create2
- * or @see serf_connection_create3
+ * - Host: if the connection was created serf_connection_create2()
+ * or serf_connection_create_async()
*/
serf_bucket_t *serf_request_bucket_request_create(
serf_request_t *request,
@@ -1903,241 +1881,6 @@ apr_status_t serf_logging_add_output(ser
const serf_log_output_t *output);
-/*** Connection and protocol API v2 ***/
-#if 0
-/* ### docco. */
-apr_status_t serf_connection_switch_protocol(
- serf_connection_t *conn,
- serf_protocol_t *proto
- /* ### other params? */
- );
-
-
-/* ### docco. */
-typedef struct serf_queue_item_t serf_queue_item_t;
-
-
-/**
- * Present a response to the application.
- *
- * Called when a response has been processed by the current protocol (to any
- * extent necessary) and is ready for the application to handle.
- *
- * Note: @a request may be NULL if this response is server-pushed rather than
- * specifically requested.
- *
- * @since New in 1.4.
- */
-typedef apr_status_t (*serf_begin_response_t)(
- /* ### args not settled */
- void **handler_baton,
- serf_request_t *request,
- serf_bucket_t *response,
- apr_pool_t *scratch_pool);
-
-
-/* ### better name? */
-typedef apr_status_t (*serf_handler_t)(
- /* ### args not settled */
- void *handler_baton,
- serf_bucket_t *response,
- apr_pool_t *scratch_pool);
-
-
-struct serf_protocol_type_t {
- /** Name of this protocol type. */
- const char *name;
-
- /** Vtable version. */
- int version;
-#define SERF_PROTOCOL_TYPE_VERSION 1
-
- /**
- * When a pending request reaches the front of the queue, then it becomes
- * "active". This callback is used to build/provide the protocol-specific
- * request bucket.
- *
- * ### more docco
- */
- apr_status_t (*serf_request_activate_t)(
- serf_bucket_t **request_bkt,
- serf_queue_item_t *request_qi,
- void *request_baton,
- serf_bucket_alloc_t *request_bktalloc,
- apr_pool_t *scratch_pool);
-
- /**
- * Construct a protocol parsing bucket, for passing to the process_data
- * vtable entry.
- *
- * When data arrives on the connection, and a parser is not already
- * processing the connection's data, then build a new bucket to parse
- * this incoming data (according to the protocol).
- */
- serf_bucket_t * (*build_parser)(serf_protocol_t *proto,
- apr_pool_t *scratch_pool);
-
- /**
- * The protocol should parse all available response data, per the protocol.
- *
- * This is called when data has become available to the parser. The
protocol
- * should read all available data before returning.
- */
- apr_status_t (*process_data)(serf_protocol_t *proto,
- serf_bucket_t *parser,
- apr_pool_t *scratch_pool);
-};
-
-
-/**
- * Activate an HTTP request when it reaches the front of the queue.
- *
- * ### more docco
- *
- * @since New in 1.4.
- */
-typedef apr_status_t (*serf_http_activate_t)(
- serf_bucket_t **body_bkt,
- serf_bucket_t *request_bkt, /* type REQUEST */
- serf_queue_item_t *request_qi,
- void *request_baton,
- serf_bucket_alloc_t *request_bktalloc,
- apr_pool_t *scratch_pool);
-
-
-/**
- * Create a new connection and associated HTTP protocol parser.
- *
- * The new connection/protocol will be associated with @a ctx. It will be
- * opened once a request is placed into its outgoing queue. The connection
- * will use @a hostname and @a port for the origin server. If
- * @a proxy_hostname is not NULL, then all requests will go through the
- * proxy specified by @a proxy_hostname and @a proxy_port.
- *
- * DNS lookups for @a hostname and @a proxy_hostname will be performed
- * when the connection first opened, then cached in case the connection
- * ever needs to be re-opened.
- *
- * When a queued request reaches the front of the queue, and is ready for
- * delivery, then @a activate_cb will be called to prepare the request.
- *
- * @a authn_types specifies the types of authentication allowed on this
- * connection. Normally, it should be SERF_AUTHN_ALL. When authentication
- * credentials are required (for the origin server or the proxy), then
- * @a creds_cb will be called with @a app_baton.
- *
- * When the connection is closed (upon request or because of an error),
- * then @a closed_cb will be called with @a app_baton.
- *
- * The connection and protocol paresr will be allocated in @a result_pool.
- * This function will use @a scratch_pool for temporary allocations.
- *
- * @since New in 1.4.
- */
-apr_status_t serf_http_protocol_create(
- serf_protocol_t **proto,
- serf_context_t *ctx,
- const char *hostname,
- int port,
- const char *proxy_hostname,
- int proxy_port,
- int authn_types,
- serf_http_activate_t activate_cb,
- /* ### do we need different params for CREDS_CB and CLOSED_CB ? */
- serf_credentials_callback_t creds_cb,
- serf_connection_closed_t closed_cb,
- void *app_baton,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
-
-/* ### docco. create http proto parser with an encrypted connection. */
-apr_status_t serf_https_protocol_create(
- serf_protocol_t **proto,
- serf_context_t *ctx,
- const char *hostname,
- int port,
- /* ### client certs, credential validation callbacks, etc */
- serf_connection_closed_t closed,
- void *closed_baton,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
-
-/* ### docco. queue up an http request. */
-serf_queue_item_t *serf_http_request_queue(
- serf_protocol_t *proto,
- int priority,
- void *request_baton);
-
-/**
- * ### rationalize against "serf connections and request" group above
- *
- * @defgroup serf connections
- * @ingroup serf
- * @{
- */
-
-struct serf_connection_type_t {
- /** Name of this connection type. */
- const char *name;
-
- /** Vtable version. */
- int version;
-#define SERF_CONNECTION_TYPE_VERSION 1
-
- /**
- * Initiate a connection to the server.
- *
- * ### docco. note async. note that request(s) may be queued.
- * ### can we somehow defer the SSL tunnel's CONNECT to the higher
- * ### layer? then have the HTTP protocol layer wrap a CONN_PLAIN
- * ### into a CONN_TLS connection once the tunnel is established?
- */
- apr_status_t (*connect)(serf_connection_t *conn);
-
- /**
- * Returns a bucket for reading from this connection.
- *
- * This bucket remains constant for the lifetime of the connection. It has
- * built-in BARRIER bucket protection, so it can safely be "destroyed"
- * without problem (and a later call to this vtable function will return
- * the same bucket again).
- *
- * For all intents and purposes, this bucket is borrowed by the caller.
- *
- * This bucket effectively maps to the underlying socket, or possibly to
- * a decrypting bucket layered over the socket.
- */
- serf_bucket_t * (*get_read_bucket)(serf_connection_t *conn);
-
- /**
- * Write some data into into the connection.
- *
- * Attempt to write a number of iovecs into the connection. The number of
- * vectors *completely* written will be returned in @a vecs_written. If
that
- * equals @a vecs_size, then @a last_written will be set to 0. If it is
less
- * (not all iovecs were written), then the amount written from the next,
- * incompletely written iovec is returned in @a last_written.
- *
- * In other words, the first byte of unwritten content is located at:
- *
- * <pre>
- * first = vecs[vecs_written][last_written];
- * </pre>
- *
- * If all bytes are written, then APR_SUCCESS is returned. If only a
portion
- * was written, then APR_EAGAIN will be returned.
- */
- apr_status_t (*writev)(serf_connection_t *conn,
- int vecs_size, struct iovec *vecs,
- int *vecs_written, apr_size_t *last_written);
-};
-
-#endif /* Connection and protocol API v2 */
-/** @} */
-
-
/* Internal functions for bucket use and lifecycle tracking.
### Some of these are directly or via Macros used by third party
### applications, such as Apache Subversion */
Modified: serf/branches/SERF-195/src/outgoing.c
==============================================================================
--- serf/branches/SERF-195/src/outgoing.c Sun Dec 14 16:02:14 2025
(r1930562)
+++ serf/branches/SERF-195/src/outgoing.c Sun Dec 14 17:04:51 2025
(r1930563)
@@ -1262,33 +1262,15 @@ serf_connection_t *serf_connection_creat
return conn;
}
-apr_status_t serf_connection_create2(
- serf_connection_t **conn,
- serf_context_t *ctx,
- apr_uri_t host_info,
- serf_connection_setup_t setup,
- void *setup_baton,
- serf_connection_closed_t closed,
- void *closed_baton,
- apr_pool_t *pool)
-{
- return serf_connection_create3(conn, ctx, host_info, NULL,
- setup, setup_baton,
- closed, closed_baton,
- pool);
-}
-
-
-apr_status_t serf_connection_create3(
- serf_connection_t **conn,
- serf_context_t *ctx,
- apr_uri_t host_info,
- apr_sockaddr_t *host_address,
- serf_connection_setup_t setup,
- void *setup_baton,
- serf_connection_closed_t closed,
- void *closed_baton,
- apr_pool_t *pool)
+static apr_status_t create_connection(serf_connection_t **conn,
+ serf_context_t *ctx,
+ apr_uri_t host_info,
+ apr_sockaddr_t *host_address,
+ serf_connection_setup_t setup,
+ void *setup_baton,
+ serf_connection_closed_t closed,
+ void *closed_baton,
+ apr_pool_t *pool)
{
apr_status_t status = APR_SUCCESS;
serf_config_t *config;
@@ -1346,6 +1328,22 @@ apr_status_t serf_connection_create3(
return status;
}
+apr_status_t serf_connection_create2(
+ serf_connection_t **conn,
+ serf_context_t *ctx,
+ apr_uri_t host_info,
+ serf_connection_setup_t setup,
+ void *setup_baton,
+ serf_connection_closed_t closed,
+ void *closed_baton,
+ apr_pool_t *pool)
+{
+ return create_connection(conn, ctx, host_info, NULL,
+ setup, setup_baton,
+ closed, closed_baton,
+ pool);
+}
+
struct async_create_baton
{
@@ -1375,12 +1373,12 @@ static void async_conn_create(serf_conte
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);
+ status = create_connection(&conn, ctx,
+ baton->host_info,
+ host_address,
+ baton->setup, baton->setup_baton,
+ baton->closed, baton->closed_baton,
+ baton->conn_pool);
}
}
@@ -1405,14 +1403,14 @@ apr_status_t serf_connection_create_asyn
if (ctx->proxy_address)
{
/* If we're using a proxy, we do *not* resolve the host
- (see serf_connection_create3(), above), so just create
+ (see create_connection(), above), so just create
the connection immediately. */
serf_connection_t *conn;
- status = serf_connection_create3(&conn, ctx,
- host_info, NULL,
- setup, setup_baton,
- closed, closed_baton,
- pool);
+ status = create_connection(&conn, ctx,
+ host_info, NULL,
+ setup, setup_baton,
+ closed, closed_baton,
+ pool);
if (status == APR_SUCCESS)
created(ctx, created_baton, conn, status, scratch_pool);
}
Modified: serf/branches/SERF-195/src/resolve.c
==============================================================================
--- serf/branches/SERF-195/src/resolve.c Sun Dec 14 16:02:14 2025
(r1930562)
+++ serf/branches/SERF-195/src/resolve.c Sun Dec 14 17:04:51 2025
(r1930563)
@@ -108,16 +108,6 @@ apr_status_t serf_address_resolve_async(
}
apr_pool_create(&resolve_pool, ctx->pool);
-
- /* See serf_connection_create3(): if there's a proxy configured in the
- context, don't resolve the host address, just register the result. */
- if (ctx->proxy_address)
- {
- push_resolve_result(ctx, NULL, APR_SUCCESS,
- resolved, resolved_baton, resolve_pool);
- return APR_SUCCESS;
- }
-
return resolve_address_async(ctx, host_info, resolved, resolved_baton,
resolve_pool, pool);
}
Modified: serf/branches/SERF-195/test/serf_get.c
==============================================================================
--- serf/branches/SERF-195/test/serf_get.c Sun Dec 14 16:02:14 2025
(r1930562)
+++ serf/branches/SERF-195/test/serf_get.c Sun Dec 14 17:04:51 2025
(r1930563)
@@ -329,6 +329,7 @@ typedef struct handler_baton_t {
const char *username;
const char *password;
int auth_attempts;
+ int conn_count;
serf_bucket_t *req_hdrs;
} handler_baton_t;
@@ -493,7 +494,8 @@ credentials_callback(char **username,
{
handler_baton_t *ctx = baton;
- if (ctx->auth_attempts > 0)
+ /* Every connection should be allowed to connect once. */
+ if (ctx->auth_attempts > ctx->conn_count)
{
return SERF_ERROR_AUTHN_FAILED;
}
@@ -873,6 +875,7 @@ int main(int argc, const char **argv)
handler_ctx.username = username;
handler_ctx.password = password;
handler_ctx.auth_attempts = 0;
+ handler_ctx.conn_count = conn_count;
handler_ctx.req_body_path = req_body_path;