mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-03-15 20:12:08 +01:00
MINOR: haterm: add haterm HTTP server
Contrary to haproxy, httpterm does not support all the HTTP protocols. Furthermore, it has become easier to handle inbound/outbound connections / streams since the rework done at conn_stream level. This patch implements httpterm HTTP server services into haproxy. To do so, it proceeds the same way as for the TCP checks which use only one stream connector, but on frontend side. The makefile is modified to handle haterm.c in additions to all the C files for haproxy to build new haterm program into haproxy, the haterm server also instantiates a haterm stream (hstream struct) attached to a stream connector for each incoming connection without backend stream connector. This is the role of sc_new_from_endp() called by the muxes to instantiate streams/hstreams. As for stream_new(), hstream_new() instantiates a task named process_hstream() (see haterm.c) which has the same role as process_stream() but for haterm streams. haterm into haproxy takes advantage of the HTTP muxes and HTX API to support all the HTTP protocols supported by haproxy.
This commit is contained in:
parent
2bf091e9da
commit
c9d47804d1
2
Makefile
2
Makefile
@ -1003,7 +1003,7 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.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/cfgparse-peers.o
|
||||
src/cfgparse-peers.o src/haterm.o
|
||||
|
||||
ifneq ($(TRACE),)
|
||||
OBJS += src/calltrace.o
|
||||
|
||||
@ -9307,6 +9307,9 @@ mode { tcp|http|log|spop }
|
||||
processing and switching will be possible. This is the mode which
|
||||
brings HAProxy most of its value.
|
||||
|
||||
haterm The frontend will work in haterm HTTP benchmark mode. This is
|
||||
not supported by backends. See doc/haterm.txt for details.
|
||||
|
||||
log When used in a backend section, it will turn the backend into a
|
||||
log backend. Such backend can be used as a log destination for
|
||||
any "log" directive by using the "backend@<name>" syntax. Log
|
||||
|
||||
36
include/haproxy/hstream-t.h
Normal file
36
include/haproxy/hstream-t.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef _HAPROXY_HSTREAM_T_H
|
||||
#define _HAPROXY_HSTREAM_T_H
|
||||
|
||||
#include <haproxy/dynbuf-t.h>
|
||||
#include <haproxy/http-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
|
||||
/* hastream 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 */
|
||||
struct buffer_wait buf_wait; /* Wait list for buffer allocation */
|
||||
|
||||
int flags;
|
||||
|
||||
int ka; /* .0: keep-alive .1: forced .2: http/1.1, .3: was_reused */
|
||||
int req_cache;
|
||||
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 res_wait; /* time to wait before replying in ms */
|
||||
int res_time;
|
||||
int req_chunked;
|
||||
int req_random;
|
||||
int req_after_res; /* Drain the request body after having sent the response */
|
||||
enum http_meth_t req_meth;
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_HSTREAM_T_H */
|
||||
12
include/haproxy/hstream.h
Normal file
12
include/haproxy/hstream.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _HAPROXY_HSTREAM_H
|
||||
#define _HAPROXY_HSTREAM_H
|
||||
|
||||
#include <haproxy/cfgparse.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
|
||||
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 */
|
||||
@ -46,6 +46,7 @@ enum obj_type {
|
||||
#ifdef USE_QUIC
|
||||
OBJ_TYPE_DGRAM, /* object is a struct quic_dgram */
|
||||
#endif
|
||||
OBJ_TYPE_HATERM, /* object is a struct hstream */
|
||||
OBJ_TYPE_ENTRIES /* last one : number of entries */
|
||||
} __attribute__((packed)) ;
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <haproxy/applet-t.h>
|
||||
#include <haproxy/check-t.h>
|
||||
#include <haproxy/connection-t.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
#include <haproxy/listener-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/pool.h>
|
||||
@ -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_HATERM)
|
||||
return NULL;
|
||||
|
||||
return __objt_hstream(t);
|
||||
}
|
||||
|
||||
#ifdef USE_QUIC
|
||||
static inline struct quic_dgram *__objt_dgram(enum obj_type *t)
|
||||
{
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
#include <haproxy/htx-t.h>
|
||||
#include <haproxy/obj_type.h>
|
||||
#include <haproxy/stconn-t.h>
|
||||
@ -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_haterm(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 haterm stream from a sc if the application is a
|
||||
* haterm stream. Otherwise NULL is returned. __sc_hstream() returns the haterm
|
||||
* 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_HATERM)
|
||||
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.
|
||||
*/
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <haproxy/compression-t.h>
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/extcheck.h>
|
||||
#include <haproxy/hstream.h>
|
||||
#include <haproxy/http_ana.h>
|
||||
#include <haproxy/http_htx.h>
|
||||
#include <haproxy/http_ext.h>
|
||||
@ -645,9 +646,22 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
|
||||
mode = str_to_proxy_mode(args[1]);
|
||||
if (!mode) {
|
||||
ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
if (strcmp(args[1], "haterm") == 0) {
|
||||
if (!(curproxy->cap & PR_CAP_FE)) {
|
||||
ha_alert("parsing [%s:%d] : mode haterm is only applicable"
|
||||
" on proxies with frontend capability.\n", file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if ((mode == PR_MODE_SYSLOG || mode == PR_MODE_SPOP) &&
|
||||
!(curproxy->cap & PR_CAP_BE)) {
|
||||
|
||||
1028
src/haterm.c
Normal file
1028
src/haterm.c
Normal file
File diff suppressed because it is too large
Load Diff
34
src/stconn.c
34
src/stconn.c
@ -16,6 +16,7 @@
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/check.h>
|
||||
#include <haproxy/filters.h>
|
||||
#include <haproxy/hstream.h>
|
||||
#include <haproxy/http_ana.h>
|
||||
#include <haproxy/pipe.h>
|
||||
#include <haproxy/pool.h>
|
||||
@ -91,6 +92,15 @@ struct sc_app_ops sc_app_check_ops = {
|
||||
.name = "CHCK",
|
||||
};
|
||||
|
||||
struct sc_app_ops sc_app_hstream_ops = {
|
||||
.chk_rcv = NULL,
|
||||
.chk_snd = NULL,
|
||||
.abort = NULL,
|
||||
.shutdown= NULL,
|
||||
.wake = hstream_wake,
|
||||
.name = "HTERM",
|
||||
};
|
||||
|
||||
/* Initializes an endpoint */
|
||||
void sedesc_init(struct sedesc *sedesc)
|
||||
{
|
||||
@ -415,6 +425,30 @@ int sc_attach_strm(struct stconn *sc, struct stream *strm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attach a stconn to a haterm layer and sets the relevant
|
||||
* callbacks. Returns -1 on error and 0 on success. SE_FL_ORPHAN flag is
|
||||
* removed. This function is called by a haterm stream when it is created
|
||||
* to attach it on the stream connector on the client side.
|
||||
*/
|
||||
int sc_attach_hstream(struct stconn *sc, struct hstream *hs)
|
||||
{
|
||||
BUG_ON(!sc_ep_test(sc, SE_FL_T_MUX));
|
||||
|
||||
sc->app = &hs->obj_type;
|
||||
sc_ep_clr(sc, SE_FL_ORPHAN);
|
||||
sc_ep_report_read_activity(sc);
|
||||
sc->wait_event.tasklet = tasklet_new();
|
||||
if (!sc->wait_event.tasklet)
|
||||
return -1;
|
||||
|
||||
sc->wait_event.tasklet->process = sc_hstream_io_cb;
|
||||
sc->wait_event.tasklet->context = sc;
|
||||
sc->wait_event.events = 0;
|
||||
|
||||
sc->app_ops = &sc_app_hstream_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Detaches the stconn from the endpoint, if any. For a connecrion, if a
|
||||
* mux owns the connection ->detach() callback is called. Otherwise, it means
|
||||
* the stream connector owns the connection. In this case the connection is closed
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user