... | ... |
@@ -193,12 +193,22 @@ typedef struct tcp_conn_alias { |
193 | 193 |
#endif |
194 | 194 |
|
195 | 195 |
|
196 |
+enum tcp_closed_reason { |
|
197 |
+ TCP_CLOSED_EOF = 0, |
|
198 |
+ TCP_CLOSED_TIMEOUT, |
|
199 |
+ TCP_CLOSED_RESET, |
|
200 |
+ |
|
201 |
+ _TCP_CLOSED_REASON_MAX /* /!\ keep this one always at the end */ |
|
202 |
+}; |
|
203 |
+ |
|
204 |
+ |
|
196 | 205 |
typedef struct tcp_connection { |
197 | 206 |
int s; /*socket, used by "tcp main" */ |
198 | 207 |
int fd; /* used only by "children", don't modify it! private data! */ |
199 | 208 |
gen_lock_t write_lock; |
200 | 209 |
int id; /* id (unique!) used to retrieve a specific connection when |
201 | 210 |
* reply-ing */ |
211 |
+ enum tcp_closed_reason event; /* connection close reason */ |
|
202 | 212 |
int reader_pid; /* pid of the active reader process */ |
203 | 213 |
struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/ |
204 | 214 |
ksr_coninfo_t cinfo; /* connection info (e.g., for haproxy ) */ |
... | ... |
@@ -343,14 +353,6 @@ typedef struct tcp_event_info { |
343 | 353 |
struct tcp_connection *con; |
344 | 354 |
} tcp_event_info_t; |
345 | 355 |
|
346 |
-enum tcp_closed_reason { |
|
347 |
- TCP_CLOSED_EOF = 0, |
|
348 |
- TCP_CLOSED_TIMEOUT, |
|
349 |
- TCP_CLOSED_RESET, |
|
350 |
- |
|
351 |
- _TCP_CLOSED_REASON_MAX /* /!\ keep this one always at the end */ |
|
352 |
-}; |
|
353 |
- |
|
354 | 356 |
typedef struct tcp_closed_event_info { |
355 | 357 |
enum tcp_closed_reason reason; |
356 | 358 |
struct tcp_connection *con; |
... | ... |
@@ -3549,11 +3549,18 @@ again: |
3549 | 3549 |
} |
3550 | 3550 |
|
3551 | 3551 |
|
3552 |
-static int tcp_emit_closed_event(struct tcp_connection *con, enum tcp_closed_reason reason) |
|
3552 |
+static int tcp_emit_closed_event(struct tcp_connection *con) |
|
3553 | 3553 |
{ |
3554 | 3554 |
int ret; |
3555 | 3555 |
tcp_closed_event_info_t tev; |
3556 | 3556 |
sr_event_param_t evp = {0}; |
3557 |
+ enum tcp_closed_reason reason; |
|
3558 |
+ |
|
3559 |
+ if (con->event) { |
|
3560 |
+ reason = con->event; |
|
3561 |
+ } else { |
|
3562 |
+ reason = TCP_CLOSED_EOF; |
|
3563 |
+ } |
|
3557 | 3564 |
|
3558 | 3565 |
ret = 0; |
3559 | 3566 |
LM_DBG("TCP closed event creation triggered (reason: %d)\n", reason); |
... | ... |
@@ -3649,7 +3656,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3649 | 3656 |
/* if refcnt was 1 => it was used only in the |
3650 | 3657 |
tcp reader => it's not hashed or watched for IO |
3651 | 3658 |
anymore => no need to io_watch_del() */ |
3652 |
- tcp_emit_closed_event(tcpconn, TCP_CLOSED_EOF); |
|
3659 |
+ tcp_emit_closed_event(tcpconn); |
|
3653 | 3660 |
tcpconn_destroy(tcpconn); |
3654 | 3661 |
break; |
3655 | 3662 |
} |
... | ... |
@@ -3661,7 +3668,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3661 | 3668 |
tcpconn->flags &= ~F_CONN_WRITE_W; |
3662 | 3669 |
} |
3663 | 3670 |
#endif /* TCP_ASYNC */ |
3664 |
- tcp_emit_closed_event(tcpconn, TCP_CLOSED_EOF); |
|
3671 |
+ tcp_emit_closed_event(tcpconn); |
|
3665 | 3672 |
tcpconn_put_destroy(tcpconn); |
3666 | 3673 |
} |
3667 | 3674 |
#ifdef TCP_ASYNC |
... | ... |
@@ -3713,7 +3720,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3713 | 3720 |
io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING); |
3714 | 3721 |
tcpconn->flags&=~F_CONN_WRITE_W; |
3715 | 3722 |
} |
3716 |
- tcp_emit_closed_event(tcpconn, TCP_CLOSED_EOF); |
|
3723 |
+ tcpconn->event = TCP_CLOSED_TIMEOUT; |
|
3724 |
+ tcp_emit_closed_event(tcpconn); |
|
3717 | 3725 |
tcpconn_put_destroy(tcpconn); |
3718 | 3726 |
} else if (unlikely(tcpconn->flags & F_CONN_WRITE_W)){ |
3719 | 3727 |
BUG("unhashed connection watched for write\n"); |
... | ... |
@@ -3750,7 +3758,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3750 | 3758 |
tcpconn->flags&=~F_CONN_WRITE_W; |
3751 | 3759 |
} |
3752 | 3760 |
#endif /* TCP_ASYNC */ |
3753 |
- tcp_emit_closed_event(tcpconn, TCP_CLOSED_EOF); |
|
3761 |
+ tcp_emit_closed_event(tcpconn); |
|
3754 | 3762 |
tcpconn_put_destroy(tcpconn); |
3755 | 3763 |
} |
3756 | 3764 |
#ifdef TCP_ASYNC |
... | ... |
@@ -3782,7 +3790,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3782 | 3790 |
#endif /* TCP_ASYNC */ |
3783 | 3791 |
if (tcpconn_try_unhash(tcpconn)) |
3784 | 3792 |
tcpconn_put(tcpconn); |
3785 |
- tcp_emit_closed_event(tcpconn, TCP_CLOSED_EOF); |
|
3793 |
+ tcp_emit_closed_event(tcpconn); |
|
3786 | 3794 |
tcpconn_put_destroy(tcpconn); /* deref & delete if refcnt==0 */ |
3787 | 3795 |
break; |
3788 | 3796 |
default: |
... | ... |
@@ -268,6 +268,11 @@ again: |
268 | 268 |
ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); |
269 | 269 |
LOG(cfg_get(core, core_cfg, corelog),"-> [%s]:%u)\n", |
270 | 270 |
ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
271 |
+ if (errno == ETIMEDOUT) { |
|
272 |
+ c->event = TCP_CLOSED_TIMEOUT; |
|
273 |
+ } else if (errno == ECONNRESET) { |
|
274 |
+ c->event = TCP_CLOSED_RESET; |
|
275 |
+ } |
|
271 | 276 |
return -1; |
272 | 277 |
} |
273 | 278 |
}else if (unlikely((bytes_read==0) || |
... | ... |
@@ -279,6 +284,7 @@ again: |
279 | 284 |
ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
280 | 285 |
c->state=S_CONN_EOF; |
281 | 286 |
*flags|=RD_CONN_EOF; |
287 |
+ c->event=TCP_CLOSED_EOF; |
|
282 | 288 |
}else{ |
283 | 289 |
if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){ |
284 | 290 |
TCP_STATS_ESTABLISHED(c->state); |
... | ... |
@@ -1670,6 +1676,7 @@ static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln* tl, void* data) |
1670 | 1676 |
} |
1671 | 1677 |
if(tcp_conn_lst!=NULL) { |
1672 | 1678 |
tcpconn_listrm(tcp_conn_lst, c, c_next, c_prev); |
1679 |
+ c->event = TCP_CLOSED_TIMEOUT; |
|
1673 | 1680 |
release_tcpconn(c, (c->state<0)?CONN_ERROR:CONN_RELEASE, tcpmain_sock); |
1674 | 1681 |
} |
1675 | 1682 |
return 0; |