Ticket #528: committed ticket528.patch



git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1944 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h
index 19869a9..51bab86 100644
--- a/pjmedia/include/pjmedia/transport.h
+++ b/pjmedia/include/pjmedia/transport.h
@@ -306,6 +306,20 @@
 			     pj_size_t size);
 
     /**
+     * This function is called by the stream to send RTCP packet using the
+     * transport with destination address other than default specified in
+     * #pjmedia_transport_attach().
+     *
+     * Application should call #pjmedia_transport_send_rtcp2() instead of 
+     * calling this function directly.
+     */
+    pj_status_t (*send_rtcp2)(pjmedia_transport *tp,
+			      const pj_sockaddr_t *addr,
+			      unsigned addr_len,
+			      const void *pkt,
+			      pj_size_t size);
+
+    /**
      * This function is called by application to generate the SDP parts
      * related to transport type, e.g: ICE, SRTP.
      *
@@ -587,6 +601,31 @@
 
 
 /**
+ * Send RTCP packet with the specified media transport. This is just a simple
+ * wrapper which calls <tt>send_rtcp2()</tt> member of the transport. The 
+ * RTCP packet will be delivered to the destination address specified in
+ * param addr, if addr is NULL, RTCP packet will be delivered to destination 
+ * address specified in #pjmedia_transport_attach() function.
+ *
+ * @param tp	    The media transport.
+ * @param addr	    The destination address.
+ * @param addr_len  Length of destination address.
+ * @param pkt	    The packet to send.
+ * @param size	    Size of the packet.
+ *
+ * @return	    PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_send_rtcp2(pjmedia_transport *tp,
+						    const pj_sockaddr_t *addr,
+						    unsigned addr_len,
+						    const void *pkt,
+						    pj_size_t size)
+{
+    return (*tp->op->send_rtcp2)(tp, addr, addr_len, pkt, size);
+}
+
+
+/**
  * Generate local SDP parts that are related to the specified media transport.
  * Remote SDP might be needed as reference when application is in deciding
  * side of negotiation (callee side), otherwise it should be NULL.
diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c
index 59408dd..96581ad 100644
--- a/pjmedia/src/pjmedia/transport_ice.c
+++ b/pjmedia/src/pjmedia/transport_ice.c
@@ -75,6 +75,11 @@
 static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
 				       const void *pkt,
 				       pj_size_t size);
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+				       const pj_sockaddr_t *addr,
+				       unsigned addr_len,
+				       const void *pkt,
+				       pj_size_t size);
 static pj_status_t transport_media_create(pjmedia_transport *tp,
 				       pj_pool_t *pool,
 				       unsigned options,
@@ -110,6 +115,7 @@
     &transport_detach,
     &transport_send_rtp,
     &transport_send_rtcp,
+    &transport_send_rtcp2,
     &transport_media_create,
     &transport_media_start,
     &transport_media_stop,
@@ -770,11 +776,23 @@
 				       const void *pkt,
 				       pj_size_t size)
 {
+    return transport_send_rtcp2(tp, NULL, 0, pkt, size);
+}
+
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+				        const pj_sockaddr_t *addr,
+				        unsigned addr_len,
+				        const void *pkt,
+				        pj_size_t size)
+{
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
     if (tp_ice->ice_st->comp_cnt > 1) {
-	return pj_ice_strans_sendto(tp_ice->ice_st, 2, 
-				    pkt, size, &tp_ice->remote_rtcp,
-				    sizeof(pj_sockaddr_in));
+	if (addr == NULL) {
+	    addr = &tp_ice->remote_rtcp;
+	    addr_len = pj_sockaddr_get_len(addr);
+	}
+	return pj_ice_strans_sendto(tp_ice->ice_st, 2, pkt, size, 
+				    addr, addr_len);
     } else {
 	return PJ_SUCCESS;
     }
diff --git a/pjmedia/src/pjmedia/transport_srtp.c b/pjmedia/src/pjmedia/transport_srtp.c
index 03470d2..1bcf71f 100644
--- a/pjmedia/src/pjmedia/transport_srtp.c
+++ b/pjmedia/src/pjmedia/transport_srtp.c
@@ -145,6 +145,11 @@
 static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
 				       const void *pkt,
 				       pj_size_t size);
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+				       const pj_sockaddr_t *addr,
+				       unsigned addr_len,
+				       const void *pkt,
+				       pj_size_t size);
 static pj_status_t transport_media_create(pjmedia_transport *tp,
 				       pj_pool_t *pool,
 				       unsigned options,
@@ -171,6 +176,7 @@
     &transport_detach,
     &transport_send_rtp,
     &transport_send_rtcp,
+    &transport_send_rtcp2,
     &transport_media_create,
     &transport_media_start,
     &transport_media_stop,
@@ -657,13 +663,24 @@
 				       const void *pkt,
 				       pj_size_t size)
 {
+    return transport_send_rtcp2(tp, NULL, 0, pkt, size);
+}
+
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+				        const pj_sockaddr_t *addr,
+				        unsigned addr_len,
+				        const void *pkt,
+				        pj_size_t size)
+{
     pj_status_t status;
     transport_srtp *srtp = (transport_srtp*) tp;
     int len = size;
     err_status_t err;
 
-    if (srtp->bypass_srtp)
-	return pjmedia_transport_send_rtcp(srtp->real_tp, pkt, size);
+    if (srtp->bypass_srtp) {
+	return pjmedia_transport_send_rtcp2(srtp->real_tp, addr, addr_len, 
+	                                    pkt, size);
+    }
 
     if (!srtp->session_inited)
 	return PJ_SUCCESS;
@@ -677,8 +694,8 @@
     err = srtp_protect_rtcp(srtp->srtp_tx_ctx, srtp->tx_buffer, &len);
     
     if (err == err_status_ok) {
-	status = pjmedia_transport_send_rtcp(srtp->real_tp, srtp->tx_buffer, 
-					     len);
+	status = pjmedia_transport_send_rtcp2(srtp->real_tp, addr, addr_len,
+					      srtp->tx_buffer, len);
     } else {
 	status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
     }
@@ -688,6 +705,7 @@
     return status;
 }
 
+
 static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
 					   pjmedia_dir dir,
 					   unsigned pct_lost)
diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c
index a6c5b68..0804b8b 100644
--- a/pjmedia/src/pjmedia/transport_udp.c
+++ b/pjmedia/src/pjmedia/transport_udp.c
@@ -121,6 +121,11 @@
 static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
 				       const void *pkt,
 				       pj_size_t size);
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+				       const pj_sockaddr_t *addr,
+				       unsigned addr_len,
+				       const void *pkt,
+				       pj_size_t size);
 static pj_status_t transport_media_create(pjmedia_transport *tp,
 				       pj_pool_t *pool,
 				       unsigned options,
@@ -146,6 +151,7 @@
     &transport_detach,
     &transport_send_rtp,
     &transport_send_rtcp,
+    &transport_send_rtcp2,
     &transport_media_create,
     &transport_media_start,
     &transport_media_stop,
@@ -748,16 +754,31 @@
 				       const void *pkt,
 				       pj_size_t size)
 {
+    return transport_send_rtcp2(tp, NULL, 0, pkt, size);
+}
+
+
+/* Called by application to send RTCP packet */
+static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
+					const pj_sockaddr_t *addr,
+					unsigned addr_len,
+				        const void *pkt,
+				        pj_size_t size)
+{
     struct transport_udp *udp = (struct transport_udp*)tp;
     pj_ssize_t sent;
     pj_status_t status;
 
     PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
 
+    if (addr == NULL) {
+	addr = &udp->rem_rtcp_addr;
+	addr_len = udp->addr_len;
+    }
+
     sent = size;
     status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op,
-				pkt, &sent, 0,
-				&udp->rem_rtcp_addr, udp->addr_len);
+				pkt, &sent, 0, addr, addr_len);
 
     if (status==PJ_SUCCESS || status==PJ_EPENDING)
 	return PJ_SUCCESS;