summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua-lib/pjsua_call.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsua-lib/pjsua_call.c')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c86
1 files changed, 72 insertions, 14 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index ea847464..b01b968d 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -97,6 +97,73 @@ static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e,
}
+/* Close and reopen socket. */
+static pj_status_t reopen_sock( pj_sock_t *sock)
+{
+ pj_sockaddr_in addr;
+ int addrlen;
+ pj_status_t status;
+
+ addrlen = sizeof(pj_sockaddr_in);
+ status = pj_sock_getsockname(*sock, &addr, &addrlen);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error getting RTP/RTCP socket name", status);
+ return status;
+ }
+
+ pj_sock_close(*sock);
+
+ status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, sock);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to create socket", status);
+ return status;
+ }
+
+ status = pj_sock_bind(*sock, &addr, sizeof(pj_sockaddr_in));
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to re-bind RTP/RTCP socket", status);
+ return status;
+ }
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Destroy the call's media
+ */
+static pj_status_t call_destroy_media(int call_index)
+{
+ pjsua_call *call = &pjsua.calls[call_index];
+
+ if (call->conf_slot > 0) {
+ pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot);
+ call->conf_slot = 0;
+ }
+
+ if (call->session) {
+
+ /* Close and reopen RTP socket.
+ * This is necessary to get the socket unregistered from ioqueue,
+ * when IOCompletionPort is used.
+ */
+ reopen_sock(&call->skinfo.rtp_sock);
+
+ /* Close and reopen RTCP socket too. */
+ reopen_sock(&call->skinfo.rtcp_sock);
+
+ /* Must destroy session after socket is closed. */
+ pjmedia_session_destroy(call->session);
+ call->session = NULL;
+
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",
+ call_index));
+
+ return PJ_SUCCESS;
+}
+
+
/**
* Make outgoing call.
*/
@@ -494,13 +561,8 @@ static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
pj_assert(call != NULL);
- if (call && call->session) {
- pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
-
- PJ_LOG(3,(THIS_FILE,"Media session is destroyed"));
- }
+ if (call)
+ call_destroy_media(call->index);
/* Remove timers. */
schedule_call_timer(call, &call->refresh_tm, REFRESH_CALL_TIMER, 0);
@@ -878,11 +940,8 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
/* Destroy existing media session, if any. */
- if (call && call->session) {
- pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
- }
+ if (call)
+ call_destroy_media(call->index);
/* Get local and remote SDP */
@@ -947,8 +1006,7 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create conference slot",
status);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
+ call_destroy_media(call->index);
//call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR);
return;
}