diff --git a/include/types/proxy.h b/include/types/proxy.h index 37a50609c..13cc2a4e8 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -205,26 +205,43 @@ enum PR_SRV_STATE_FILE { struct stream; -struct error_snapshot { - struct timeval when; /* date of this event, (tv_sec == 0) means "never" */ - unsigned int len; /* original length of the last invalid request/response */ - unsigned int pos; /* position of the first invalid character */ +struct http_snapshot { unsigned int sid; /* ID of the faulty stream */ - unsigned int ev_id; /* event number (counter incremented for each capture) */ unsigned int state; /* message state before the error (when saved) */ unsigned int b_flags; /* buffer flags */ unsigned int s_flags; /* stream flags */ + unsigned int t_flags; /* transaction flags */ unsigned int m_flags; /* message flags */ - unsigned int b_out; /* pending output bytes */ - unsigned int b_wrap; /* position where the buffer is expected to wrap */ - unsigned long long b_tot; /* total bytes transferred via this buffer */ unsigned long long m_clen; /* chunk len for this message */ unsigned long long m_blen; /* body len for this message */ - struct server *srv; /* server associated with the error (or NULL) */ - struct proxy *oe; /* other end = frontend or backend involved */ - struct sockaddr_storage src; /* client's address */ - char *buf; /* copy of the beginning of the message (may be NULL) */ +}; + +union error_snapshot_ctx { + struct http_snapshot http; +}; + +struct error_snapshot { + /**** common part ****/ + struct timeval when; /* date of this event, (tv_sec == 0) means "never" */ + /* @16 */ + char *buf; /* copy of the beginning of the message (may be NULL) */ + unsigned long long buf_ofs; /* relative position of the buffer's input inside its container */ + /* @32 */ + unsigned int buf_out; /* pending output bytes _before_ the buffer's input (0..buf->data-1) */ + unsigned int buf_len; /* original length of the last invalid request/response (0..buf->data-1-buf_out) */ + unsigned int buf_err; /* buffer-relative position where the error was detected (0..len-1) */ + unsigned int buf_wrap; /* buffer-relative position where the buffer is expected to wrap (1..buf_size) */ + /* @48 */ + struct proxy *oe; /* other end = frontend or backend involved */ + struct server *srv; /* server associated with the error (or NULL) */ + /* @64 */ + unsigned int ev_id; /* event number (counter incremented for each capture) */ + /* @68: 4 bytes hole here */ + struct sockaddr_storage src; /* client's address */ + + /**** protocol-specific part ****/ + union error_snapshot_ctx ctx; }; struct email_alert { diff --git a/src/proto_http.c b/src/proto_http.c index b6d429ba1..2555c6699 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -8024,10 +8024,10 @@ void http_capture_bad_message(struct proxy *proxy, struct error_snapshot *es, st int len1, len2; HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock); - es->len = MIN(ci_data(chn), global.tune.bufsize); + es->buf_len = MIN(ci_data(chn), global.tune.bufsize); len1 = b_wrap(&chn->buf) - ci_head(chn); - len1 = MIN(len1, es->len); - len2 = es->len - len1; /* remaining data if buffer wraps */ + len1 = MIN(len1, es->buf_len); + len2 = es->buf_len - len1; /* remaining data if buffer wraps */ if (!es->buf) es->buf = malloc(global.tune.bufsize); @@ -8039,12 +8039,11 @@ void http_capture_bad_message(struct proxy *proxy, struct error_snapshot *es, st } if (msg->err_pos >= 0) - es->pos = msg->err_pos; + es->buf_err = msg->err_pos; else - es->pos = msg->next; + es->buf_err = msg->next; es->when = date; // user-visible date - es->sid = s->uniq_id; es->srv = objt_server(s->target); es->oe = other_end; if (objt_conn(sess->origin)) @@ -8052,17 +8051,20 @@ void http_capture_bad_message(struct proxy *proxy, struct error_snapshot *es, st else memset(&es->src, 0, sizeof(es->src)); - es->state = state; es->ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1); - es->b_flags = chn->flags; - es->s_flags = s->flags; - es->t_flags = s->txn->flags; - es->m_flags = msg->flags; - es->b_out = co_data(chn); - es->b_wrap = b_wrap(&chn->buf) - ci_head(chn); - es->b_tot = chn->total; - es->m_clen = msg->chunk_len; - es->m_blen = msg->body_len; + es->buf_wrap = b_wrap(&chn->buf) - ci_head(chn); + es->buf_out = co_data(chn); + es->buf_ofs = chn->total; + + /* http-specific part now */ + es->ctx.http.sid = s->uniq_id; + es->ctx.http.state = state; + es->ctx.http.b_flags = chn->flags; + es->ctx.http.s_flags = s->flags; + es->ctx.http.t_flags = s->txn->flags; + es->ctx.http.m_flags = msg->flags; + es->ctx.http.m_clen = msg->chunk_len; + es->ctx.http.m_blen = msg->body_len; HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock); } @@ -12772,11 +12774,12 @@ static int cli_io_handler_show_errors(struct appctx *appctx) " pending %d bytes, wrapping at %d, error at position %d:\n \n", es->srv ? es->srv->id : "", es->srv ? es->srv->puid : -1, es->ev_id, - pn, port, es->sid, es->s_flags, - h1_msg_state_str(es->state), es->state, es->m_flags, es->t_flags, - es->m_clen, es->m_blen, - es->b_flags, es->b_out, es->b_tot, - es->len, es->b_wrap, es->pos); + pn, port, es->ctx.http.sid, es->ctx.http.s_flags, + h1_msg_state_str(es->ctx.http.state), es->ctx.http.state, + es->ctx.http.m_flags, es->ctx.http.t_flags, + es->ctx.http.m_clen, es->ctx.http.m_blen, + es->ctx.http.b_flags, es->buf_out, es->buf_ofs, + es->buf_len, es->buf_wrap, es->buf_err); if (ci_putchk(si_ic(si), &trash) == -1) { /* Socket buffer full. Let's try again later from the same point */ @@ -12799,12 +12802,12 @@ static int cli_io_handler_show_errors(struct appctx *appctx) } /* OK, ptr >= 0, so we have to dump the current line */ - while (es->buf && appctx->ctx.errors.ptr < es->len && appctx->ctx.errors.ptr < global.tune.bufsize) { + while (es->buf && appctx->ctx.errors.ptr < es->buf_len && appctx->ctx.errors.ptr < global.tune.bufsize) { int newptr; int newline; newline = appctx->ctx.errors.bol; - newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->len, &newline, appctx->ctx.errors.ptr); + newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, appctx->ctx.errors.ptr); if (newptr == appctx->ctx.errors.ptr) return 0;