Browse code

b/f: fixes RTCP relay and symmetric RTCP

Raphael Coeffic authored on 25/01/2013 13:08:57
Showing 4 changed files
... ...
@@ -209,9 +209,9 @@ void SBCCallLeg::applyAProfile()
209 209
     DBG("Enabling RTP relay mode for SBC call\n");
210 210
 
211 211
     rtp_relay_force_symmetric_rtp = call_profile.aleg_force_symmetric_rtp_value;
212
-    DBG(rtp_relay_force_symmetric_rtp ? 
213
-	"forcing symmetric RTP (passive mode)\n": 
214
-	"disabled symmetric RTP (normal mode)\n");
212
+    DBG("%s\n",rtp_relay_force_symmetric_rtp ?
213
+	"forcing symmetric RTP (passive mode)":
214
+	"disabled symmetric RTP (normal mode)");
215 215
 
216 216
     if (call_profile.aleg_rtprelay_interface_value >= 0) {
217 217
       setRtpRelayInterface(call_profile.aleg_rtprelay_interface_value);
... ...
@@ -328,9 +328,9 @@ void SBCCallLeg::applyBProfile()
328 328
       setRtpRelayInterface(call_profile.rtprelay_interface_value);
329 329
 
330 330
     rtp_relay_force_symmetric_rtp = call_profile.force_symmetric_rtp_value;
331
-    DBG(rtp_relay_force_symmetric_rtp ? 
332
-	"forcing symmetric RTP (passive mode)\n": 
333
-	"disabled symmetric RTP (normal mode)\n");
331
+    DBG("%s\n",rtp_relay_force_symmetric_rtp ?
332
+	"forcing symmetric RTP (passive mode)":
333
+	"disabled symmetric RTP (normal mode)");
334 334
   }
335 335
 
336 336
   setRtpRelayTransparentSeqno(call_profile.rtprelay_transparent_seqno);
... ...
@@ -281,7 +281,7 @@ void AudioStreamData::setRelayStream(AmRtpStream *other)
281 281
 
282 282
   if (relay_enabled && other) {
283 283
     stream->enableRtpRelay(relay_mask, other);
284
-    stream->setRAddr(relay_address, relay_port);
284
+    stream->setRAddr(relay_address, relay_port, relay_port+1);
285 285
   }
286 286
   else {
287 287
     // nothing to relay or other stream not set
... ...
@@ -335,7 +335,7 @@ int AmRtpStream::receive( unsigned char* buffer, unsigned int size,
335 335
   if (!rp)
336 336
     return 0;
337 337
 
338
-  handleSymmetricRtp(rp);
338
+  handleSymmetricRtp(&rp->addr,false);
339 339
 
340 340
   /* do we have a new talk spurt? */
341 341
   begin_talk = ((last_payload == 13) || rp->marker);
... ...
@@ -381,6 +381,7 @@ AmRtpStream::AmRtpStream(AmSession* _s, int _if)
381 381
     r_ssrc_i(false),
382 382
     session(_s),
383 383
     passive(false),
384
+    passive_rtcp(false),
384 385
     offer_answer_used(true),
385 386
     active(false), // do not return any data unless something really received
386 387
     mute(false),
... ...
@@ -438,9 +439,11 @@ string AmRtpStream::getRHost()
438 439
   return r_host;
439 440
 }
440 441
 
441
-void AmRtpStream::setRAddr(const string& addr, unsigned short port)
442
+void AmRtpStream::setRAddr(const string& addr, unsigned short port,
443
+			   unsigned short rtcp_port)
442 444
 {
443
-  DBG("RTP remote address set to %s:%u\n",addr.c_str(),port);
445
+  DBG("RTP remote address set to %s:(%u/%u)\n",
446
+      addr.c_str(),port,rtcp_port);
444 447
 
445 448
   struct sockaddr_storage ss;
446 449
   memset (&ss, 0, sizeof (ss));
... ...
@@ -454,11 +457,12 @@ void AmRtpStream::setRAddr(const string& addr, unsigned short port)
454 457
     throw string("invalid address") + addr;
455 458
   }
456 459
 
457
-  memcpy(&r_saddr,&ss,sizeof(struct sockaddr_storage));
458
-  am_set_port(&r_saddr,port);
459
-
460 460
   r_host = addr;
461
-  r_port = port;
461
+  if(port)      r_port      = port;
462
+  if(rtcp_port) r_rtcp_port = rtcp_port;
463
+
464
+  memcpy(&r_saddr,&ss,sizeof(struct sockaddr_storage));
465
+  am_set_port(&r_saddr,r_port);
462 466
 
463 467
   mute = ((r_saddr.ss_family == AF_INET) && 
464 468
 	  (SAv4(&r_saddr)->sin_addr.s_addr == INADDR_ANY)) ||
... ...
@@ -466,46 +470,50 @@ void AmRtpStream::setRAddr(const string& addr, unsigned short port)
466 470
      IN6_IS_ADDR_UNSPECIFIED(&SAv6(&r_saddr)->sin6_addr));
467 471
 }
468 472
 
469
-void AmRtpStream::handleSymmetricRtp(AmRtpPacket* rp) {
473
+void AmRtpStream::handleSymmetricRtp(struct sockaddr_storage* recv_addr, bool rtcp) {
470 474
 
471
-  if(passive) {
472
-    struct sockaddr_storage recv_addr;
473
-    rp->getAddr(&recv_addr);
475
+  if((!rtcp && passive) || (rtcp && passive_rtcp)) {
474 476
 
475
-    struct sockaddr_in* in_recv = (struct sockaddr_in*)&recv_addr;
476
-    struct sockaddr_in6* in6_recv = (struct sockaddr_in6*)&recv_addr;
477
+    struct sockaddr_in* in_recv = (struct sockaddr_in*)recv_addr;
478
+    struct sockaddr_in6* in6_recv = (struct sockaddr_in6*)recv_addr;
477 479
 
478 480
     struct sockaddr_in* in_addr = (struct sockaddr_in*)&r_saddr;
479 481
     struct sockaddr_in6* in6_addr = (struct sockaddr_in6*)&r_saddr;
480 482
 
483
+    unsigned short port = am_get_port(recv_addr);
484
+
481 485
     // symmetric RTP
482
-    if ( ((recv_addr.ss_family == AF_INET) &&
483
-	  ((in_addr->sin_port != in_recv->sin_port)
484
-	   || (in_addr->sin_addr.s_addr != in_recv->sin_addr.s_addr))) ||
485
-	 ((recv_addr.ss_family == AF_INET6) &&
486
-	  ((in6_addr->sin6_port != in6_recv->sin6_port)
487
-	   || (memcmp(&in6_addr->sin6_addr,
486
+    if ( (!rtcp && (port != r_port)) || (rtcp && (port != r_rtcp_port)) ||
487
+	 ((recv_addr->ss_family == AF_INET) &&
488
+	  (in_addr->sin_addr.s_addr != in_recv->sin_addr.s_addr)) ||
489
+	 ((recv_addr->ss_family == AF_INET6) &&
490
+	  (memcmp(&in6_addr->sin6_addr,
488 491
 		      &in6_recv->sin6_addr,
489
-		      sizeof(struct in6_addr)))))
492
+		      sizeof(struct in6_addr))))
490 493
 	 ) {
491 494
 
492
-      string addr_str = get_addr_str(&recv_addr);
493
-      int port = am_get_port(&recv_addr);
494
-      setRAddr(addr_str,port);
495
-      DBG("Symmetric RTP: setting new remote address: %s:%i\n",
496
-	  addr_str.c_str(),port);
495
+      string addr_str = get_addr_str(recv_addr);
496
+      setRAddr(addr_str, !rtcp ? port : 0, rtcp ? port : 0);
497
+      DBG("Symmetric %s: setting new remote address: %s:%i\n",
498
+	  !rtcp ? "RTP" : "RTCP", addr_str.c_str(),port);
499
+
497 500
     } else {
498
-      DBG("Symmetric RTP: remote end sends RTP from advertised address."
499
-	  " Leaving passive mode.\n");
501
+      const char* prot = rtcp ? "RTCP" : "RTP";
502
+      DBG("Symmetric %s: remote end sends %s from advertised address."
503
+	  " Leaving passive mode.\n",prot,prot);
500 504
     }
505
+
501 506
     // avoid comparing each time sender address
502
-    passive = false;
507
+    if(!rtcp)
508
+      passive = false;
509
+    else
510
+      passive_rtcp = false;
503 511
   }
504 512
 }
505 513
 
506 514
 void AmRtpStream::setPassiveMode(bool p)
507 515
 {
508
-  passive = p;
516
+  passive_rtcp = passive = p;
509 517
   DBG("The other UA is NATed: switched to passive mode.\n");
510 518
 }
511 519
 
... ...
@@ -759,7 +767,7 @@ void AmRtpStream::bufferPacket(AmRtpPacket* p)
759 767
 	    p->timestamp,this);
760 768
 	active = false;
761 769
       }
762
-      handleSymmetricRtp(p);
770
+      handleSymmetricRtp(&p->addr,false);
763 771
 
764 772
       if (NULL != relay_stream) {
765 773
         relay_stream->relay(p);
... ...
@@ -941,14 +949,22 @@ void AmRtpStream::recvPacket(int fd)
941 949
 
942 950
 void AmRtpStream::recvRtcpPacket()
943 951
 {
952
+  struct sockaddr_storage recv_addr;
953
+  socklen_t recv_addr_len = sizeof(recv_addr);
944 954
   unsigned char buffer[4096];
945 955
 
946
-  int recved_bytes = recv(l_rtcp_sd,buffer,sizeof(buffer),0);
956
+  int recved_bytes = recvfrom(l_rtcp_sd,buffer,sizeof(buffer),0,
957
+			      (struct sockaddr*)&recv_addr,
958
+			      &recv_addr_len);
959
+
947 960
   if(recved_bytes < 0) {
948 961
     ERROR("rtcp recv(%d): %s",l_rtcp_sd,strerror(errno));
949 962
     return;
950 963
   }
951 964
 
965
+  // clear RTP timer
966
+  clearRTPTimeout();
967
+
952 968
   if(!relay_enabled || !relay_stream ||
953 969
      !relay_stream->l_sd)
954 970
     return;
... ...
@@ -958,9 +974,11 @@ void AmRtpStream::recvRtcpPacket()
958 974
     return;
959 975
   }
960 976
 
977
+  handleSymmetricRtp(&recv_addr,true);
978
+
961 979
   struct sockaddr_storage rtcp_raddr;
962 980
   memcpy(&rtcp_raddr,&relay_stream->r_saddr,sizeof(rtcp_raddr));
963
-  am_set_port(&rtcp_raddr, relay_stream->r_port+1);
981
+  am_set_port(&rtcp_raddr, relay_stream->r_rtcp_port);
964 982
 
965 983
   int err = sendto(relay_stream->l_rtcp_sd,buffer,recved_bytes,0,
966 984
 		   (const struct sockaddr *)&rtcp_raddr,
... ...
@@ -187,6 +187,7 @@ protected:
187 187
   /** Remote host information */
188 188
   string             r_host;
189 189
   unsigned short     r_port;
190
+  unsigned short     r_rtcp_port;
190 191
 
191 192
   /** 
192 193
    * Local interface used for this stream
... ...
@@ -220,8 +221,9 @@ protected:
220 221
   unsigned int   r_ssrc;
221 222
   bool           r_ssrc_i;
222 223
 
223
-  /** symmetric RTP */
224
-  bool           passive;      // passive mode ?
224
+  /** symmetric RTP & RTCP */
225
+  bool           passive;
226
+  bool           passive_rtcp;
225 227
 
226 228
   /** mute && port == 0 */
227 229
   bool           hold;
... ...
@@ -271,8 +273,8 @@ protected:
271 273
   /* Get next packet from the buffer queue */
272 274
   int nextPacket(AmRtpPacket*& p);
273 275
   
274
-  /** handle symmetric RTP - if in passive mode, update raddr from rp */
275
-  void handleSymmetricRtp(AmRtpPacket* rp);
276
+  /** handle symmetric RTP/RTCP - if in passive mode, update raddr from rp */
277
+  void handleSymmetricRtp(struct sockaddr_storage* recv_addr, bool rtcp);
276 278
 
277 279
   void relay(AmRtpPacket* p);
278 280
 
... ...
@@ -368,11 +370,12 @@ public:
368 370
   /**
369 371
    * Set remote IP & port.
370 372
    */
371
-  void setRAddr(const string& addr, unsigned short port);
373
+  void setRAddr(const string& addr, unsigned short port,
374
+		unsigned short rtcp_port = 0);
372 375
 
373
-  /** Symmetric RTP: passive mode ? */
376
+  /** Symmetric RTP & RTCP: passive mode ? */
374 377
   void setPassiveMode(bool p);
375
-  bool getPassiveMode() { return passive; }
378
+  bool getPassiveMode() { return passive || passive_rtcp; }
376 379
 
377 380
   unsigned int get_ssrc() { return l_ssrc; }
378 381