diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c index c53b04c0a9..b6eeda3483 100644 --- a/pjsip-apps/src/pjsua/pjsua_app.c +++ b/pjsip-apps/src/pjsua/pjsua_app.c @@ -1060,6 +1060,11 @@ void on_ip_change_progress(pjsua_ip_change_op op, if (status == PJ_SUCCESS) { switch (op) { + case PJSUA_IP_CHANGE_OP_SHUTDOWN_TP: + pj_ansi_snprintf(info_str, sizeof(info_str), + "TCP/TLS transports shutdown"); + break; + case PJSUA_IP_CHANGE_OP_RESTART_LIS: pjsua_transport_get_info(info->lis_restart.transport_id, &tp_info); pj_ansi_snprintf(info_str, sizeof(info_str), @@ -1107,6 +1112,7 @@ void on_ip_change_progress(pjsua_ip_change_op op, pj_ansi_snprintf(info_str, sizeof(info_str), "done"); default: + info_str[0] = '\0'; break; } PJ_LOG(3,(THIS_FILE, "IP change progress report : %s", info_str)); diff --git a/pjsip-apps/src/swig/symbols.i b/pjsip-apps/src/swig/symbols.i index 85bd7c1066..bf0965b0d7 100644 --- a/pjsip-apps/src/swig/symbols.i +++ b/pjsip-apps/src/swig/symbols.i @@ -911,6 +911,7 @@ typedef enum pjsua_snd_dev_mode typedef enum pjsua_ip_change_op { PJSUA_IP_CHANGE_OP_NULL, + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_RESTART_LIS, PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT, diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index 11d7d2ceb7..75fcfad034 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -1322,6 +1322,53 @@ PJ_DECL(pj_status_t) pjsip_tpmgr_destroy(pjsip_tpmgr *mgr); PJ_DECL(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr); +/** + * Parameter for pjsip_tpmgr_shutdown_all() function. + */ +typedef struct pjsip_tpmgr_shutdown_param +{ + /** + * Specify whether disconnection state notification should be sent + * immediately, see pjsip_transport_shutdown2() for more info. + * + * Default: PJ_TRUE. + */ + pj_bool_t force; + + /** + * Specify whether UDP transports should also be shutdown. + * + * Default: PJ_TRUE. + */ + pj_bool_t include_udp; + +} pjsip_tpmgr_shutdown_param; + + +/** + * Initialize transports shutdown parameter with default values. + * + * @param prm The parameter to be initialized. + */ +PJ_DECL(void) pjsip_tpmgr_shutdown_param_default( + pjsip_tpmgr_shutdown_param *prm); + + +/** + * Shutdown all transports. This basically invokes pjsip_transport_shutdown2() + * on all transports. + * + * @param mgr The transport manager. + * @param param The function parameters. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjsip_tpmgr_shutdown_all( + pjsip_tpmgr *mgr, + const pjsip_tpmgr_shutdown_param *param); + + + /***************************************************************************** * * PUBLIC API diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index 8ac741fd5d..f33132c44b 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -837,6 +837,11 @@ typedef enum pjsua_ip_change_op { */ PJSUA_IP_CHANGE_OP_NULL, + /** + * The restart listener process. + */ + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, + /** * The restart listener process. */ @@ -2764,6 +2769,15 @@ typedef struct pjsua_ip_change_param */ unsigned restart_lis_delay; + /** + * If set to PJ_TRUE, this will forcefully shutdown all transports. + * Note that this will shutdown TCP/TLS transports only, UDP transport + * should be restarted via restart_listener. + * + * Default : PJ_TRUE + */ + pj_bool_t shutdown_transport; + } pjsua_ip_change_param; @@ -7443,7 +7457,7 @@ typedef struct pjsua_snd_dev_param */ unsigned mode; - /* + /** * The library will maintain the global sound device settings set when * opening the sound device for the first time and later can be modified * using #pjsua_snd_set_setting(). These setings are then applied to any diff --git a/pjsip/include/pjsua2/endpoint.hpp b/pjsip/include/pjsua2/endpoint.hpp index a2d946e0d5..0d2bfdc882 100644 --- a/pjsip/include/pjsua2/endpoint.hpp +++ b/pjsip/include/pjsua2/endpoint.hpp @@ -347,6 +347,15 @@ struct IpChangeParam { */ unsigned restartLisDelay; + /** + * If set to PJ_TRUE, this will forcefully shutdown all transports. + * Note that this will shutdown TCP/TLS transports only, UDP transport + * should be restarted via restart_listener. + * + * Default : PJ_TRUE + */ + bool shutdownTransport; + public: /** * Constructor. diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index 7702c67e8b..0d103f0997 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -1986,6 +1986,60 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr ) } +/** + * Initialize transports shutdown parameter with default values. + * + * @param prm The parameter to be initialized. + */ +PJ_DEF(void) pjsip_tpmgr_shutdown_param_default( + pjsip_tpmgr_shutdown_param *prm) +{ + pj_bzero(prm, sizeof(*prm)); + prm->force = PJ_TRUE; + prm->include_udp = PJ_TRUE; +} + +/* + * Shutdown all transports. + */ +PJ_DEF(pj_status_t) pjsip_tpmgr_shutdown_all( + pjsip_tpmgr *mgr, + const pjsip_tpmgr_shutdown_param *prm) +{ + pj_hash_iterator_t itr_val; + pj_hash_iterator_t *itr; + + PJ_ASSERT_RETURN(mgr, PJ_EINVAL); + + PJ_LOG(3, (THIS_FILE, "Shutting down all transports")); + + pj_lock_acquire(mgr->lock); + + itr = pj_hash_first(mgr->table, &itr_val); + while (itr) { + transport *tp_entry = (transport*)pj_hash_this(mgr->table, itr); + if (tp_entry) { + transport *tp_iter = tp_entry; + do { + pjsip_transport *tp = tp_iter->tp; + if (prm->include_udp || + ((tp->key.type & ~PJSIP_TRANSPORT_IPV6) != + PJSIP_TRANSPORT_UDP)) + { + pjsip_transport_shutdown2(tp, prm->force); + } + tp_iter = tp_iter->next; + } while (tp_iter != tp_entry); + } + itr = pj_hash_next(mgr->table, itr); + } + + pj_lock_release(mgr->lock); + + return PJ_SUCCESS; +} + + /* * pjsip_tpmgr_receive_packet() * diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 000d719a0a..8324019d9e 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -3252,6 +3252,7 @@ PJ_DEF(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param) pj_bzero(param, sizeof(*param)); param->restart_listener = PJ_TRUE; param->restart_lis_delay = PJSUA_TRANSPORT_RESTART_DELAY_TIME; + param->shutdown_transport = PJ_TRUE; } @@ -3982,6 +3983,28 @@ PJ_DEF(pj_status_t) pjsua_handle_ip_change(const pjsua_ip_change_param *param) PJ_LOG(4,(THIS_FILE,"IP change temporarily ignores request timeout")); } + /* Shutdown all TCP/TLS transports */ + if (param->shutdown_transport) { + pjsip_tpmgr_shutdown_param param; + pjsua_ip_change_op_info info; + + pjsip_tpmgr_shutdown_param_default(¶m); + param.include_udp = PJ_FALSE; + + PJ_LOG(4,(THIS_FILE, "IP change shutting down transports..")); + status = pjsip_tpmgr_shutdown_all( + pjsip_endpt_get_tpmgr(pjsua_var.endpt), + ¶m); + + /* Provide dummy info instead of NULL info to avoid possible crash + * (if app does not check). + */ + pj_bzero(&info, sizeof(info)); + pjsua_var.ua_cfg.cb.on_ip_change_progress( + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, + status, &info); + } + if (param->restart_listener) { PJSUA_LOCK(); /* Restart listener/transport, handle_ip_change_on_acc() will diff --git a/pjsip/src/pjsua2/endpoint.cpp b/pjsip/src/pjsua2/endpoint.cpp index 9f4a35e940..f206f27e3f 100644 --- a/pjsip/src/pjsua2/endpoint.cpp +++ b/pjsip/src/pjsua2/endpoint.cpp @@ -230,6 +230,7 @@ pjsua_ip_change_param IpChangeParam::toPj() const param.restart_listener = restartListener; param.restart_lis_delay = restartLisDelay; + param.shutdown_transport = shutdownTransport; return param; } @@ -239,6 +240,7 @@ void IpChangeParam::fromPj(const pjsua_ip_change_param ¶m) { restartListener = PJ2BOOL(param.restart_listener); restartLisDelay = param.restart_lis_delay; + shutdownTransport = PJ2BOOL(param.shutdown_transport); } ///////////////////////////////////////////////////////////////////////////////