-*- coding: utf-8 -*-
Changes with Apache 2.5.0
+ *) core: add ap_get_protocol_upgrades() to retrieve the list of protocols
+ that a client could possibly upgrade to. Use in first request on a
+ connection to announce protocol choices.
+ [Stefan Eissing]
+
*) mod_http2: reworked deallocation on connection shutdown and worker
abort. Separate parent pool for all workers. worker threads are joined
on planned worker shutdown.
* @return The identifier of the protocol in place or NULL
*/
AP_DECLARE_HOOK(const char *,protocol_get,(const conn_rec *c))
-
+
+/**
+ * Get the protocols that the connection and optional request may
+ * upgrade to - besides the protocol currently active on the connection. These
+ * values may be used to announce to a client what choices it has.
+ *
+ * @param c The current connection
+ * @param r The current request or NULL
+ * @param s The server/virtual host selected or NULL
+ * @param pupgrades on return, possible protocols to upgrade to in descending order
+ * of preference. Maybe NULL if none are available.
+ */
+AP_DECLARE(apr_status_t) ap_get_protocol_upgrades(conn_rec *c, request_rec *r,
+ server_rec *s,
+ const apr_array_header_t **pupgrades);
+
/**
* Select a protocol for the given connection and optional request. Will return
* the protocol identifier selected which may be the protocol already in place
}
}
}
+ else if (!r->connection->keepalives) {
+ /* first request on connection, if we have protocols other
+ * than the current one enabled here, announce them to the
+ * client */
+ const apr_array_header_t *upgrades;
+ ap_get_protocol_upgrades(r->connection, r, NULL, &upgrades);
+ if (upgrades && upgrades->nelts > 0) {
+ char *protocols = apr_array_pstrcat(r->pool, upgrades, ',');
+ apr_table_setn(r->headers_out, "Upgrade", protocols);
+ apr_table_setn(r->headers_out, "Connection", "Upgrade");
+ }
+ }
return DECLINED;
}
return protocol? protocol : AP_PROTOCOL_HTTP1;
}
+AP_DECLARE(apr_status_t) ap_get_protocol_upgrades(conn_rec *c, request_rec *r,
+ server_rec *s,
+ const apr_array_header_t **pupgrades)
+{
+ apr_pool_t *pool = r? r->pool : c->pool;
+ core_server_config *conf;
+ const char *existing;
+ apr_array_header_t *upgrades = NULL;
+
+ if (!s) {
+ s = (r? r->server : c->base_server);
+ }
+ conf = ap_get_core_module_config(s->module_config);
+
+ if (conf->protocols->nelts > 0) {
+ existing = ap_get_protocol(c);
+ if (conf->protocols->nelts > 1
+ || !ap_array_str_contains(conf->protocols, existing)) {
+ /* possibly more than one choice or one, but not the
+ * existing. (TODO: maybe 426 and Upgrade then?) */
+ upgrades = apr_array_make(pool, conf->protocols->nelts + 1,
+ sizeof(char *));
+ for (int i = 0; i < conf->protocols->nelts; ++i) {
+ const char *p = APR_ARRAY_IDX(conf->protocols, i, char *);
+ if (strcmp(existing, p)) {
+ /* not the one we have and possible, add in this order */
+ APR_ARRAY_PUSH(upgrades, const char*) = p;
+ }
+ }
+ }
+ }
+
+ *pupgrades = upgrades;
+ return APR_SUCCESS;
+}
+
AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r,
server_rec *s,
const apr_array_header_t *choices)