Author: brane
Date: Sun Jun 29 13:37:25 2025
New Revision: 1926858
URL: http://svn.apache.org/viewvc?rev=1926858&view=rev
Log:
On the user-defined-authn branch: In the interaction diagram, correct the
position in the handshake sequence where pipelining is optionally turned
off on a connection. Add the option to reset pipelining on two more
callbacks; current internal schemes sometimes restore it during the 'handle'
phase, and sometimes (notably spnego) during the response validation phase.
This makes the API for user-defined implementations more flexible at the
cost of having to deal with far too long argument lists. Ain't no fun if
it's less than six parameters, right?
* serf.h: Update the authentication interaction diagram.
(serf_authn_handle_func_t): Add the reset_pipelining argument and update
the docstring to hopefully make it clear what that argument means.
(serf_authn_setup_request_func_t): Add the reset_pipelining argument.
(serf_authn_validate_response_func_t): Update the docstring.
* auth/auth_user_defined.c
(struct authn_baton_wrapper::pipelining_was_reset): Rename from the shorter
but more ambiguous pipelining_reset.
(validate_handler): Add docstring.
(maybe_reset_pipelining): New. Now common code extracted from one of
the callbacks.
(serf__authn_user__handle,
serf__authn_user__setup_request): Implement the reset_pipelining argument.
(serf__authn_user__validate_response): Call maybe_reset_pipelining.
* test/test_auth.c
(user_authn_handle,
user_authn_setup_request): Implement the reset_pipelining argument.
Modified:
serf/branches/user-defined-authn/auth/auth_user_defined.c
serf/branches/user-defined-authn/serf.h
serf/branches/user-defined-authn/test/test_auth.c
Modified: serf/branches/user-defined-authn/auth/auth_user_defined.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/auth/auth_user_defined.c?rev=1926858&r1=1926857&r2=1926858&view=diff
==============================================================================
--- serf/branches/user-defined-authn/auth/auth_user_defined.c (original)
+++ serf/branches/user-defined-authn/auth/auth_user_defined.c Sun Jun 29
13:37:25 2025
@@ -53,13 +53,14 @@ struct authn_baton_wrapper {
int pipelining;
/* Was pipelining reset to its previous value?. */
- bool pipelining_reset;
+ bool pipelining_was_reset;
/* The user-defined scheme's per-connection baton. */
void *user_authn_baton;
};
+/* Common callback parameter validation. */
typedef apr_status_t (*callback_fn_t)();
static apr_status_t validate_handler(serf_config_t *config,
const serf__authn_scheme_t *scheme,
@@ -89,6 +90,34 @@ static apr_status_t validate_handler(ser
}
+/* Reset request pipelining on the connection if required. */
+static void maybe_reset_pipelining(const serf__authn_scheme_t *scheme,
+ struct authn_baton_wrapper *authn_baton,
+ serf_connection_t *conn,
+ apr_status_t status,
+ int reset_pipelining)
+{
+ if (!reset_pipelining
+ || status != APR_SUCCESS
+ || authn_baton->pipelining_was_reset
+ || (scheme->user_flags & SERF_AUTHN_FLAG_PIPE))
+ {
+ serf__log(LOGLVL_DEBUG, LOGCOMP_AUTHN, __FILE__, conn->config,
+ "User-defined scheme %s: no pipelining change for %s\n",
+ scheme->name, conn->host_url);
+ return;
+ }
+
+ serf__log(LOGLVL_DEBUG, LOGCOMP_AUTHN, __FILE__, conn->config,
+ "User-defined scheme %s: pipelining reset to %s for %s\n",
+ scheme->name,
+ authn_baton->pipelining ? "on" : "off",
+ conn->host_url);
+ serf__connection_set_pipelining(conn, authn_baton->pipelining);
+ authn_baton->pipelining_was_reset = true;
+}
+
+
apr_status_t
serf__authn_user__init_conn(const serf__authn_scheme_t *scheme,
int code,
@@ -135,9 +164,9 @@ serf__authn_user__init_conn(const serf__
"User-defined scheme %s: pipelining off for %s\n",
scheme->name, conn->host_url);
authn_baton->pipelining = serf__connection_set_pipelining(conn, 0);
- authn_baton->pipelining_reset = false;
+ authn_baton->pipelining_was_reset = false;
} else {
- authn_baton->pipelining_reset = true;
+ authn_baton->pipelining_was_reset = true;
}
return status;
}
@@ -156,6 +185,7 @@ serf__authn_user__handle(const serf__aut
serf__authn_info_t *const authn_info = get_authn_info(code, conn);
serf_context_t *const ctx = conn->ctx;
struct authn_baton_wrapper *authn_baton;
+ int reset_pipelining = 0;
char *username, *password;
apr_pool_t *scratch_pool;
apr_hash_t *auth_param;
@@ -222,7 +252,8 @@ serf__authn_user__handle(const serf__aut
username = password = NULL;
}
- status = scheme->user_handle_func(scheme->user_baton,
+ status = scheme->user_handle_func(&reset_pipelining,
+ scheme->user_baton,
authn_baton->user_authn_baton, code,
auth_hdr, auth_param,
SERF__HEADER_FROM_CODE(code),
@@ -231,6 +262,7 @@ serf__authn_user__handle(const serf__aut
pool, scratch_pool);
cleanup:
+ maybe_reset_pipelining(scheme, authn_baton, conn, status,
reset_pipelining);
apr_pool_destroy(scratch_pool);
return status;
}
@@ -249,6 +281,7 @@ serf__authn_user__setup_request(const se
const int peer_id = SERF__CODE_FROM_PEER(peer);
serf__authn_info_t *const authn_info = get_authn_info(peer_id, conn);
struct authn_baton_wrapper *authn_baton;
+ int reset_pipelining = 0;
apr_pool_t *scratch_pool;
apr_status_t status;
@@ -271,11 +304,14 @@ serf__authn_user__setup_request(const se
authn_baton = authn_info->baton;
apr_pool_create(&scratch_pool, conn->pool);
- status = scheme->user_setup_request_func(scheme->user_baton,
+ status = scheme->user_setup_request_func(&reset_pipelining,
+ scheme->user_baton,
authn_baton->user_authn_baton,
conn, request,
method, uri, hdrs_bkt,
scratch_pool);
+
+ maybe_reset_pipelining(scheme, authn_baton, conn, status,
reset_pipelining);
apr_pool_destroy(scratch_pool);
return status;
}
@@ -334,19 +370,7 @@ serf__authn_user__validate_response(cons
request, response,
scratch_pool);
- /* Reset pipelining if the scheme requires it. */
- if (status == APR_SUCCESS && reset_pipelining
- && !authn_baton->pipelining_reset
- && !(scheme->user_flags & SERF_AUTHN_FLAG_PIPE)) {
- serf__log(LOGLVL_DEBUG, LOGCOMP_AUTHN, __FILE__, conn->config,
- "User-defined scheme %s: pipelining reset to %s for %s\n",
- scheme->name,
- authn_baton->pipelining ? "on" : "off",
- conn->host_url);
- serf__connection_set_pipelining(conn, authn_baton->pipelining);
- authn_baton->pipelining_reset = true;
- }
-
+ maybe_reset_pipelining(scheme, authn_baton, conn, status,
reset_pipelining);
apr_pool_destroy(scratch_pool);
return status;
}
Modified: serf/branches/user-defined-authn/serf.h
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf.h?rev=1926858&r1=1926857&r2=1926858&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf.h (original)
+++ serf/branches/user-defined-authn/serf.h Sun Jun 29 13:37:25 2025
@@ -962,19 +962,22 @@ serf_bucket_t *serf_request_bucket_reque
* | +<---- authenticate <----+ (401 or 407)
* +<------ init-conn <------+ |
* | | |
+ * | (pipelining off) <--+ (optional) |
* | (get credentials) <--+ (optional) |
* | | |
* +<-------- handle <-------+ |
* | | |
- * | (pipelining off) <--+ (optional) |
+ * | (reset pipelining) <--+ (optional) |
* | | |
* +<---- setup-requiest <---+ |
+ * | | |
+ * | (reset pipelining) <--+ (optional) |
* | +---> request + authn -->+
* | | |
* | +<------ response <------+
* +<-- validate-response <--+ |
* | | |
- * | (pipelining on) <--+ (optional) |
+ * | (reset pipelining) <--+ (optional) |
* | | |
* ```
*/
@@ -1077,12 +1080,22 @@ typedef apr_status_t
* @a request is the pending request and @a response is the response that
* caused this callback to be called.
*
+ * If the scheme flag @c SERF_AUTHN_FLAG_PIPE is *not* set, return a boolean
+ * value in @a reset_pipelining to indicate whether pipelining on @a conn
+ * should be restored to the value before the init-conn callback was invoked.
+ * The value of this flag is set to @c false by the caller, so the
+ * implementation does not have to modify it if the pipelining state should
+ * remain unchanged. This parameter has the same meaning in the
+ * serf_authn_setup_request_func_t and serf_authn_validate_response_func_t
+ * callbacks and will only take effect the first time its value @c true.
+ *
* Use @a scratch_pool for temporary allocations.
*
* @since New in 1.4.
*/
typedef apr_status_t
-(*serf_authn_handle_func_t)(void *baton,
+(*serf_authn_handle_func_t)(int *reset_pipelining,
+ void *baton,
void *authn_baton,
int code,
const char *authn_header,
@@ -1106,12 +1119,15 @@ typedef apr_status_t
* @a method and @a uri are the requests attributes and @a headers are the
* request headers where the credentials are usually set.
*
+ * For the meaning of @a reset_pipelining, see serf_authn_handle_func_t.
+ *
* Use @a scratch_pool for temporary allocations.
*
* @since New in 1.4.
*/
typedef apr_status_t
-(*serf_authn_setup_request_func_t)(void *baton,
+(*serf_authn_setup_request_func_t)(int *reset_pipelining,
+ void *baton,
void *authn_baton,
serf_connection_t *conn,
serf_request_t *request,
@@ -1134,9 +1150,7 @@ typedef apr_status_t
* response header. This argument will be NULL @a response does not contain
* one of those headers.
*
- * If the scheme flag @c SERF_AUTHN_FLAG_PIPE is *not* set, return a boolean
- * value in @a reset_pipelining to indicate whether pipelining on @a conn
should
- * be restored to the value before the init-conn callback was invoked.
+ * For the meaning of @a reset_pipelining, see serf_authn_handle_func_t.
*
* Use @a scratch_pool for temporary allocations.
*
Modified: serf/branches/user-defined-authn/test/test_auth.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/test_auth.c?rev=1926858&r1=1926857&r2=1926858&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/test_auth.c (original)
+++ serf/branches/user-defined-authn/test/test_auth.c Sun Jun 29 13:37:25 2025
@@ -733,7 +733,8 @@ static apr_status_t user_authn_get_realm
return APR_SUCCESS;
}
-static apr_status_t user_authn_handle(void *baton,
+static apr_status_t user_authn_handle(int *reset_pipelining,
+ void *baton,
void *authn_baton,
int code,
const char *authn_header,
@@ -753,10 +754,12 @@ static apr_status_t user_authn_handle(vo
ab->header = apr_pstrdup(result_pool, response_header);
ab->value = apr_pstrcat(result_pool, b->name, " ", password, NULL);
+ *reset_pipelining = 1;
return APR_SUCCESS;
}
-static apr_status_t user_authn_setup_request(void *baton,
+static apr_status_t user_authn_setup_request(int *reset_pipelining,
+ void *baton,
void *authn_baton,
serf_connection_t *conn,
serf_request_t *request,
@@ -777,6 +780,8 @@ static apr_status_t user_authn_setup_req
ab->header, ab->value);
serf_bucket_headers_setn(headers, ab->header, ab->value);
+
+ *reset_pipelining = 1;
return APR_SUCCESS;
}