... | ... |
@@ -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; |
... | ... |
@@ -79,6 +79,7 @@ |
79 | 79 |
#include "tcp_stats.h" |
80 | 80 |
#include "tcp_ev.h" |
81 | 81 |
#include "tsend.h" |
82 |
+#include "events.h" |
|
82 | 83 |
#include "timer_ticks.h" |
83 | 84 |
#include "local_timer.h" |
84 | 85 |
#ifdef CORE_TLS |
... | ... |
@@ -3548,6 +3549,33 @@ again: |
3548 | 3549 |
} |
3549 | 3550 |
|
3550 | 3551 |
|
3552 |
+static int tcp_emit_closed_event(struct tcp_connection *con) |
|
3553 |
+{ |
|
3554 |
+ int ret; |
|
3555 |
+ tcp_closed_event_info_t tev; |
|
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 |
+ } |
|
3564 |
+ |
|
3565 |
+ ret = 0; |
|
3566 |
+ LM_DBG("TCP closed event creation triggered (reason: %d)\n", reason); |
|
3567 |
+ if(likely(sr_event_enabled(SREV_TCP_CLOSED))) { |
|
3568 |
+ memset(&tev, 0, sizeof(tcp_closed_event_info_t)); |
|
3569 |
+ tev.reason = reason; |
|
3570 |
+ tev.con = con; |
|
3571 |
+ evp.data = (void*)(&tev); |
|
3572 |
+ ret = sr_event_exec(SREV_TCP_CLOSED, &evp); |
|
3573 |
+ } else { |
|
3574 |
+ LM_DBG("no callback registering for handling TCP closed event\n"); |
|
3575 |
+ } |
|
3576 |
+ return ret; |
|
3577 |
+} |
|
3578 |
+ |
|
3551 | 3579 |
|
3552 | 3580 |
/* handles io from a tcp child process |
3553 | 3581 |
* params: tcp_c - pointer in the tcp_children array, to the entry for |
... | ... |
@@ -3628,6 +3656,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3628 | 3656 |
/* if refcnt was 1 => it was used only in the |
3629 | 3657 |
tcp reader => it's not hashed or watched for IO |
3630 | 3658 |
anymore => no need to io_watch_del() */ |
3659 |
+ tcp_emit_closed_event(tcpconn); |
|
3631 | 3660 |
tcpconn_destroy(tcpconn); |
3632 | 3661 |
break; |
3633 | 3662 |
} |
... | ... |
@@ -3639,6 +3668,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3639 | 3668 |
tcpconn->flags &= ~F_CONN_WRITE_W; |
3640 | 3669 |
} |
3641 | 3670 |
#endif /* TCP_ASYNC */ |
3671 |
+ tcp_emit_closed_event(tcpconn); |
|
3642 | 3672 |
tcpconn_put_destroy(tcpconn); |
3643 | 3673 |
} |
3644 | 3674 |
#ifdef TCP_ASYNC |
... | ... |
@@ -3690,6 +3720,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3690 | 3720 |
io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING); |
3691 | 3721 |
tcpconn->flags&=~F_CONN_WRITE_W; |
3692 | 3722 |
} |
3723 |
+ tcpconn->event = TCP_CLOSED_TIMEOUT; |
|
3724 |
+ tcp_emit_closed_event(tcpconn); |
|
3693 | 3725 |
tcpconn_put_destroy(tcpconn); |
3694 | 3726 |
} else if (unlikely(tcpconn->flags & F_CONN_WRITE_W)){ |
3695 | 3727 |
BUG("unhashed connection watched for write\n"); |
... | ... |
@@ -3726,6 +3758,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3726 | 3758 |
tcpconn->flags&=~F_CONN_WRITE_W; |
3727 | 3759 |
} |
3728 | 3760 |
#endif /* TCP_ASYNC */ |
3761 |
+ tcp_emit_closed_event(tcpconn); |
|
3729 | 3762 |
tcpconn_put_destroy(tcpconn); |
3730 | 3763 |
} |
3731 | 3764 |
#ifdef TCP_ASYNC |
... | ... |
@@ -3757,6 +3790,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
3757 | 3790 |
#endif /* TCP_ASYNC */ |
3758 | 3791 |
if (tcpconn_try_unhash(tcpconn)) |
3759 | 3792 |
tcpconn_put(tcpconn); |
3793 |
+ tcp_emit_closed_event(tcpconn); |
|
3760 | 3794 |
tcpconn_put_destroy(tcpconn); /* deref & delete if refcnt==0 */ |
3761 | 3795 |
break; |
3762 | 3796 |
default: |
... | ... |
@@ -174,26 +174,6 @@ int tcp_http11_continue(struct tcp_connection *c) |
174 | 174 |
} |
175 | 175 |
#endif /* HTTP11 */ |
176 | 176 |
|
177 |
-static int tcp_emit_closed_event(struct tcp_connection *con, enum tcp_closed_reason reason) |
|
178 |
-{ |
|
179 |
- int ret; |
|
180 |
- tcp_closed_event_info_t tev; |
|
181 |
- sr_event_param_t evp = {0}; |
|
182 |
- |
|
183 |
- ret = 0; |
|
184 |
- LM_DBG("TCP closed event creation triggered (reason: %d)\n", reason); |
|
185 |
- if(likely(sr_event_enabled(SREV_TCP_CLOSED))) { |
|
186 |
- memset(&tev, 0, sizeof(tcp_closed_event_info_t)); |
|
187 |
- tev.reason = reason; |
|
188 |
- tev.con = con; |
|
189 |
- evp.data = (void*)(&tev); |
|
190 |
- ret = sr_event_exec(SREV_TCP_CLOSED, &evp); |
|
191 |
- } else { |
|
192 |
- LM_DBG("no callback registering for handling TCP closed event\n"); |
|
193 |
- } |
|
194 |
- return ret; |
|
195 |
-} |
|
196 |
- |
|
197 | 177 |
|
198 | 178 |
/** reads data from an existing tcp connection. |
199 | 179 |
* Side-effects: blocklisting, sets connection state to S_CONN_OK, tcp stats. |
... | ... |
@@ -289,9 +269,9 @@ again: |
289 | 269 |
LOG(cfg_get(core, core_cfg, corelog),"-> [%s]:%u)\n", |
290 | 270 |
ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
291 | 271 |
if (errno == ETIMEDOUT) { |
292 |
- tcp_emit_closed_event(c, TCP_CLOSED_TIMEOUT); |
|
272 |
+ c->event = TCP_CLOSED_TIMEOUT; |
|
293 | 273 |
} else if (errno == ECONNRESET) { |
294 |
- tcp_emit_closed_event(c, TCP_CLOSED_RESET); |
|
274 |
+ c->event = TCP_CLOSED_RESET; |
|
295 | 275 |
} |
296 | 276 |
return -1; |
297 | 277 |
} |
... | ... |
@@ -304,7 +284,7 @@ again: |
304 | 284 |
ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
305 | 285 |
c->state=S_CONN_EOF; |
306 | 286 |
*flags|=RD_CONN_EOF; |
307 |
- tcp_emit_closed_event(c, TCP_CLOSED_EOF); |
|
287 |
+ c->event=TCP_CLOSED_EOF; |
|
308 | 288 |
}else{ |
309 | 289 |
if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){ |
310 | 290 |
TCP_STATS_ESTABLISHED(c->state); |
... | ... |
@@ -1696,6 +1676,7 @@ static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln* tl, void* data) |
1696 | 1676 |
} |
1697 | 1677 |
if(tcp_conn_lst!=NULL) { |
1698 | 1678 |
tcpconn_listrm(tcp_conn_lst, c, c_next, c_prev); |
1679 |
+ c->event = TCP_CLOSED_TIMEOUT; |
|
1699 | 1680 |
release_tcpconn(c, (c->state<0)?CONN_ERROR:CONN_RELEASE, tcpmain_sock); |
1700 | 1681 |
} |
1701 | 1682 |
return 0; |