Redesign RTP/RTCP stuffs so that stream does not create thread implicitly. Changed pjmedia_endpt_create() API.

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@350 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index ea84746..b01b968 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -97,6 +97,73 @@
 }
 
 
+/* 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 @@
 
 	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 @@
 
     /* 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 @@
     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;
     }