From dc01487ea6211337fbe632f0c8921d2efaa457eb Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Wed, 24 Mar 2021 21:39:08 -0400 Subject: [PATCH] [multiple] use buffer_append_* aggregates reduces the number of round-trips into some frequently-called routines --- src/configparser.y | 40 +++-- src/connections.c | 13 +- src/data_string.c | 9 +- src/gw_backend.c | 25 +-- src/h2.c | 17 +- src/http-header-glue.c | 11 +- src/http_header.c | 14 +- src/http_range.c | 4 +- src/mod_ajp13.c | 6 +- src/mod_auth.c | 27 +-- src/mod_authn_mysql.c | 35 ++-- src/mod_deflate.c | 9 +- src/mod_dirlisting.c | 92 +++++----- src/mod_fastcgi.c | 11 +- src/mod_nss.c | 10 +- src/mod_proxy.c | 20 +-- src/mod_rrdtool.c | 15 +- src/mod_secdownload.c | 4 +- src/mod_simple_vhost.c | 1 - src/mod_ssi.c | 15 +- src/mod_status.c | 388 +++++++++++++++++----------------------- src/mod_trigger_b4_dl.c | 4 +- src/mod_usertrack.c | 9 +- src/mod_vhostdb_dbi.c | 3 +- src/mod_webdav.c | 225 ++++++++++++----------- src/plugin.c | 10 +- src/request.c | 8 +- src/response.c | 14 +- src/sock_addr.c | 3 +- 29 files changed, 497 insertions(+), 545 deletions(-) diff --git a/src/configparser.y b/src/configparser.y index c65eb3da..56e2f227 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -132,9 +132,9 @@ static int configparser_remoteip_normalize_compat(buffer *rvalue) { int rc; if (rvalue->ptr[0] != '[') { - buffer_append_string_len(b, CONST_STR_LEN("[")); - buffer_append_string_buffer(b, rvalue); - buffer_append_string_len(b, CONST_STR_LEN("]")); + buffer_append_str3(b, CONST_STR_LEN("["), + CONST_BUF_LEN(rvalue), + CONST_STR_LEN("]")); } else { buffer_append_string_buffer(b, rvalue); } @@ -207,19 +207,23 @@ configparser_parse_condition(config_t * const ctx, const buffer * const obj_tag, return; /* unreachable */ } + const uint32_t comp_offset = buffer_string_length(&ctx->current->key)+3; buffer * const tb = ctx->srv->tmp_buf; - buffer_copy_buffer(tb, &ctx->current->key); - buffer_append_string_len(tb, CONST_STR_LEN(" / ")); - const uint32_t comp_offset = buffer_string_length(tb); - buffer_append_string_len(tb, CONST_STR_LEN("$")); - buffer_append_string_buffer(tb, obj_tag); /*(HTTP, REQUEST_HEADER, SERVER)*/ - buffer_append_string_len(tb, CONST_STR_LEN("[\"")); - buffer_append_string_buffer(tb, comp_tag); - buffer_append_string_len(tb, CONST_STR_LEN("\"] ")); - buffer_append_string_len(tb, op, 2); - buffer_append_string_len(tb, CONST_STR_LEN(" \"")); - buffer_append_string_buffer(tb, rvalue); - buffer_append_string_len(tb, CONST_STR_LEN("\"")); + buffer_clear(tb); + struct const_iovec iov[] = { + { CONST_BUF_LEN(&ctx->current->key) } + ,{ CONST_STR_LEN(" / ") } /* comp_offset */ + ,{ CONST_STR_LEN("$") } + ,{ CONST_BUF_LEN(obj_tag) } /*(HTTP, REQUEST_HEADER, SERVER)*/ + ,{ CONST_STR_LEN("[\"") } + ,{ CONST_BUF_LEN(comp_tag) } + ,{ CONST_STR_LEN("\"] ") } + ,{ op, 2 } + ,{ CONST_STR_LEN(" \"") } + ,{ CONST_BUF_LEN(rvalue) } + ,{ CONST_STR_LEN("\"") } + }; + buffer_append_iovec(tb, iov, sizeof(iov)/sizeof(*iov)); data_config *dc; if (NULL != (dc = configparser_get_data_config(ctx->all_configs, @@ -322,9 +326,9 @@ configparser_parse_else_condition(config_t * const ctx) { data_config * const dc = data_config_init(); dc->cond = CONFIG_COND_ELSE; - buffer_copy_buffer(&dc->key, &ctx->current->key); - buffer_append_string_len(&dc->key, CONST_STR_LEN(" / ")); - buffer_append_string_len(&dc->key, CONST_STR_LEN("else_tmp_token")); + buffer_append_str2(&dc->key, CONST_BUF_LEN(&ctx->current->key), + CONST_STR_LEN(" / " + "else_tmp_token")); configparser_push(ctx, dc, 1); } diff --git a/src/connections.c b/src/connections.c index ea40f7dc..82a8e680 100644 --- a/src/connections.c +++ b/src/connections.c @@ -417,14 +417,11 @@ connection_send_1xx (request_st * const r, connection * const con) http_status_append(b, r->http_status); for (uint32_t i = 0; i < r->resp_headers.used; ++i) { const data_string * const ds = (data_string *)r->resp_headers.data[i]; - - if (buffer_string_is_empty(&ds->value)) continue; - if (buffer_string_is_empty(&ds->key)) continue; - - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); - buffer_append_string_buffer(b, &ds->key); - buffer_append_string_len(b, CONST_STR_LEN(": ")); - buffer_append_string_buffer(b, &ds->value); + const uint32_t klen = buffer_string_length(&ds->key); + const uint32_t vlen = buffer_string_length(&ds->value); + if (0 == klen || 0 == vlen) continue; + buffer_append_str2(b, CONST_STR_LEN("\r\n"), ds->key.ptr, klen); + buffer_append_str2(b, CONST_STR_LEN(": "), ds->value.ptr, vlen); } buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n")); chunkqueue_append_buffer_commit(cq); diff --git a/src/data_string.c b/src/data_string.c index 3b81e33a..9afe6943 100644 --- a/src/data_string.c +++ b/src/data_string.c @@ -30,12 +30,11 @@ static int data_string_insert_dup(data_unset *dst, data_unset *src) { data_string *ds_dst = (data_string *)dst; data_string *ds_src = (data_string *)src; - if (!buffer_is_empty(&ds_dst->value)) { - buffer_append_string_len(&ds_dst->value, CONST_STR_LEN(", ")); - buffer_append_string_buffer(&ds_dst->value, &ds_src->value); - } else { + if (!buffer_is_empty(&ds_dst->value)) + buffer_append_str2(&ds_dst->value, CONST_STR_LEN(", "), + CONST_BUF_LEN(&ds_src->value)); + else buffer_copy_buffer(&ds_dst->value, &ds_src->value); - } src->fn->free(src); diff --git a/src/gw_backend.c b/src/gw_backend.c index 1de5b98f..55aa9190 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -375,8 +375,10 @@ static int gw_proc_sockaddr_init(gw_host * const host, gw_proc * const proc, log errno = EINVAL; return -1; } - buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("unix:")); - buffer_append_string_buffer(proc->connection_name, proc->unixsocket); + buffer_clear(proc->connection_name); + buffer_append_str2(proc->connection_name, + CONST_STR_LEN("unix:"), + CONST_BUF_LEN(proc->unixsocket)); } else { /*(note: name resolution here is *blocking* if IP string not supplied)*/ @@ -394,9 +396,11 @@ static int gw_proc_sockaddr_init(gw_host * const host, gw_proc * const proc, log sock_addr_inet_ntop_copy_buffer(h, &addr); host->family = sock_addr_get_family(&addr); } - buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:")); - buffer_append_string_buffer(proc->connection_name, host->host); - buffer_append_string_len(proc->connection_name, CONST_STR_LEN(":")); + buffer_clear(proc->connection_name); + buffer_append_str3(proc->connection_name, + CONST_STR_LEN("tcp:"), + CONST_BUF_LEN(host->host), + CONST_STR_LEN(":")); buffer_append_int(proc->connection_name, proc->port); } @@ -653,8 +657,9 @@ static void gw_proc_spawn(gw_host * const host, log_error_st * const errh, const if (buffer_string_is_empty(host->unixsocket)) { proc->port = host->port + proc->id; } else { - buffer_copy_buffer(proc->unixsocket, host->unixsocket); - buffer_append_string_len(proc->unixsocket, CONST_STR_LEN("-")); + buffer_clear(proc->unixsocket); + buffer_append_str2(proc->unixsocket, CONST_BUF_LEN(host->unixsocket), + CONST_STR_LEN("-")); buffer_append_int(proc->unixsocket, proc->id); } @@ -1628,9 +1633,9 @@ int gw_set_defaults_backend(server *srv, gw_plugin_data *p, const array *a, gw_p if (buffer_string_is_empty(host->unixsocket)) { proc->port = host->port + pno; } else { - buffer_copy_buffer(proc->unixsocket, host->unixsocket); - buffer_append_string_len(proc->unixsocket, - CONST_STR_LEN("-")); + buffer_append_str2(proc->unixsocket, + CONST_BUF_LEN(host->unixsocket), + CONST_STR_LEN("-")); buffer_append_int(proc->unixsocket, pno); } diff --git a/src/h2.c b/src/h2.c index 9560ab07..2d4db1ec 100644 --- a/src/h2.c +++ b/src/h2.c @@ -1997,8 +1997,8 @@ h2_send_headers (request_st * const r, connection * const con) && !buffer_string_is_empty(r->conf.server_tag)) { buffer * const b = chunk_buffer_acquire(); const uint32_t vlen = buffer_string_length(r->conf.server_tag); - buffer_copy_string_len(b, CONST_STR_LEN("server: ")); - buffer_append_string_len(b, CONST_BUF_LEN(r->conf.server_tag)); + buffer_append_str2(b, CONST_STR_LEN("server: "), + r->conf.server_tag->ptr, vlen); alen += 6+vlen+4; @@ -2144,14 +2144,11 @@ h2_send_1xx (request_st * const r, connection * const con) buffer_append_int(b, r->http_status); for (uint32_t i = 0; i < r->resp_headers.used; ++i) { const data_string * const ds = (data_string *)r->resp_headers.data[i]; - - if (buffer_string_is_empty(&ds->value)) continue; - if (buffer_string_is_empty(&ds->key)) continue; - - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); - buffer_append_string_buffer(b, &ds->key); - buffer_append_string_len(b, CONST_STR_LEN(": ")); - buffer_append_string_buffer(b, &ds->value); + const uint32_t klen = buffer_string_length(&ds->key); + const uint32_t vlen = buffer_string_length(&ds->value); + if (0 == klen || 0 == vlen) continue; + buffer_append_str2(b, CONST_STR_LEN("\r\n"), ds->key.ptr, klen); + buffer_append_str2(b, CONST_STR_LEN(": "), ds->value.ptr, vlen); } buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n")); diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 7d9afcd2..5805ee1d 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -104,8 +104,8 @@ int http_response_redirect_to_directory(request_st * const r, int status) { buffer_clear(o); /* XXX: store flag in global at startup? */ if (r->con->srv->srvconf.absolute_dir_redirect) { - buffer_copy_buffer(o, &r->uri.scheme); - buffer_append_string_len(o, CONST_STR_LEN("://")); + buffer_append_str2(o, CONST_BUF_LEN(&r->uri.scheme), + CONST_STR_LEN("://")); if (0 != http_response_buffer_append_authority(r, o)) { return -1; } @@ -125,10 +125,9 @@ int http_response_redirect_to_directory(request_st * const r, int status) { buffer_append_string_encoded(vb, CONST_BUF_LEN(&r->uri.path), ENCODING_REL_URI); buffer_append_string_len(vb, CONST_STR_LEN("/")); - if (!buffer_string_is_empty(&r->uri.query)) { - buffer_append_string_len(o, CONST_STR_LEN("?")); - buffer_append_string_buffer(o, &r->uri.query); - } + if (!buffer_string_is_empty(&r->uri.query)) + buffer_append_str2(vb, CONST_STR_LEN("?"), + CONST_BUF_LEN(&r->uri.query)); return 0; } diff --git a/src/http_header.c b/src/http_header.c index b0ada370..66609372 100644 --- a/src/http_header.c +++ b/src/http_header.c @@ -249,17 +249,15 @@ void http_header_response_append(request_st * const r, enum http_header_e id, co __attribute_cold__ static void http_header_response_insert_addtl(request_st * const r, enum http_header_e id, const char *k, uint32_t klen, buffer * const vb, uint32_t vlen) { UNUSED(id); - buffer_append_string_len(vb, CONST_STR_LEN("\r\n")); + char *h = buffer_string_prepare_append(vb, 2 + klen + vlen + 2); + buffer_append_str3(vb, CONST_STR_LEN("\r\n"), k, klen, CONST_STR_LEN(": ")); if (r->http_version >= HTTP_VERSION_2) { r->resp_header_repeated = 1; - char * const h = buffer_string_prepare_append(vb, klen + vlen + 2); - for (uint32_t i = 0; i < klen; ++i) - h[i] = !light_isupper(k[i]) ? k[i] : (k[i] | 0x20); - buffer_commit(vb, klen); + h += 2; + for (uint32_t i = 0; i < klen; ++i) { + if (light_isupper(h[i])) h[i] |= 0x20; + } } - else - buffer_append_string_len(vb, k, klen); - buffer_append_string_len(vb, CONST_STR_LEN(": ")); } void http_header_response_insert(request_st * const r, enum http_header_e id, const char *k, uint32_t klen, const char *v, uint32_t vlen) { diff --git a/src/http_range.c b/src/http_range.c index 52d6e17b..2414ca4f 100644 --- a/src/http_range.c +++ b/src/http_range.c @@ -207,8 +207,8 @@ http_range_multi (request_st * const r, http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type")); if (content_type) { - buffer_append_string_len(tb, CONST_STR_LEN("\r\nContent-Type: ")); - buffer_append_string_len(tb, CONST_BUF_LEN(content_type)); + buffer_append_str2(tb, CONST_STR_LEN("\r\nContent-Type: "), + CONST_BUF_LEN(content_type)); } buffer_append_string_len(tb,CONST_STR_LEN("\r\nContent-Range: bytes ")); const uint32_t prefix_len = buffer_string_length(tb); diff --git a/src/mod_ajp13.c b/src/mod_ajp13.c index c46778eb..13e5d026 100644 --- a/src/mod_ajp13.c +++ b/src/mod_ajp13.c @@ -729,9 +729,9 @@ ajp13_expand_headers (buffer * const b, handler_ctx * const hctx, uint32_t plen) else { if (plen < len+1) break; plen -= len+1; - buffer_append_string_len(b, CONST_STR_LEN("\n")); - buffer_append_string_len(b, (char *)ptr, len); - buffer_append_string_len(b, CONST_STR_LEN(": ")); + buffer_append_str3(b, CONST_STR_LEN("\n"), + (char *)ptr, len, + CONST_STR_LEN(": ")); ptr += len+1; } diff --git a/src/mod_auth.c b/src/mod_auth.c index 38ce0bf6..7cd920eb 100644 --- a/src/mod_auth.c +++ b/src/mod_auth.c @@ -720,12 +720,12 @@ static handler_t mod_auth_send_400_bad_request(request_st * const r) { static handler_t mod_auth_send_401_unauthorized_basic(request_st * const r, const buffer * const realm) { r->http_status = 401; r->handler_module = NULL; - buffer * const vb = + buffer_append_str3( http_header_response_set_ptr(r, HTTP_HEADER_WWW_AUTHENTICATE, - CONST_STR_LEN("WWW-Authenticate")); - buffer_copy_string_len(vb, CONST_STR_LEN("Basic realm=\"")); - buffer_append_string_buffer(vb, realm); - buffer_append_string_len(vb, CONST_STR_LEN("\", charset=\"UTF-8\"")); + CONST_STR_LEN("WWW-Authenticate")), + CONST_STR_LEN("Basic realm=\""), + CONST_BUF_LEN(realm), + CONST_STR_LEN("\", charset=\"UTF-8\"")); return HANDLER_FINISHED; } @@ -1133,14 +1133,15 @@ static void mod_auth_digest_www_authenticate(buffer *b, time_t cur_ts, const str buffer_clear(b); for (int i = 0; i < n; ++i) { - if (i > 0) { - buffer_append_string_len(b,CONST_STR_LEN("\r\nWWW-Authenticate: ")); - } - buffer_append_string_len(b, CONST_STR_LEN("Digest realm=\"")); - buffer_append_string_buffer(b, require->realm); - buffer_append_string_len(b, CONST_STR_LEN("\", charset=\"UTF-8\", algorithm=")); - buffer_append_string_len(b, algoname[i], algolen[i]); - buffer_append_string_len(b, CONST_STR_LEN(", nonce=\"")); + struct const_iovec iov[] = { + { CONST_STR_LEN("\r\nWWW-Authenticate: ") } + ,{ CONST_STR_LEN("Digest realm=\"") } + ,{ CONST_BUF_LEN(require->realm) } + ,{ CONST_STR_LEN("\", charset=\"UTF-8\", algorithm=") } + ,{ algoname[i], algolen[i] } + ,{ CONST_STR_LEN(", nonce=\"") } + }; + buffer_append_iovec(b, iov+(0==i), sizeof(iov)/sizeof(*iov)-(0==i)); mod_auth_append_nonce(b, cur_ts, require, algoid[i], NULL); buffer_append_string_len(b, CONST_STR_LEN("\", qop=\"auth\"")); if (nonce_stale) { diff --git a/src/mod_authn_mysql.c b/src/mod_authn_mysql.c index 4e023f73..b99a53c4 100644 --- a/src/mod_authn_mysql.c +++ b/src/mod_authn_mysql.c @@ -35,7 +35,6 @@ #include "plugin.h" #include "safe_memclear.h" -#include #include #include @@ -385,7 +384,7 @@ static handler_t mod_authn_mysql_query(request_st * const r, void *p_d, http_aut } do { - char q[1024], uname[512], urealm[512]; + char uname[512], urealm[512]; unsigned long mrc; if (ai->ulen > sizeof(uname)/2-1) @@ -415,19 +414,25 @@ static handler_t mod_authn_mysql_query(request_st * const r, void *p_d, http_aut if ((unsigned long)~0 == mrc) break; #endif - rc = snprintf(q, sizeof(q), - "SELECT %s FROM %s WHERE %s='%s' AND %s='%s'", - p->conf.auth_mysql_col_pass, - p->conf.auth_mysql_users_table, - p->conf.auth_mysql_col_user, - uname, - p->conf.auth_mysql_col_realm, - urealm); - - if (rc >= (int)sizeof(q)) { - rc = -1; - break; - } + buffer * const tb = r->tmp_buf; + buffer_clear(tb); + struct const_iovec iov[] = { + { CONST_STR_LEN("SELECT ") } + ,{ p->conf.auth_mysql_col_pass, strlen(p->conf.auth_mysql_col_pass) } + ,{ CONST_STR_LEN(" FROM ") } + ,{ p->conf.auth_mysql_users_table, strlen(p->conf.auth_mysql_users_table) } + ,{ CONST_STR_LEN(" WHERE ") } + ,{ p->conf.auth_mysql_col_user, strlen(p->conf.auth_mysql_col_user) } + ,{ CONST_STR_LEN("='") } + ,{ uname, strlen(uname) } + ,{ CONST_STR_LEN("' AND ") } + ,{ p->conf.auth_mysql_col_realm, strlen(p->conf.auth_mysql_col_realm) } + ,{ CONST_STR_LEN("='") } + ,{ urealm, strlen(urealm) } + ,{ CONST_STR_LEN("'") } + }; + buffer_append_iovec(tb, iov, sizeof(iov)/sizeof(*iov)); + char * const q = tb->ptr; /* for now we stay synchronous */ if (0 != mysql_query(p->mysql_conn, q)) { diff --git a/src/mod_deflate.c b/src/mod_deflate.c index 3833375e..c1208a77 100644 --- a/src/mod_deflate.c +++ b/src/mod_deflate.c @@ -291,12 +291,13 @@ static buffer * mod_deflate_cache_file_name(request_st * const r, const buffer * /* XXX: future: for shorter paths into the cache, we could checksum path, * and then shard it to avoid a huge single directory. * Alternatively, could use &r->uri.path, minus any - * (matching) &r->pathinfo suffix, with result url-encoded */ + * (matching) &r->pathinfo suffix, with result url-encoded + * Alternative, we could shard etag which is already our "checksum" */ buffer * const tb = r->tmp_buf; buffer_copy_buffer(tb, cache_dir); - buffer_append_string_len(tb, CONST_BUF_LEN(&r->physical.path)); - buffer_append_string_len(tb, CONST_STR_LEN("-")); - buffer_append_string_len(tb, etag->ptr+1, buffer_string_length(etag)-2); + buffer_append_path_len(tb, CONST_BUF_LEN(&r->physical.path)); + buffer_append_str2(tb, CONST_STR_LEN("-"), /*(strip surrounding '"')*/ + etag->ptr+1, buffer_string_length(etag)-2); return tb; } diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index ed3e2f36..eaf9d050 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -641,39 +641,41 @@ static const char js_simple_table_init_sort[] = \ "}\n"; static void http_dirlist_append_js_table_resort (buffer * const b, const request_st * const r) { - char col = '0'; - char ascending = '0'; + char init_sort[] = "0,0"; if (!buffer_string_is_empty(&r->uri.query)) { const char *qs = r->uri.query.ptr; do { if (qs[0] == 'C' && qs[1] == '=') { + const int col = 0; switch (qs[2]) { - case 'N': col = '0'; break; - case 'M': col = '1'; break; - case 'S': col = '2'; break; + case 'N': init_sort[col] = '0'; break; + case 'M': init_sort[col] = '1'; break; + case 'S': init_sort[col] = '2'; break; case 'T': - case 'D': col = '3'; break; + case 'D': init_sort[col] = '3'; break; default: break; } } else if (qs[0] == 'O' && qs[1] == '=') { + const int order = 2; switch (qs[2]) { - case 'A': ascending = '1'; break; - case 'D': ascending = '0'; break; + case 'A': init_sort[order] = '1'; break; + case 'D': init_sort[order] = '0'; break; default: break; } } } while ((qs = strchr(qs, '&')) && *++qs); } - buffer_append_string_len(b, CONST_STR_LEN("\n\n\n")); + struct const_iovec iov[] = { + { CONST_STR_LEN("\n\n\n") } + }; + buffer_append_iovec(b, iov, sizeof(iov)/sizeof(*iov)); } static void http_list_directory_header(request_st * const r, plugin_data * const p) { @@ -687,19 +689,21 @@ static void http_list_directory_header(request_st * const r, plugin_data * const "\n" )); if (!buffer_string_is_empty(p->conf.encoding)) { - buffer_append_string_len(out, CONST_STR_LEN("conf.encoding); - buffer_append_string_len(out, CONST_STR_LEN("\">\n")); + buffer_append_str3(out, + CONST_STR_LEN("conf.encoding), + CONST_STR_LEN("\">\n")); } buffer_append_string_len(out, CONST_STR_LEN("Index of ")); buffer_append_string_encoded(out, CONST_BUF_LEN(&r->uri.path), ENCODING_MINIMAL_XML); buffer_append_string_len(out, CONST_STR_LEN("\n")); if (!buffer_string_is_empty(p->conf.external_css)) { - buffer_append_string_len(out, CONST_STR_LEN("")); - buffer_append_string_len(out, CONST_STR_LEN("conf.external_css); - buffer_append_string_len(out, CONST_STR_LEN("\">\n")); + buffer_append_str3(out, + CONST_STR_LEN("" + "conf.external_css), + CONST_STR_LEN("\">\n")); } else { buffer_append_string_len(out, CONST_STR_LEN( "