From: Frederic Lecaille Date: Fri, 16 Jan 2026 10:06:10 +0000 (+0100) Subject: WIP: httpterm: add httpterm sources X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9afc83a45f2a4089ec47d79252feb5d77a076375;p=thirdparty%2Fhaproxy.git WIP: httpterm: add httpterm sources --- diff --git a/Makefile b/Makefile index 0bb4557f7..88ba6ad5c 100644 --- a/Makefile +++ b/Makefile @@ -951,11 +951,12 @@ all: @echo @exit 1 else -all: dev/flags/flags haproxy $(EXTRA) +all: dev/flags/flags haproxy httpterm $(EXTRA) endif # obsolete targets endif # TARGET OBJS = +HTTPTERM_OBJS = ifneq ($(EXTRA_OBJS),) OBJS += $(EXTRA_OBJS) @@ -1002,12 +1003,15 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \ src/ebsttree.o src/freq_ctr.o src/systemd.o src/init.o \ src/http_acl.o src/dict.o src/dgram.o src/pipe.o \ src/hpack-huff.o src/hpack-enc.o src/ebtree.o src/hash.o \ - src/httpclient_cli.o src/version.o src/ncbmbuf.o src/ech.o + src/httpclient_cli.o src/version.o src/ncbmbuf.o src/ech.o \ + src/httpterm.o ifneq ($(TRACE),) OBJS += src/calltrace.o endif +HTTPTERM_OBJS += $(OBJS) + # Used only for forced dependency checking. May be cleared during development. INCLUDES = $(wildcard include/*/*.h) DEP = $(INCLUDES) .build_opts @@ -1055,6 +1059,9 @@ endif # non-empty target haproxy: $(OPTIONS_OBJS) $(OBJS) $(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS) +httpterm: $(OPTIONS_OBJS) $(HTTPTERM_OBJS) + $(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS) + objsize: haproxy $(Q)objdump -t $^|grep ' g '|grep -F '.text'|awk '{print $$5 FS $$6}'|sort diff --git a/include/haproxy/hstream-t.h b/include/haproxy/hstream-t.h new file mode 100644 index 000000000..5919c1f6b --- /dev/null +++ b/include/haproxy/hstream-t.h @@ -0,0 +1,35 @@ +#ifndef _HAPROXY_HSTREAM_T_H +#define _HAPROXY_HSTREAM_T_H + +#include +#include +#include + +/* httpterm stream */ +struct hstream { + enum obj_type obj_type; + struct session *sess; + + struct stconn *sc; + struct task *task; + + struct buffer req; + struct buffer res; + unsigned long long to_write; /* #of response data bytes to write after headers */ + /* Wait list for buffer allocation */ + struct buffer_wait buf_wait; + + int flags; + + int ka; /* .0: keep-alive .1: forced .2: http/1.1, .3: was_reused */ + unsigned long long req_size; /* values passed in the URI to override the server's */ + unsigned long long req_body; /* remaining body to be consumed from the request */ + int req_code; + int req_cache, req_time; + int req_chunked; + int req_random; + int res_before_req; + enum http_meth_t req_meth; +}; + +#endif /* _HAPROXY_HSTREAM_T_H */ diff --git a/include/haproxy/hstream.h b/include/haproxy/hstream.h new file mode 100644 index 000000000..97e4d60e1 --- /dev/null +++ b/include/haproxy/hstream.h @@ -0,0 +1,13 @@ +#ifndef _HAPROXY_HSTREAM_H +#define _HAPROXY_HSTREAM_H + +#include +#include + +void init_httpterm_cfg(int argc, char **argv, struct cfgfile *cfg); +struct task *sc_hstream_io_cb(struct task *t, void *ctx, unsigned int state); +int hstream_wake(struct stconn *sc); +void hstream_shutdown(struct stconn *sc); +void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input); + +#endif /* _HAPROXY_HSTREAM_H */ diff --git a/include/haproxy/obj_type-t.h b/include/haproxy/obj_type-t.h index da2efbf86..37c4a358b 100644 --- a/include/haproxy/obj_type-t.h +++ b/include/haproxy/obj_type-t.h @@ -46,6 +46,7 @@ enum obj_type { #ifdef USE_QUIC OBJ_TYPE_DGRAM, /* object is a struct quic_dgram */ #endif + OBJ_TYPE_HTTPTERM, /* object is a struct hstream */ OBJ_TYPE_ENTRIES /* last one : number of entries */ } __attribute__((packed)) ; diff --git a/include/haproxy/obj_type.h b/include/haproxy/obj_type.h index 233f9d7ad..cc01c54f4 100644 --- a/include/haproxy/obj_type.h +++ b/include/haproxy/obj_type.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -189,6 +190,19 @@ static inline struct check *objt_check(enum obj_type *t) return __objt_check(t); } +static inline struct hstream *__objt_hstream(enum obj_type *t) +{ + return container_of(t, struct hstream, obj_type); +} + +static inline struct hstream *objt_hstream(enum obj_type *t) +{ + if (!t || *t != OBJ_TYPE_HTTPTERM) + return NULL; + + return __objt_hstream(t); +} + #ifdef USE_QUIC static inline struct quic_dgram *__objt_dgram(enum obj_type *t) { diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 0b8ce6d38..cb33d0dee 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -411,6 +411,7 @@ struct proxy { int redispatch_after; /* number of retries before redispatch */ unsigned down_time; /* total time the proxy was down */ int (*accept)(struct stream *s); /* application layer's accept() */ + void *(*stream_new_from_sc)(struct session *sess, struct stconn *sc, struct buffer *in); /* stream connector creator function from mux stream connector */ struct conn_src conn_src; /* connection source settings */ enum obj_type *default_target; /* default target to use for accepted streams or NULL */ struct proxy *next; diff --git a/include/haproxy/stconn.h b/include/haproxy/stconn.h index 61ce17c39..226bc21d1 100644 --- a/include/haproxy/stconn.h +++ b/include/haproxy/stconn.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -45,10 +46,12 @@ void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode); struct stconn *sc_new_from_endp(struct sedesc *sedesc, struct session *sess, struct buffer *input); struct stconn *sc_new_from_strm(struct stream *strm, unsigned int flags); struct stconn *sc_new_from_check(struct check *check, unsigned int flags); +struct stconn *sc_new_from_httpterm(struct sedesc *sd, struct session *sess, struct buffer *input); void sc_free(struct stconn *sc); int sc_attach_mux(struct stconn *sc, void *target, void *ctx); int sc_attach_strm(struct stconn *sc, struct stream *strm); +int sc_attach_hstream(struct stconn *sc, struct hstream *hs); void sc_destroy(struct stconn *sc); int sc_reset_endp(struct stconn *sc); @@ -331,6 +334,21 @@ static inline struct check *sc_check(const struct stconn *sc) return NULL; } +/* Returns the httpterm stream from a sc if the application is a + * httpterm stream. Otherwise NULL is returned. __sc_hstream() returns the httpterm + * stream without any control while sc_hstream() check the application type. + */ +static inline struct hstream *__sc_hstream(const struct stconn *sc) +{ + return __objt_hstream(sc->app); +} +static inline struct hstream *sc_hstream(const struct stconn *sc) +{ + if (obj_type(sc->app) == OBJ_TYPE_HTTPTERM) + return __objt_hstream(sc->app); + return NULL; +} + /* Returns the name of the application layer's name for the stconn, * or "NONE" when none is attached. */ diff --git a/include/haproxy/stream.h b/include/haproxy/stream.h index 78d828fb2..46464f860 100644 --- a/include/haproxy/stream.h +++ b/include/haproxy/stream.h @@ -59,7 +59,7 @@ extern struct pool_head *pool_head_uniqueid; extern struct data_cb sess_conn_cb; -struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer *input); +void *stream_new(struct session *sess, struct stconn *sc, struct buffer *input); void stream_free(struct stream *s); int stream_upgrade_from_sc(struct stconn *sc, struct buffer *input); int stream_set_http_mode(struct stream *s, const struct mux_proto_list *mux_proto); diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 68bf93731..9ae7b183c 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -705,6 +706,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) err_code |= ERR_ALERT | ERR_FATAL; goto out; } + else if (strcmp(args[1], "httpterm") == 0 && (curproxy->cap & PR_CAP_FE)) { + curproxy->mode = PR_MODE_HTTP; + curproxy->stream_new_from_sc = hstream_new; + } else { ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]); err_code |= ERR_ALERT | ERR_FATAL; diff --git a/src/httpterm.c b/src/httpterm.c new file mode 100644 index 000000000..6faa46dcc --- /dev/null +++ b/src/httpterm.c @@ -0,0 +1,1126 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +DECLARE_TYPED_POOL(pool_head_hstream, "hstream", struct hstream); + +#define HTTPTERM_VERSION "1.7.9" +#define HTTPTERM_DATE "2020/06/28" + +#define HS_ST_IN_ALLOC 0x0001 +#define HS_ST_OUT_ALLOC 0x0002 +#define HS_ST_CONN_ERROR 0x0004 +#define HS_ST_HTTP_GOT_HDRS 0x0008 +#define HS_ST_HTTP_HELP 0x0010 +#define HS_ST_HTTP_EXPECT 0x0020 +#define HS_ST_HTTP_RESP_SL_SENT 0x0040 +#define HS_ST_HTTP_RESP_SENT 0x0080 + +static int httpterm_debug; +const char *HTTP_HELP = + "HTTPTerm-" HTTPTERM_VERSION " - " HTTPTERM_DATE "\n" + "All integer argument values are in the form [digits]*[kmgr] (r=random(0..1)).\n" + "The following arguments are supported to override the default objects :\n" + " - /?s= return bytes.\n" + " E.g. /?s=20k\n" + " - /?r= present as the HTTP return code.\n" + " E.g. /?r=404\n" + " - /?c= set the return as not cacheable if <1.\n" + " E.g. /?c=0\n" + " - /?A= drain the request body before sending the response.\n" + " E.g. /?A=1\n" + " - /?C= force the response to use close if >0.\n" + " E.g. /?C=1\n" + " - /?K= force the response to use keep-alive if >0.\n" + " E.g. /?K=1\n" + " - /?t=