From 476a04aca75f9b49813db98744a3214d41aef2d2 Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Mon, 18 May 2015 04:42:42 +0000 Subject: Fixed #1853: Add callback for dropped data in SIP transport git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5097 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_transport.h | 61 +++++++++++++++++++++++++++++++++++++ pjsip/src/pjsip/sip_transport.c | 52 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index 2ebecd48..1fe3b5af 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -1512,6 +1512,67 @@ PJ_DECL(pj_status_t) pjsip_transport_remove_state_listener ( const void *user_data); +/** + * Structure of dropped received data. + */ +typedef struct pjsip_tp_dropped_data +{ + /** + * The transport receiving the data. + */ + pjsip_transport *tp; + + /** + * The data. + */ + void *data; + + /** + * The data length. + * If the status field below indicates an invalid SIP message + * (PJSIP_EINVALIDMSG) and application detects a SIP message + * at position p, it can pass the data back to PJSIP to be processed + * by setting the len to p. This can be useful for apps which + * wishes to use the same transport for SIP signalling and non-SIP + * purposes (such as SIP outbound using STUN message). + */ + pj_size_t len; + + /** + * The status or reason of drop. For example, a leading newlines (common + * keep-alive packet) will be dropped with status PJ_EIGNORED, an invalid + * SIP message will have status PJSIP_EINVALIDMSG, a SIP message overflow + * will have status PJSIP_ERXOVERFLOW. + */ + pj_status_t status; + +} pjsip_tp_dropped_data; + + +/** + * Type of callback to data dropping notifications. + * + * @param data The dropped data. + */ +typedef void (*pjsip_tp_on_rx_dropped_cb)(pjsip_tp_dropped_data *data); + + +/** + * Set callback of data dropping. The caller will be notified whenever any + * received data is dropped (due to leading newlines or keep-alive packet or + * invalid SIP message). This callback can be useful for application, + * for example, to implement custom keep-alive mechanism or connection + * availability detection. + * + * @param mgr Transport manager. + * @param cb The callback function, set to NULL to reset the callback. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjsip_tpmgr_set_drop_data_cb(pjsip_tpmgr *mgr, + pjsip_tp_on_rx_dropped_cb cb); + + /** * @} */ diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index 2913053b..7c837168 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -99,6 +99,7 @@ struct pjsip_tpmgr void (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*); pjsip_tp_state_callback tp_state_cb; + pjsip_tp_on_rx_dropped_cb tp_drop_data_cb; /* Transmit data list, for transmit data cleanup when transport manager * is destroyed. @@ -1693,6 +1694,18 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr, if (p!=current_pkt) { remaining_len -= (p - current_pkt); total_processed += (p - current_pkt); + + /* Notify application about the dropped newlines */ + if (mgr->tp_drop_data_cb) { + pjsip_tp_dropped_data dd; + pj_bzero(&dd, sizeof(dd)); + dd.tp = tr; + dd.data = current_pkt; + dd.len = p - current_pkt; + dd.status = PJ_EIGNORED; + (*mgr->tp_drop_data_cb)(&dd); + } + current_pkt = p; if (remaining_len == 0) { return total_processed; @@ -1719,6 +1732,18 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr, if (msg_status != PJ_SUCCESS) { if (remaining_len == PJSIP_MAX_PKT_LEN) { mgr->on_rx_msg(mgr->endpt, PJSIP_ERXOVERFLOW, rdata); + + /* Notify application about the message overflow */ + if (mgr->tp_drop_data_cb) { + pjsip_tp_dropped_data dd; + pj_bzero(&dd, sizeof(dd)); + dd.tp = tr; + dd.data = current_pkt; + dd.len = msg_fragment_size; + dd.status = PJSIP_ERXOVERFLOW; + (*mgr->tp_drop_data_cb)(&dd); + } + /* Exhaust all data. */ return rdata->pkt_info.len; } else { @@ -1783,6 +1808,20 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr, rdata->msg_info.msg_buf)); } + /* Notify application about the dropped data (syntax error) */ + if (tmp.slen && mgr->tp_drop_data_cb) { + pjsip_tp_dropped_data dd; + pj_bzero(&dd, sizeof(dd)); + dd.tp = tr; + dd.data = current_pkt; + dd.len = msg_fragment_size; + dd.status = PJSIP_EINVALIDMSG; + (*mgr->tp_drop_data_cb)(&dd); + + if (dd.len > 0 && dd.len < msg_fragment_size) + msg_fragment_size = dd.len; + } + goto finish_process_fragment; } @@ -2265,3 +2304,16 @@ PJ_DEF(pj_status_t) pjsip_transport_remove_state_listener ( return PJ_SUCCESS; } + +/* + * Set callback of data dropping. + */ +PJ_DEF(pj_status_t) pjsip_tpmgr_set_drop_data_cb(pjsip_tpmgr *mgr, + pjsip_tp_on_rx_dropped_cb cb) +{ + PJ_ASSERT_RETURN(mgr, PJ_EINVAL); + + mgr->tp_drop_data_cb = cb; + + return PJ_SUCCESS; +} -- cgit v1.2.3