mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
[MEDIUM] reference the current hijack function in the buffer itself
Instead of calling a hard-coded function to produce data, let's reference this function into the buffer and call it from there when BF_HIJACK is set. This goes in the direction of more generic session management code.
This commit is contained in:
parent
b5654f6ff4
commit
01bf8675ed
@ -126,13 +126,21 @@ static inline void buffer_abort(struct buffer *buf)
|
|||||||
buf->flags |= BF_SHUTR_NOW | BF_SHUTW_NOW;
|
buf->flags |= BF_SHUTR_NOW | BF_SHUTW_NOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the buffer to hijacking mode */
|
/* Installs <func> as a hijacker on the buffer <b> for session <s>. The hijack
|
||||||
static inline void buffer_start_hijack(struct buffer *buf)
|
* flag is set, and the function called once. The function is responsible for
|
||||||
|
* clearing the hijack bit. It is possible that the function clears the flag
|
||||||
|
* during this first call.
|
||||||
|
*/
|
||||||
|
static inline void buffer_install_hijacker(struct session *s,
|
||||||
|
struct buffer *b,
|
||||||
|
void (*func)(struct session *, struct buffer *))
|
||||||
{
|
{
|
||||||
buf->flags |= BF_HIJACK;
|
b->hijacker = func;
|
||||||
|
b->flags |= BF_HIJACK;
|
||||||
|
func(s, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* releases the buffer from hijacking mode */
|
/* Releases the buffer from hijacking mode. Often used by the hijack function */
|
||||||
static inline void buffer_stop_hijack(struct buffer *buf)
|
static inline void buffer_stop_hijack(struct buffer *buf)
|
||||||
{
|
{
|
||||||
buf->flags &= ~BF_HIJACK;
|
buf->flags &= ~BF_HIJACK;
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#define STATS_ST_CLOSE 3
|
#define STATS_ST_CLOSE 3
|
||||||
|
|
||||||
int stats_dump_raw(struct session *s, struct uri_auth *uri);
|
int stats_dump_raw(struct session *s, struct uri_auth *uri);
|
||||||
int stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
|
void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
|
||||||
int stats_dump_http(struct session *s, struct uri_auth *uri);
|
int stats_dump_http(struct session *s, struct uri_auth *uri);
|
||||||
int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri);
|
int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ int http_process_tarpit(struct session *s, struct buffer *req);
|
|||||||
int http_process_request_body(struct session *s, struct buffer *req);
|
int http_process_request_body(struct session *s, struct buffer *req);
|
||||||
int process_response(struct session *t);
|
int process_response(struct session *t);
|
||||||
|
|
||||||
int produce_content(struct session *s);
|
void produce_content(struct session *s, struct buffer *rep);
|
||||||
int produce_content_stats(struct session *s);
|
int produce_content_stats(struct session *s);
|
||||||
int produce_content_stats_proxy(struct session *s, struct proxy *px);
|
int produce_content_stats_proxy(struct session *s, struct proxy *px);
|
||||||
void debug_hdr(const char *dir, struct session *t, const char *start, const char *end);
|
void debug_hdr(const char *dir, struct session *t, const char *start, const char *end);
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
* it is strictly forbidden for the stream interface to send anything from the
|
* it is strictly forbidden for the stream interface to send anything from the
|
||||||
* buffer.
|
* buffer.
|
||||||
*/
|
*/
|
||||||
#define BF_HIJACK 0x040000 /* the producer is temporarily replaced */
|
#define BF_HIJACK 0x040000 /* the producer is temporarily replaced by ->hijacker */
|
||||||
#define BF_ANA_TIMEOUT 0x080000 /* the analyser timeout has expired */
|
#define BF_ANA_TIMEOUT 0x080000 /* the analyser timeout has expired */
|
||||||
#define BF_READ_ATTACHED 0x100000 /* the read side is attached for the first time */
|
#define BF_READ_ATTACHED 0x100000 /* the read side is attached for the first time */
|
||||||
|
|
||||||
@ -116,6 +116,9 @@ struct chunk {
|
|||||||
int len; /* size of the string from first to last char. <0 = uninit. */
|
int len; /* size of the string from first to last char. <0 = uninit. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* needed for a declaration below */
|
||||||
|
struct session;
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
unsigned int flags; /* BF_* */
|
unsigned int flags; /* BF_* */
|
||||||
int rex; /* expiration date for a read, in ticks */
|
int rex; /* expiration date for a read, in ticks */
|
||||||
@ -128,6 +131,7 @@ struct buffer {
|
|||||||
char *rlim; /* read limit, used for header rewriting */
|
char *rlim; /* read limit, used for header rewriting */
|
||||||
unsigned int analysers; /* bit field indicating what to do on the buffer */
|
unsigned int analysers; /* bit field indicating what to do on the buffer */
|
||||||
int analyse_exp; /* expiration date for current analysers (if set) */
|
int analyse_exp; /* expiration date for current analysers (if set) */
|
||||||
|
void (*hijacker)(struct session *, struct buffer *); /* alternative content producer */
|
||||||
unsigned char xfer_large; /* number of consecutive large xfers */
|
unsigned char xfer_large; /* number of consecutive large xfers */
|
||||||
unsigned char xfer_small; /* number of consecutive small xfers */
|
unsigned char xfer_small; /* number of consecutive small xfers */
|
||||||
unsigned long long total; /* total data read */
|
unsigned long long total; /* total data read */
|
||||||
|
@ -290,18 +290,18 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri)
|
|||||||
|
|
||||||
/* This function is called to send output to the response buffer. It simply
|
/* This function is called to send output to the response buffer. It simply
|
||||||
* calls stats_dump_raw(), and releases the buffer's hijack bit when the dump
|
* calls stats_dump_raw(), and releases the buffer's hijack bit when the dump
|
||||||
* is finished. It always returns 0.
|
* is finished.
|
||||||
*/
|
*/
|
||||||
int stats_dump_raw_to_buffer(struct session *s, struct buffer *req)
|
void stats_dump_raw_to_buffer(struct session *s, struct buffer *req)
|
||||||
{
|
{
|
||||||
if (s->ana_state != STATS_ST_REP)
|
if (s->ana_state != STATS_ST_REP)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (stats_dump_raw(s, NULL) != 0) {
|
if (stats_dump_raw(s, NULL) != 0) {
|
||||||
buffer_stop_hijack(s->rep);
|
buffer_stop_hijack(s->rep);
|
||||||
s->ana_state = STATS_ST_CLOSE;
|
s->ana_state = STATS_ST_CLOSE;
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -327,9 +327,6 @@ int stats_dump_http(struct session *s, struct uri_auth *uri)
|
|||||||
|
|
||||||
switch (s->data_state) {
|
switch (s->data_state) {
|
||||||
case DATA_ST_INIT:
|
case DATA_ST_INIT:
|
||||||
/* the function had not been called yet */
|
|
||||||
buffer_start_hijack(rep);
|
|
||||||
|
|
||||||
chunk_printf(&msg, sizeof(trash),
|
chunk_printf(&msg, sizeof(trash),
|
||||||
"HTTP/1.0 200 OK\r\n"
|
"HTTP/1.0 200 OK\r\n"
|
||||||
"Cache-Control: no-cache\r\n"
|
"Cache-Control: no-cache\r\n"
|
||||||
|
@ -2989,33 +2989,32 @@ int process_response(struct session *t)
|
|||||||
* called with client socket shut down on input. Right now, only statistics can
|
* called with client socket shut down on input. Right now, only statistics can
|
||||||
* be produced. It stops by itself by unsetting the BF_HIJACK flag from the
|
* be produced. It stops by itself by unsetting the BF_HIJACK flag from the
|
||||||
* buffer, which it uses to keep on being called when there is free space in
|
* buffer, which it uses to keep on being called when there is free space in
|
||||||
* the buffer, or simply by letting an empty buffer upon return. It returns 1
|
* the buffer, or simply by letting an empty buffer upon return.
|
||||||
* when it wants to stop sending data, otherwise 0.
|
|
||||||
*/
|
*/
|
||||||
int produce_content(struct session *s)
|
void produce_content(struct session *s, struct buffer *rep)
|
||||||
{
|
{
|
||||||
if (s->data_source == DATA_SRC_NONE) {
|
if (s->data_source == DATA_SRC_NONE) {
|
||||||
buffer_stop_hijack(s->rep);
|
buffer_stop_hijack(rep);
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
else if (s->data_source == DATA_SRC_STATS) {
|
else if (s->data_source == DATA_SRC_STATS) {
|
||||||
/* dump server statistics */
|
/* dump server statistics */
|
||||||
int ret = stats_dump_http(s, s->be->uri_auth);
|
int ret = stats_dump_http(s, s->be->uri_auth);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
return ret;
|
return;
|
||||||
/* -1 indicates an error */
|
/* -1 indicates an error */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unknown data source or internal error */
|
/* unknown data source or internal error */
|
||||||
s->txn.status = 500;
|
s->txn.status = 500;
|
||||||
stream_int_retnclose(s->rep->cons, error_message(s, HTTP_ERR_500));
|
stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_500));
|
||||||
trace_term(s, TT_HTTP_CNT_1);
|
trace_term(s, TT_HTTP_CNT_1);
|
||||||
if (!(s->flags & SN_ERR_MASK))
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
s->flags |= SN_ERR_PRXCOND;
|
s->flags |= SN_ERR_PRXCOND;
|
||||||
if (!(s->flags & SN_FINST_MASK))
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
s->flags |= SN_FINST_R;
|
s->flags |= SN_FINST_R;
|
||||||
buffer_stop_hijack(s->rep);
|
buffer_stop_hijack(rep);
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4392,12 +4391,11 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
|
|||||||
buffer_write_dis(t->req);
|
buffer_write_dis(t->req);
|
||||||
buffer_shutw_now(t->req);
|
buffer_shutw_now(t->req);
|
||||||
buffer_shutr_now(t->rep);
|
buffer_shutr_now(t->rep);
|
||||||
buffer_start_hijack(t->rep);
|
|
||||||
t->logs.tv_request = now;
|
t->logs.tv_request = now;
|
||||||
t->data_source = DATA_SRC_STATS;
|
t->data_source = DATA_SRC_STATS;
|
||||||
t->data_state = DATA_ST_INIT;
|
t->data_state = DATA_ST_INIT;
|
||||||
t->task->nice = -32; /* small boost for HTTP statistics */
|
t->task->nice = -32; /* small boost for HTTP statistics */
|
||||||
produce_content(t);
|
buffer_install_hijacker(t, t->rep, produce_content);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,15 +596,13 @@ int unix_sock_parse_request(struct session *s, char *line)
|
|||||||
s->data_ctx.stats.flags |= STAT_SHOW_STAT;
|
s->data_ctx.stats.flags |= STAT_SHOW_STAT;
|
||||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||||
s->ana_state = STATS_ST_REP;
|
s->ana_state = STATS_ST_REP;
|
||||||
buffer_start_hijack(s->rep);
|
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
||||||
stats_dump_raw_to_buffer(s, s->rep);
|
|
||||||
}
|
}
|
||||||
else if (strcmp(args[1], "info") == 0) {
|
else if (strcmp(args[1], "info") == 0) {
|
||||||
s->data_ctx.stats.flags |= STAT_SHOW_INFO;
|
s->data_ctx.stats.flags |= STAT_SHOW_INFO;
|
||||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||||
s->ana_state = STATS_ST_REP;
|
s->ana_state = STATS_ST_REP;
|
||||||
buffer_start_hijack(s->rep);
|
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
||||||
stats_dump_raw_to_buffer(s, s->rep);
|
|
||||||
}
|
}
|
||||||
else { /* neither "stat" nor "info" */
|
else { /* neither "stat" nor "info" */
|
||||||
return 0;
|
return 0;
|
||||||
@ -837,8 +835,7 @@ void uxst_process_session(struct task *t, int *next)
|
|||||||
|
|
||||||
if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
|
if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
|
||||||
!(s->rep->flags & BF_FULL)) {
|
!(s->rep->flags & BF_FULL)) {
|
||||||
/* it is the only hijacker right now */
|
s->rep->hijacker(s, s->rep);
|
||||||
stats_dump_raw_to_buffer(s, s->rep);
|
|
||||||
}
|
}
|
||||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
||||||
flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
||||||
|
@ -805,7 +805,7 @@ resync_stream_interface:
|
|||||||
|
|
||||||
if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
|
if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
|
||||||
!(s->rep->flags & BF_FULL)) {
|
!(s->rep->flags & BF_FULL)) {
|
||||||
produce_content(s);
|
s->rep->hijacker(s, s->rep);
|
||||||
}
|
}
|
||||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
||||||
flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user