Add cfgparse-mux_h1.c new C file to avoid compiling such code for ha-inject.
Move mux_h1.c parsing functions to this new file.
src/version.o src/ncbmbuf.o src/ech.o \
OBJS += $(OBJS_COMMON) src/acl.o src/cfgdiag.o src/cfgparse.o \
- src/cfgparse-global.o src/cfgparse-listen.o src/cfgparse-mux_h2.o \
+ src/cfgparse-global.o src/cfgparse-listen.o src/cfgparse-mux_h1.o \
+ src/cfgparse-mux_h2.o \
src/cfgparse-tcp.o src/cfgparse-thread.o \
src/cfgparse-unix.o src/check.o src/dns.o src/dns_ring.o src/event_hdl.o \
src/extcheck.o src/filters.o src/flt_bwlim.o src/flt_http_comp.o \
#ifndef _HAPROXY_MUX_H1_T_H
#define _HAPROXY_MUX_H1_T_H
+#include <import/ist.h>
+
#include <haproxy/api-t.h>
#include <haproxy/show_flags-t.h>
#define H1S_F_BODYLESS_REQ 0x00040000 /* Bodyless request message */
#define H1S_F_BODYLESS_RESP 0x00080000 /* Bodyless response message */
+/* An entry in a headers map */
+struct h1_hdr_entry {
+ struct ist name;
+ struct ebpt_node node;
+};
+
+/* Map of headers used to convert outgoing headers */
+struct h1_hdrs_map {
+ char *name;
+ struct eb_root map;
+};
+
+extern struct h1_hdrs_map hdrs_map;
+extern int accept_payload_with_any_method;
+
/* This function is used to report flags in debugging tools. Please reflect
* below any single-bit flag addition above in the same order via the
* __APPEND_FLAG macro. The new end of the buffer is returned.
--- /dev/null
+#include <string.h>
+
+#include <import/ebistree.h>
+
+#include <haproxy/api.h>
+#include <haproxy/cfgparse.h>
+#include <haproxy/errors.h>
+#include <haproxy/mux_h1-t.h>
+#include <haproxy/tools.h>
+
+/* Add an entry in the headers map. Returns -1 on error and 0 on success. */
+static int add_hdr_case_adjust(const char *from, const char *to, char **err)
+{
+ struct h1_hdr_entry *entry;
+
+ /* Be sure there is a non-empty <to> */
+ if (!strlen(to)) {
+ memprintf(err, "expect <to>");
+ return -1;
+ }
+
+ /* Be sure only the case differs between <from> and <to> */
+ if (strcasecmp(from, to) != 0) {
+ memprintf(err, "<from> and <to> must not differ except the case");
+ return -1;
+ }
+
+ /* Be sure <from> does not already existsin the tree */
+ if (ebis_lookup(&hdrs_map.map, from)) {
+ memprintf(err, "duplicate entry '%s'", from);
+ return -1;
+ }
+
+ /* Create the entry and insert it in the tree */
+ entry = malloc(sizeof(*entry));
+ if (!entry) {
+ memprintf(err, "out of memory");
+ return -1;
+ }
+
+ entry->node.key = strdup(from);
+ entry->name = ist(strdup(to));
+ if (!entry->node.key || !isttest(entry->name)) {
+ free(entry->node.key);
+ istfree(&entry->name);
+ free(entry);
+ memprintf(err, "out of memory");
+ return -1;
+ }
+ ebis_insert(&hdrs_map.map, &entry->node);
+ return 0;
+}
+
+static void h1_hdeaders_case_adjust_deinit()
+{
+ struct ebpt_node *node, *next;
+ struct h1_hdr_entry *entry;
+
+ node = ebpt_first(&hdrs_map.map);
+ while (node) {
+ next = ebpt_next(node);
+ ebpt_delete(node);
+ entry = container_of(node, struct h1_hdr_entry, node);
+ free(entry->node.key);
+ istfree(&entry->name);
+ free(entry);
+ node = next;
+ }
+ free(hdrs_map.name);
+}
+
+static int cfg_h1_headers_case_adjust_postparser()
+{
+ FILE *file = NULL;
+ char *c, *key_beg, *key_end, *value_beg, *value_end;
+ char *err;
+ int rc, line = 0, err_code = 0;
+
+ if (!hdrs_map.name)
+ goto end;
+
+ file = fopen(hdrs_map.name, "r");
+ if (!file) {
+ ha_alert("h1-headers-case-adjust-file '%s': failed to open file.\n",
+ hdrs_map.name);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto end;
+ }
+
+ /* now parse all lines. The file may contain only two header name per
+ * line, separated by spaces. All heading and trailing spaces will be
+ * ignored. Lines starting with a # are ignored.
+ */
+ while (fgets(trash.area, trash.size, file) != NULL) {
+ line++;
+ c = trash.area;
+
+ /* strip leading spaces and tabs */
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ /* ignore emptu lines, or lines beginning with a dash */
+ if (*c == '#' || *c == '\0' || *c == '\r' || *c == '\n')
+ continue;
+
+ /* look for the end of the key */
+ key_beg = c;
+ while (*c != '\0' && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r')
+ c++;
+ key_end = c;
+
+ /* strip middle spaces and tabs */
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ /* look for the end of the value, it is the end of the line */
+ value_beg = c;
+ while (*c && *c != '\n' && *c != '\r')
+ c++;
+ value_end = c;
+
+ /* trim possibly trailing spaces and tabs */
+ while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t'))
+ value_end--;
+
+ /* set final \0 and check entries */
+ *key_end = '\0';
+ *value_end = '\0';
+
+ err = NULL;
+ rc = add_hdr_case_adjust(key_beg, value_beg, &err);
+ if (rc < 0) {
+ ha_alert("h1-headers-case-adjust-file '%s' : %s at line %d.\n",
+ hdrs_map.name, err, line);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ free(err);
+ goto end;
+ }
+ if (rc > 0) {
+ ha_warning("h1-headers-case-adjust-file '%s' : %s at line %d.\n",
+ hdrs_map.name, err, line);
+ err_code |= ERR_WARN;
+ free(err);
+ }
+ }
+
+ end:
+ if (file)
+ fclose(file);
+ hap_register_post_deinit(h1_hdeaders_case_adjust_deinit);
+ return err_code;
+}
+
+/* config parser for global "h1-accept-payload_=-with-any-method" */
+static int cfg_parse_h1_accept_payload_with_any_method(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(0, args, err, NULL))
+ return -1;
+
+ accept_payload_with_any_method = 1;
+ return 0;
+}
+
+
+/* config parser for global "h1-header-case-adjust" */
+static int cfg_parse_h1_header_case_adjust(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(2, args, err, NULL))
+ return -1;
+ if (!*(args[1]) || !*(args[2])) {
+ memprintf(err, "'%s' expects <from> and <to> as argument.", args[0]);
+ return -1;
+ }
+ return add_hdr_case_adjust(args[1], args[2], err);
+}
+
+/* config parser for global "h1-headers-case-adjust-file" */
+static int cfg_parse_h1_headers_case_adjust_file(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(1, args, err, NULL))
+ return -1;
+ if (!*(args[1])) {
+ memprintf(err, "'%s' expects <file> as argument.", args[0]);
+ return -1;
+ }
+ free(hdrs_map.name);
+ hdrs_map.name = strdup(args[1]);
+ if (!hdrs_map.name) {
+ memprintf(err, "'%s %s' : out of memory", args[0], args[1]);
+ return -1;
+ }
+ return 0;
+}
+
+/* config parser for global "tune.h1.zero-copy-fwd-recv" */
+static int cfg_parse_h1_zero_copy_fwd_rcv(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(1, args, err, NULL))
+ return -1;
+
+ if (strcmp(args[1], "on") == 0)
+ global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_RCV;
+ else if (strcmp(args[1], "off") == 0)
+ global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_RCV;
+ else {
+ memprintf(err, "'%s' expects 'on' or 'off'.", args[0]);
+ return -1;
+ }
+ return 0;
+}
+
+/* config parser for global "tune.h1.zero-copy-fwd-send" */
+static int cfg_parse_h1_zero_copy_fwd_snd(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(1, args, err, NULL))
+ return -1;
+
+ if (strcmp(args[1], "on") == 0)
+ global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_SND;
+ else if (strcmp(args[1], "off") == 0)
+ global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_SND;
+ else {
+ memprintf(err, "'%s' expects 'on' or 'off'.", args[0]);
+ return -1;
+ }
+ return 0;
+}
+
+/* config keyword parsers */
+static struct cfg_kw_list cfg_kws = {{ }, {
+ { CFG_GLOBAL, "h1-accept-payload-with-any-method", cfg_parse_h1_accept_payload_with_any_method },
+ { CFG_GLOBAL, "h1-case-adjust", cfg_parse_h1_header_case_adjust },
+ { CFG_GLOBAL, "h1-case-adjust-file", cfg_parse_h1_headers_case_adjust_file },
+ { CFG_GLOBAL, "tune.h1.zero-copy-fwd-recv", cfg_parse_h1_zero_copy_fwd_rcv },
+ { CFG_GLOBAL, "tune.h1.zero-copy-fwd-send", cfg_parse_h1_zero_copy_fwd_snd },
+ { 0, NULL, NULL },
+ }
+};
+
+INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+REGISTER_CONFIG_POSTPARSER("h1-headers-map", cfg_h1_headers_case_adjust_postparser);
+
+
+
char ws_key[25]; /* websocket handshake key */
};
-/* Map of headers used to convert outgoing headers */
-struct h1_hdrs_map {
- char *name;
- struct eb_root map;
-};
-
-/* An entry in a headers map */
-struct h1_hdr_entry {
- struct ist name;
- struct ebpt_node node;
-};
-
/* Declare the headers map */
-static struct h1_hdrs_map hdrs_map = { .name = NULL, .map = EB_ROOT };
-static int accept_payload_with_any_method = 0;
+struct h1_hdrs_map hdrs_map = { .name = NULL, .map = EB_ROOT };
+int accept_payload_with_any_method = 0;
/* trace source and events */
static void h1_trace(enum trace_level level, uint64_t mask,
}
-/* Add an entry in the headers map. Returns -1 on error and 0 on success. */
-static int add_hdr_case_adjust(const char *from, const char *to, char **err)
-{
- struct h1_hdr_entry *entry;
-
- /* Be sure there is a non-empty <to> */
- if (!strlen(to)) {
- memprintf(err, "expect <to>");
- return -1;
- }
-
- /* Be sure only the case differs between <from> and <to> */
- if (strcasecmp(from, to) != 0) {
- memprintf(err, "<from> and <to> must not differ except the case");
- return -1;
- }
-
- /* Be sure <from> does not already existsin the tree */
- if (ebis_lookup(&hdrs_map.map, from)) {
- memprintf(err, "duplicate entry '%s'", from);
- return -1;
- }
-
- /* Create the entry and insert it in the tree */
- entry = malloc(sizeof(*entry));
- if (!entry) {
- memprintf(err, "out of memory");
- return -1;
- }
-
- entry->node.key = strdup(from);
- entry->name = ist(strdup(to));
- if (!entry->node.key || !isttest(entry->name)) {
- free(entry->node.key);
- istfree(&entry->name);
- free(entry);
- memprintf(err, "out of memory");
- return -1;
- }
- ebis_insert(&hdrs_map.map, &entry->node);
- return 0;
-}
-
/* Migrate the the connection to the current thread.
* Return 0 if successful, non-zero otherwise.
* Expected to be called with the old thread lock held.
return -1;
}
-
-static void h1_hdeaders_case_adjust_deinit()
-{
- struct ebpt_node *node, *next;
- struct h1_hdr_entry *entry;
-
- node = ebpt_first(&hdrs_map.map);
- while (node) {
- next = ebpt_next(node);
- ebpt_delete(node);
- entry = container_of(node, struct h1_hdr_entry, node);
- free(entry->node.key);
- istfree(&entry->name);
- free(entry);
- node = next;
- }
- free(hdrs_map.name);
-}
-
-static int cfg_h1_headers_case_adjust_postparser()
-{
- FILE *file = NULL;
- char *c, *key_beg, *key_end, *value_beg, *value_end;
- char *err;
- int rc, line = 0, err_code = 0;
-
- if (!hdrs_map.name)
- goto end;
-
- file = fopen(hdrs_map.name, "r");
- if (!file) {
- ha_alert("h1-headers-case-adjust-file '%s': failed to open file.\n",
- hdrs_map.name);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto end;
- }
-
- /* now parse all lines. The file may contain only two header name per
- * line, separated by spaces. All heading and trailing spaces will be
- * ignored. Lines starting with a # are ignored.
- */
- while (fgets(trash.area, trash.size, file) != NULL) {
- line++;
- c = trash.area;
-
- /* strip leading spaces and tabs */
- while (*c == ' ' || *c == '\t')
- c++;
-
- /* ignore emptu lines, or lines beginning with a dash */
- if (*c == '#' || *c == '\0' || *c == '\r' || *c == '\n')
- continue;
-
- /* look for the end of the key */
- key_beg = c;
- while (*c != '\0' && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r')
- c++;
- key_end = c;
-
- /* strip middle spaces and tabs */
- while (*c == ' ' || *c == '\t')
- c++;
-
- /* look for the end of the value, it is the end of the line */
- value_beg = c;
- while (*c && *c != '\n' && *c != '\r')
- c++;
- value_end = c;
-
- /* trim possibly trailing spaces and tabs */
- while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t'))
- value_end--;
-
- /* set final \0 and check entries */
- *key_end = '\0';
- *value_end = '\0';
-
- err = NULL;
- rc = add_hdr_case_adjust(key_beg, value_beg, &err);
- if (rc < 0) {
- ha_alert("h1-headers-case-adjust-file '%s' : %s at line %d.\n",
- hdrs_map.name, err, line);
- err_code |= ERR_ALERT | ERR_FATAL;
- free(err);
- goto end;
- }
- if (rc > 0) {
- ha_warning("h1-headers-case-adjust-file '%s' : %s at line %d.\n",
- hdrs_map.name, err, line);
- err_code |= ERR_WARN;
- free(err);
- }
- }
-
- end:
- if (file)
- fclose(file);
- hap_register_post_deinit(h1_hdeaders_case_adjust_deinit);
- return err_code;
-}
-
-/* config parser for global "h1-accept-payload_=-with-any-method" */
-static int cfg_parse_h1_accept_payload_with_any_method(char **args, int section_type, struct proxy *curpx,
- const struct proxy *defpx, const char *file, int line,
- char **err)
-{
- if (too_many_args(0, args, err, NULL))
- return -1;
- accept_payload_with_any_method = 1;
- return 0;
-}
-
-
-/* config parser for global "h1-header-case-adjust" */
-static int cfg_parse_h1_header_case_adjust(char **args, int section_type, struct proxy *curpx,
- const struct proxy *defpx, const char *file, int line,
- char **err)
-{
- if (too_many_args(2, args, err, NULL))
- return -1;
- if (!*(args[1]) || !*(args[2])) {
- memprintf(err, "'%s' expects <from> and <to> as argument.", args[0]);
- return -1;
- }
- return add_hdr_case_adjust(args[1], args[2], err);
-}
-
-/* config parser for global "h1-headers-case-adjust-file" */
-static int cfg_parse_h1_headers_case_adjust_file(char **args, int section_type, struct proxy *curpx,
- const struct proxy *defpx, const char *file, int line,
- char **err)
-{
- if (too_many_args(1, args, err, NULL))
- return -1;
- if (!*(args[1])) {
- memprintf(err, "'%s' expects <file> as argument.", args[0]);
- return -1;
- }
- free(hdrs_map.name);
- hdrs_map.name = strdup(args[1]);
- if (!hdrs_map.name) {
- memprintf(err, "'%s %s' : out of memory", args[0], args[1]);
- return -1;
- }
- return 0;
-}
-
-/* config parser for global "tune.h1.zero-copy-fwd-recv" */
-static int cfg_parse_h1_zero_copy_fwd_rcv(char **args, int section_type, struct proxy *curpx,
- const struct proxy *defpx, const char *file, int line,
- char **err)
-{
- if (too_many_args(1, args, err, NULL))
- return -1;
-
- if (strcmp(args[1], "on") == 0)
- global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_RCV;
- else if (strcmp(args[1], "off") == 0)
- global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_RCV;
- else {
- memprintf(err, "'%s' expects 'on' or 'off'.", args[0]);
- return -1;
- }
- return 0;
-}
-
-/* config parser for global "tune.h1.zero-copy-fwd-send" */
-static int cfg_parse_h1_zero_copy_fwd_snd(char **args, int section_type, struct proxy *curpx,
- const struct proxy *defpx, const char *file, int line,
- char **err)
-{
- if (too_many_args(1, args, err, NULL))
- return -1;
-
- if (strcmp(args[1], "on") == 0)
- global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_SND;
- else if (strcmp(args[1], "off") == 0)
- global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_SND;
- else {
- memprintf(err, "'%s' expects 'on' or 'off'.", args[0]);
- return -1;
- }
- return 0;
-}
-
-/* config keyword parsers */
-static struct cfg_kw_list cfg_kws = {{ }, {
- { CFG_GLOBAL, "h1-accept-payload-with-any-method", cfg_parse_h1_accept_payload_with_any_method },
- { CFG_GLOBAL, "h1-case-adjust", cfg_parse_h1_header_case_adjust },
- { CFG_GLOBAL, "h1-case-adjust-file", cfg_parse_h1_headers_case_adjust_file },
- { CFG_GLOBAL, "tune.h1.zero-copy-fwd-recv", cfg_parse_h1_zero_copy_fwd_rcv },
- { CFG_GLOBAL, "tune.h1.zero-copy-fwd-send", cfg_parse_h1_zero_copy_fwd_snd },
- { 0, NULL, NULL },
- }
-};
-
-INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
-REGISTER_CONFIG_POSTPARSER("h1-headers-map", cfg_h1_headers_case_adjust_postparser);
-
-
/****************************************/
/* MUX initialization and instantiation */
/****************************************/