diff --git a/modules/tcpops/doc/eventroutes.xml b/modules/tcpops/doc/eventroutes.xml index f219b1da091..f1be99f11eb 100644 --- a/modules/tcpops/doc/eventroutes.xml +++ b/modules/tcpops/doc/eventroutes.xml @@ -8,28 +8,73 @@ ]>
- Event routes -
- - <function moreinfo="none">tcp:closed</function> - - - This route is called when a socket is closed by the remote party, - or reset, or timeout. The corresponding $conid - variable will be available in the event route. - - - Whether this route is always called, never, or on a per socket basis - is controlled by the closed_event parameter. - - - + Event routes + The 3 following routes are called when a socket is closed. + + The corresponding + $conid + , + $Ri + , + $Rp + , + $si + , + $sp + and + $proto + variable will be available in the event routes. + + + Whether these routes are always called, never, or on a per socket + basis is controlled by the + closed_event + parameter. + +
+ + <function moreinfo="none">tcp:closed</function> + + + Called for each "normal" TCP socket closure by the other side (FIN,ACK). + +
+
+ + <function moreinfo="none">tcp:timeout</function> + + + Called for connection timeouts (unanswered keepalives). + +
+
+ + <function moreinfo="none">tcp:reset</function> + + + Called if the connection is reset by peer (RST). + +
+
+ + <function moreinfo="none">Example</function> + + + ... event_route[tcp:closed] { - xlog("L_INFO", "TCP connection closed ($conid)\n"); + xlog("L_INFO", "$proto connection closed ($conid)\n"); +} + +event_route[tcp:timeout] { + xlog("L_INFO", "$proto connection timed out ($conid)\n"); +} + +event_route[tcp:reset] { + xlog("L_INFO", "$proto connection reset by peer ($conid)\n"); } ... - - + +
\ No newline at end of file diff --git a/modules/tcpops/tcpops.c b/modules/tcpops/tcpops.c index 624e8877d41..43340caa4bf 100644 --- a/modules/tcpops/tcpops.c +++ b/modules/tcpops/tcpops.c @@ -38,6 +38,9 @@ /* globally enabled by default */ int tcp_closed_event = 1; +int tcp_closed_routes[_TCP_CLOSED_REASON_MAX] = + {[0 ... sizeof(tcp_closed_routes)/sizeof(*tcp_closed_routes)-1] = -1}; + /** * gets the fd of the current message source connection * @@ -192,20 +195,14 @@ int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) { return 1; } -static void tcpops_tcp_closed_run_route(struct tcp_connection *con) +static void tcpops_tcp_closed_run_route(tcp_closed_event_info_t *tev) { int rt, backup_rt; struct run_act_ctx ctx; sip_msg_t *fmsg; - LM_DBG("tcp_closed_run_route event_route[tcp:closed]\n"); - - rt = route_get(&event_rt, "tcp:closed"); - if (rt < 0 || event_rt.rlist[rt] == NULL) - { - LM_DBG("route does not exist"); - return; - } + rt = tcp_closed_routes[tev->reason]; + if (rt == -1) return; if (faked_msg_init() < 0) { @@ -213,7 +210,7 @@ static void tcpops_tcp_closed_run_route(struct tcp_connection *con) return; } fmsg = faked_msg_next(); - fmsg->rcv = con->rcv; + fmsg->rcv = tev->con->rcv; backup_rt = get_route_type(); set_route_type(EVENT_ROUTE); @@ -224,7 +221,7 @@ static void tcpops_tcp_closed_run_route(struct tcp_connection *con) int tcpops_handle_tcp_closed(void *data) { - tcp_event_info_t *tev = (tcp_event_info_t *) data; + tcp_closed_event_info_t *tev = (tcp_closed_event_info_t *) data; if (tev == NULL || tev->con == NULL) { LM_WARN("received bad TCP closed event\n"); @@ -234,7 +231,7 @@ int tcpops_handle_tcp_closed(void *data) /* run event route if tcp_closed_event == 1 or if the * F_CONN_CLOSE_EV flag is explicitly set */ if (tcp_closed_event == 1 || (tev->con->flags & F_CONN_CLOSE_EV)) - tcpops_tcp_closed_run_route(tev->con); + tcpops_tcp_closed_run_route(tev); return 0; } diff --git a/modules/tcpops/tcpops.h b/modules/tcpops/tcpops.h index 8e1c823dd63..bde142b8582 100644 --- a/modules/tcpops/tcpops.h +++ b/modules/tcpops/tcpops.h @@ -28,6 +28,7 @@ #include "../../events.h" extern int tcp_closed_event; +extern int tcp_closed_routes[_TCP_CLOSED_REASON_MAX]; int tcpops_get_current_fd(int conid, int *fd); int tcpops_acquire_fd_from_tcpmain(int conid, int *fd); diff --git a/modules/tcpops/tcpops_mod.c b/modules/tcpops/tcpops_mod.c index 60c7b88db8d..b235cd4fb85 100644 --- a/modules/tcpops/tcpops_mod.c +++ b/modules/tcpops/tcpops_mod.c @@ -118,11 +118,17 @@ static int mod_init(void) return -1; } - if (tcp_closed_event /* register event only if tcp_closed_event != 0 */ - && (sr_event_register_cb(SREV_TCP_CLOSED, tcpops_handle_tcp_closed) != 0)) - { - LM_ERR("problem registering tcpops_handle_tcp_closed call-back\n"); - return -1; + if (tcp_closed_event) { + /* register event only if tcp_closed_event != 0 */ + if (sr_event_register_cb(SREV_TCP_CLOSED, tcpops_handle_tcp_closed) != 0) { + LM_ERR("problem registering tcpops_handle_tcp_closed call-back\n"); + return -1; + } + + /* get event routes */ + tcp_closed_routes[TCP_CLOSED_EOF] = route_get(&event_rt, "tcp:closed"); + tcp_closed_routes[TCP_CLOSED_TIMEOUT] = route_get(&event_rt, "tcp:timeout"); + tcp_closed_routes[TCP_CLOSED_RESET] = route_get(&event_rt, "tcp:reset"); } return 0; diff --git a/tcp_conn.h b/tcp_conn.h index 7c4ef5d4704..771b744bf34 100644 --- a/tcp_conn.h +++ b/tcp_conn.h @@ -335,6 +335,19 @@ typedef struct tcp_event_info { struct tcp_connection *con; } tcp_event_info_t; +enum tcp_closed_reason { + TCP_CLOSED_EOF = 0, + TCP_CLOSED_TIMEOUT, + TCP_CLOSED_RESET, + + _TCP_CLOSED_REASON_MAX /* /!\ keep this one always at the end */ +}; + +typedef struct tcp_closed_event_info { + enum tcp_closed_reason reason; + struct tcp_connection *con; +} tcp_closed_event_info_t; + typedef struct ws_event_info { int type; char *buf; diff --git a/tcp_read.c b/tcp_read.c index 85dd4b1a6a6..e8b262bbd0c 100644 --- a/tcp_read.c +++ b/tcp_read.c @@ -186,17 +186,16 @@ int tcp_http11_continue(struct tcp_connection *c) } #endif /* HTTP11 */ -static int tcp_make_closed_event(struct receive_info* rcv_info, struct tcp_connection* con) +static int tcp_emit_closed_event(struct tcp_connection *con, enum tcp_closed_reason reason) { int ret; - tcp_event_info_t tev; + tcp_closed_event_info_t tev; ret = 0; LM_DBG("TCP closed event creation triggered\n"); if(likely(sr_event_enabled(SREV_TCP_CLOSED))) { - memset(&tev, 0, sizeof(tcp_event_info_t)); - tev.type = SREV_TCP_CLOSED; - tev.rcv = rcv_info; + memset(&tev, 0, sizeof(tcp_closed_event_info_t)); + tev.reason = reason; tev.con = con; ret = sr_event_exec(SREV_TCP_CLOSED, (void*)(&tev)); } else { @@ -291,19 +290,18 @@ int tcp_read_data(int fd, struct tcp_connection *c, strerror(errno), errno, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); LOG(cfg_get(core, core_cfg, corelog),"-> [%s]:%u)\n", ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); - if((errno == ECONNRESET || errno == ETIMEDOUT) && likely(c->rcv.proto_reserved1 != 0)){ - tcp_make_closed_event(&c->rcv, c); + if (errno == ETIMEDOUT) { + tcp_emit_closed_event(c, TCP_CLOSED_TIMEOUT); + } else if (errno == ECONNRESET) { + tcp_emit_closed_event(c, TCP_CLOSED_RESET); } - return -1; } }else if (unlikely((bytes_read==0) || (*flags & RD_CONN_FORCE_EOF))){ c->state=S_CONN_EOF; *flags|=RD_CONN_EOF; - if (likely(c->rcv.proto_reserved1 != 0)){ - tcp_make_closed_event(&c->rcv, c); - } + tcp_emit_closed_event(c, TCP_CLOSED_EOF); LM_DBG("EOF on %p, FD %d ([%s]:%u ->", c, fd, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); LM_DBG("-> [%s]:%u)\n", ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); }else{