ccRTP 2.1.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
control.cpp
Go to the documentation of this file.
1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction. Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License. This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27 //
28 // This exception applies only to the code released under the name GNU
29 // ccRTP. If you copy code from other releases into a copy of GNU
30 // ccRTP, as the General Public License permits, the exception does
31 // not apply to the code that you add in this way. To avoid misleading
32 // anyone as to the status of such modified files, you must delete
33 // this exception notice from them.
34 //
35 // If you write modifications of your own for GNU ccRTP, it is your choice
36 // whether to permit this exception to apply to your modifications.
37 // If you do not wish that, delete this exception notice.
38 //
39 
46 #include "private.h"
47 #include <cstdlib>
48 #include <ccrtp/cqueue.h>
49 #include <cstdlib>
50 #include <climits>
51 
52 NAMESPACE_COMMONCPP
53 
55 const double QueueRTCPManager::RECONSIDERATION_COMPENSATION = 2.718281828 - 1.5;
60 
63 queueApplication(app), srtcpIndex(0)
64 {
65  controlServiceActive = false;
66  controlBwFract = 0.05f;
67  sendControlBwFract = 0.25;
69  ctrlSendCount = 0;
70 
72 
74 
75  // initialize RTCP timing
76  reconsInfo.rtcpTp.tv_sec = reconsInfo.rtcpTc.tv_sec =
77  reconsInfo.rtcpTn.tv_sec = 0;
78  reconsInfo.rtcpTp.tv_usec = reconsInfo.rtcpTc.tv_usec =
79  reconsInfo.rtcpTn.tv_usec = 0;
80  reconsInfo.rtcpPMembers = 1;
81 
82  rtcpWeSent = false;
83  rtcpAvgSize = sizeof(RTCPFixedHeader) + sizeof(uint32) +
84  sizeof(SenderInfo);
85  rtcpInitial = true;
86  // force an initial check for incoming RTCP packets
87  SysTime::gettimeofday(&rtcpNextCheck,NULL);
88  // check for incoming RTCP packets every 1/4 seconds.
89  rtcpCheckInterval.tv_sec = 0;
90  rtcpCheckInterval.tv_usec = 250000;
92 
94 
95  rtcpMinInterval = 5000000; // 5 seconds.
96 
97  leavingDelay = 1000000; // 1 second
99 
100  // Fill in fixed fields that will never change
101  RTCPPacket* pkt = reinterpret_cast<RTCPPacket*>(rtcpSendBuffer);
102  pkt->fh.version = CCRTP_VERSION;
103  // (SSRCCollision will have to take this into account)
104  pkt->info.SR.ssrc = getLocalSSRCNetwork();
105 
106  // allow to start RTCP service once everything is set up
107  controlServiceActive = true;
108 }
109 
110 // TODO Streamline this code (same as above, put into a separate method)
111 QueueRTCPManager::QueueRTCPManager(uint32 ssrc, uint32 size, RTPApplication& app):
112 RTPDataQueue(&ssrc, size),
114 queueApplication(app), srtcpIndex(0)
115 {
116  controlServiceActive = false;
117  controlBwFract = 0.05f;
118  sendControlBwFract = 0.25;
120  ctrlSendCount = 0;
121 
123 
125 
126  // initialize RTCP timing
127  reconsInfo.rtcpTp.tv_sec = reconsInfo.rtcpTc.tv_sec =
128  reconsInfo.rtcpTn.tv_sec = 0;
129 
130  reconsInfo.rtcpTp.tv_usec = reconsInfo.rtcpTc.tv_usec =
131  reconsInfo.rtcpTn.tv_usec = 0;
132 
133  reconsInfo.rtcpPMembers = 1;
134 
135  rtcpWeSent = false;
136  rtcpAvgSize = sizeof(RTCPFixedHeader) + sizeof(uint32) + sizeof(SenderInfo);
137  rtcpInitial = true;
138  // force an initial check for incoming RTCP packets
139  SysTime::gettimeofday(&rtcpNextCheck,NULL);
140  // check for incoming RTCP packets every 1/4 seconds.
141  rtcpCheckInterval.tv_sec = 0;
142  rtcpCheckInterval.tv_usec = 250000;
144 
146 
147  rtcpMinInterval = 5000000; // 5 seconds.
148 
149  leavingDelay = 1000000; // 1 second
151 
152  // Fill in fixed fields that will never change
153  RTCPPacket* pkt = reinterpret_cast<RTCPPacket*>(rtcpSendBuffer);
154  pkt->fh.version = CCRTP_VERSION;
155  // (SSRCCollision will have to take this into account)
156  pkt->info.SR.ssrc = getLocalSSRCNetwork();
157 
158  // allow to start RTCP service once everything is set up
159  controlServiceActive = true;
160 }
161 
163 {
165 }
166 
168 {
169  controlServiceActive = false;
171  removeOutQueueCryptoContextCtrl(NULL); // remove the outgoing crypto context
172  removeInQueueCryptoContextCtrl(NULL); // Remove any incoming crypto contexts
173 
174 }
175 
177 bool is_new, InetAddress& network_address, tpport_t transport_port)
178 {
179  bool result = true;
180 
181  // Test if the source is new and it is not the local one.
182  if ( is_new && sourceLink.getSource()->getID() != getLocalSSRC() )
183  return result;
184 
185  SyncSource *s = sourceLink.getSource();
186  if ( s->getControlTransportPort() != transport_port ||
187  s->getNetworkAddress() != network_address ) {
188  // SSRC collision or a loop has happened
189  if ( s->getID() != getLocalSSRC() ) {
190  // TODO: Optional error counter.
191 
192  // Note this differs from the default in the RFC.
193  // Discard packet only when the collision is
194  // repeating (to avoid flip-flopping)
195  if ( sourceLink.getPrevConflict() &&
196  (
197  (network_address ==
198  sourceLink.getPrevConflict()->networkAddress)
199  &&
200  (transport_port ==
202  ) ) {
203  // discard packet and do not flip-flop
204  result = false;
205  } else {
206  // Record who has collided so that in
207  // the future we can how if the
208  // collision repeats.
209  sourceLink.setPrevConflict(network_address,
210  0,transport_port);
211  // Change sync source transport address
212  setControlTransportPort(*s,transport_port);
213  setNetworkAddress(*s,network_address);
214  }
215 
216  } else {
217  // Collision or loop of own packets.
218  ConflictingTransportAddress* conflicting =
219  searchControlConflict(network_address,
220  transport_port);
221  if ( conflicting ) {
222  // Optional error counter.
223  updateConflict(*conflicting);
224  result = false;
225  } else {
226  // New collision
230  dispatchBYE("SSRC collision detected when receiving RTCP packet");
231  renewLocalSSRC();
232  setNetworkAddress(*s,network_address);
233  setControlTransportPort(*s,transport_port);
235  sourceLink.initStats();
236  }
237  }
238  }
239  return result;
240 }
241 
243 {
244  if ( !controlServiceActive )
245  return;
246 
247  // A) see if there are incoming RTCP packets
248  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
249  if ( timercmp(&(reconsInfo.rtcpTc),&rtcpNextCheck,>=) ) {
250  while ( isPendingControl(0) )
252  // If this do loops more than once, then we have not
253  // been in time. So it skips until the next future
254  // instant.
255  do {
256  timeval tmp = rtcpNextCheck;
257  timeradd(&rtcpLastCheck,&rtcpCheckInterval,
258  &rtcpNextCheck);
259  rtcpLastCheck = tmp;
260  } while ( timercmp(&(reconsInfo.rtcpTc), &(rtcpNextCheck), >=) );
261  }
262 }
263 
265 {
266  if ( !controlServiceActive )
267  return;
268 
269  // B) send RTCP packets
270  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
271  if ( timercmp(&(reconsInfo.rtcpTc),&(reconsInfo.rtcpTn),>=) ) {
272  if ( timerReconsideration() ) {
273  // this would update to last received RTCP packets
274  //while ( isPendingControl(0) )
275  // takeInControlPacket();
276  rtcpLastCheck = reconsInfo.rtcpTc;
278  if (rtcpInitial)
279  rtcpInitial = false;
280  expireSSRCs();
281  reconsInfo.rtcpTp = reconsInfo.rtcpTc;
282  // we have updated tp and sent a report, so we
283  // have to recalculate the sending interval
284  timeval T = computeRTCPInterval();
285  timeradd(&(reconsInfo.rtcpTc),&T,&(reconsInfo.rtcpTn));
286 
287  // record current number of members for the
288  // next check.
289  reconsInfo.rtcpPMembers = getMembersCount();
290  }
291  }
292 }
293 
295 {
296  bool result = false;
297  // compute again the interval to confirm it under current
298  // circumstances
299  timeval T = computeRTCPInterval();
300  timeradd(&(reconsInfo.rtcpTp),&T,&(reconsInfo.rtcpTn));
301  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
302  if ( timercmp(&(reconsInfo.rtcpTc),&(reconsInfo.rtcpTn),>=) ) {
303  reconsInfo.rtcpTp = reconsInfo.rtcpTc;
304  result = true;
305  }
306  return result;
307 }
308 
309 void
311 {}
312 
313 void
315 {
316  size_t len = 0;
317  InetHostAddress network_address;
318  tpport_t transport_port;
319  len = recvControl(rtcpRecvBuffer,getPathMTU(),network_address, transport_port);
320 
321  // get time of arrival
322  struct timeval recvtime;
323  SysTime::gettimeofday(&recvtime,NULL);
324 
325  // process a 'len' octets long RTCP compound packet
326 
327  RTCPPacket *pkt = reinterpret_cast<RTCPPacket *>(rtcpRecvBuffer);
328 
330  if (pcc == NULL) {
332  if (pcc != NULL) {
333  pcc = pcc->newCryptoContextForSSRC(pkt->getSSRC());
334  if (pcc != NULL) {
335  pcc->deriveSrtcpKeys();
337  }
338  }
339  }
340  // If no crypto context: then SRTP/SRTCP is off
341  // If crypto context is available then unprotect data here. If an error
342  // occurs report the error and discard the packet.
343  if (pcc != NULL) {
344  int32 ret;
345  if ((ret = unprotect(rtcpRecvBuffer, len, pcc)) < 0) {
346  // TODO: do more error handling?
347  return;
348  }
349  len = ret; // adjust length after unprotecting the packet
350  }
351  // Check validity of the header fields of the compound packet
353  return;
354 
355 
356  // TODO: for now, we do nothing with the padding bit
357  // in the header.
358 
359  bool source_created;
360  SyncSourceLink* sourceLink = getSourceBySSRC(pkt->getSSRC(),source_created);
361  SyncSource* s = sourceLink->getSource();
362 
363  if ( source_created ) {
364  // Set control transport address.
365  setControlTransportPort(*s,transport_port);
366  // Network address is assumed to be the same as the control one
367  setNetworkAddress(*s,network_address);
368  sourceLink->initStats();
370  if ( sourceLink->getHello() )
371  onNewSyncSource(*s);
372  } else if ( s->getControlTransportPort() == 0 ) {
373  // Test if RTP data packets had been received but this
374  // is the first control packet from this source.
375  setControlTransportPort(*s,transport_port);
376  }
377  // record reception time
378  sourceLink->lastRTCPPacketTime = recvtime;
379  sourceLink->lastRTCPSRTime = recvtime;
380 
381  size_t pointer = 0;
382  // Check the first packet is a report and do special
383  // processing for SR reports.
384  if ( RTCPPacket::tRR == pkt->fh.type ) {
385  // no special initialization is required for
386  // RR reports, all reports will be processed
387  // in the do-while down here.
388  } else if ( RTCPPacket::tSR == pkt->fh.type ){
389  if ( checkSSRCInRTCPPkt(*sourceLink,source_created,
390  network_address,
391  transport_port) )
392  sourceLink->lastRTCPSRTime = recvtime;
393  onGotSR(*s,pkt->info.SR,pkt->fh.block_count);
394  // Advance to the next packet in the compound.
395  pointer += pkt->getLength();
396  pkt = reinterpret_cast<RTCPPacket *>(rtcpRecvBuffer +pointer);
397  } else if ( RTCPPacket::tXR == pkt->fh.type ) {
398  // TODO: handle XR reports.
399  } else {
400  // Ignore RTCP types unknown.
401  }
402 
403  // Process all RR reports.
404  while ( (pointer < len) && (RTCPPacket::tRR == pkt->fh.type) ) {
405  sourceLink = getSourceBySSRC(pkt->getSSRC(),
406  source_created);
407  if ( checkSSRCInRTCPPkt(*sourceLink,source_created,
408  network_address,transport_port) )
409  onGotRR(*s,pkt->info.RR,pkt->fh.block_count);
410  // Advance to the next packet in the compound
411  pointer += pkt->getLength();
412  pkt = reinterpret_cast<RTCPPacket *>(rtcpRecvBuffer +pointer);
413  }
414 
415  // SDES, APP and BYE. process first everything but the
416  // BYE packets.
417  bool cname_found = false;
418  while ( (pointer < len ) &&
419  (pkt->fh.type == RTCPPacket::tSDES ||
420  pkt->fh.type == RTCPPacket::tAPP) ) {
421  I ( cname_found || !pkt->fh.padding );
422  sourceLink = getSourceBySSRC(pkt->getSSRC(),
423  source_created);
424  if ( checkSSRCInRTCPPkt(*sourceLink,source_created,
425  network_address,
426  transport_port) ) {
427  if ( pkt->fh.type == RTCPPacket::tSDES ) {
428  bool cname = onGotSDES(*s,*pkt);
429  cname_found = cname_found? cname_found : cname;
430  } else if ( pkt->fh.type == RTCPPacket::tAPP ) {
431  onGotAPP(*s,pkt->info.APP,pkt->getLength());
432  // pointer += pkt->getLength();
433  } else {
434  // error?
435  }
436  }
437  // Get the next packet in the compound.
438  pointer += pkt->getLength();
439  pkt = reinterpret_cast<RTCPPacket *>(rtcpRecvBuffer +pointer);
440  }
441 
442  // TODO: error? if !cname_found
443 
444  // process BYE packets
445  while ( pointer < len ) {
446  if ( pkt->fh.type == RTCPPacket::tBYE ) {
447  sourceLink = getSourceBySSRC(pkt->getSSRC(),
448  source_created);
449  if ( checkSSRCInRTCPPkt(*sourceLink,source_created,
450  network_address,
451  transport_port) )
452  getBYE(*pkt,pointer,len);
453  } else if ( pkt->fh.type != RTCPPacket::tBYE ) {
454  break; // TODO: check non-BYE out of place.
455  } else {
456  break;
457  }
458  }
459 
460  // Call plug-in in case there are profile extensions
461  // at the end of the SR/RR.
462  if ( pointer != len ) {
464  len - pointer);
465  }
466 
467  // Everything went right, update the RTCP average size
468  updateAvgRTCPSize(len);
469 }
470 
472 {
473  bool result = false;
474 
475  if ( 0 != getEnd2EndDelay() ) {
476  SyncSourceLink* sl = pl.getSourceLink();
477  void* si = sl->getSenderInfo();
478  if ( NULL != si ) {
479  RTCPSenderInfo rsi(si);
480  uint32 tsInc = pl.getPacket()->getTimestamp() -
481  rsi.getRTPTimestamp();
482  // approx.
483  microtimeout_t Inc = tsInc * 1000 /
484  (getCurrentRTPClockRate() / 1000);
485  timeval timevalInc = microtimeout2Timeval(Inc);
486 
487  timeval tNTP = NTP2Timeval(rsi.getNTPTimestampInt(),
488  rsi.getNTPTimestampFrac());
489  timeval packetTime;
490  timeradd(&tNTP,&timevalInc,&packetTime);
491  timeval now, diff;
492  SysTime::gettimeofday(&now,NULL);
493  timersub(&now,&packetTime,&diff);
494 
495  if ( timeval2microtimeout(diff) > getEnd2EndDelay() )
496  result = true;
497  }
498  }
499  return result;
500 }
501 
503 {
504  // We ignore the receiver blocks and just get the sender info
505  // at the beginning of the SR.
506  getLink(source)->setSenderInfo(reinterpret_cast<unsigned char*>(&(SR.sinfo)));
507 }
508 
509 void QueueRTCPManager::onGotRR(SyncSource& source, RecvReport& RR, uint8 blocks)
510 {
511  for ( uint8 i = 0; i < blocks; i++) {
512  // this generic RTCP manager ignores reports about
513  // other sources than the local one
514  if ( getLocalSSRCNetwork() == RR.ssrc ) {
515  getLink(source)->
516  setReceiverInfo
517  (reinterpret_cast<unsigned char*>(&(RR.blocks[i].rinfo)));
518  }
519  }
520 }
521 
523 {
524  size_t newlen = len;
525  newlen += lowerHeadersSize;
526  rtcpAvgSize = (uint16)(( (15 * rtcpAvgSize) >> 4 ) + ( newlen >> 4));
527 }
528 
529 bool QueueRTCPManager::getBYE(RTCPPacket& pkt, size_t& pointer, size_t)
530 {
531  if ( 0 == pkt.fh.block_count )
532  return false;
533 
534  char *reason = NULL;
535 
536  if ( (sizeof(RTCPFixedHeader) + pkt.fh.block_count * sizeof(uint32))
537  < pkt.getLength() ) {
538  uint16 endpointer = (uint16)(pointer + sizeof(RTCPFixedHeader) +
539  pkt.fh.block_count * sizeof(uint32));
540  uint16 len = rtcpRecvBuffer[endpointer];
541  reason = new char[len + 1];
542  memcpy(reason,rtcpRecvBuffer + endpointer + 1,len);
543  reason[len] = '\0';
544  } else { // avoid dangerous conversion of NULL to a C++ string.
545  reason = new char[1];
546  reason[0] = '\0';
547  }
548 
549  int i = 0;
550  while ( i < pkt.fh.block_count ) {
551  bool created;
552  SyncSourceLink* srcLink =
553  getSourceBySSRC(pkt.getSSRC(),created);
554  i++;
555  if( srcLink->getGoodbye() )
556  onGotGoodbye(*(srcLink->getSource()),reason);
557  BYESource(pkt.getSSRC());
559 
561  }
562 
563  delete [] reason;
564  pointer += pkt.getLength();
565  return true;
566 }
567 
569 {
570  if ( getMembersCount() < reconsInfo.rtcpPMembers ) {
571  timeval inc;
572 
573  // reconsider reconsInfo.rtcpTn (time for next RTCP packet)
574  microtimeout_t t =
575  (reconsInfo.rtcpTn.tv_sec - reconsInfo.rtcpTc.tv_sec) *
576  1000000 +
577  (reconsInfo.rtcpTn.tv_usec - reconsInfo.rtcpTc.tv_usec);
578  t *= getMembersCount();
579  t /= reconsInfo.rtcpPMembers;
580  inc.tv_usec = t % 1000000;
581  inc.tv_sec = t / 1000000;
582  timeradd(&(reconsInfo.rtcpTc),&inc,&(reconsInfo.rtcpTn));
583 
584  // reconsider tp (time for previous RTCP packet)
585  t = (reconsInfo.rtcpTc.tv_sec - reconsInfo.rtcpTp.tv_sec) *
586  1000000 +
587  (reconsInfo.rtcpTc.tv_usec - reconsInfo.rtcpTp.tv_usec);
588  t *= getMembersCount();
589  t /= reconsInfo.rtcpPMembers;
590  inc.tv_usec = t % 1000000;
591  inc.tv_sec = t / 1000000;
592  timeradd(&(reconsInfo.rtcpTc),&inc,&(reconsInfo.rtcpTp));
593  }
594  reconsInfo.rtcpPMembers = getMembersCount();
595 }
596 
598 {
599  // Take into account that length fields in SDES items are
600  // 8-bit long, so no ntoh[s|l] is required
601  bool cname_found = false;
602 
603  std::ptrdiff_t pointer = reinterpret_cast<unsigned char*>(&pkt) - rtcpRecvBuffer;
604  uint16 i = 0;
605  do {
606  size_t len = pkt.getLength();
607  pointer += sizeof(RTCPFixedHeader);
608  SDESChunk* chunk = (SDESChunk*)(rtcpRecvBuffer + pointer);
609 
610  bool source_created = false;
611  // TODO: avoid searching again the source of the first chunk.
612  SyncSourceLink* sourceLink =
613  getSourceBySSRC(chunk->getSSRC(),
614  source_created);
615  // TODO: check that there are no two chunks with the
616  // same SSRC but different CNAME
617  SyncSource& src = *( sourceLink->getSource() );
618 
619  if ( onGotSDESChunk(source,*chunk,len) )
620  cname_found = true;
621  pointer +=len;
622  if( sourceLink->getHello() )
623  onNewSyncSource(src);
624  i++;
625  } while ( i < pkt.fh.block_count );
626  return cname_found;
627 }
628 
629 bool QueueRTCPManager::onGotSDESChunk(SyncSource& source, SDESChunk& chunk, size_t len)
630 {
631  bool cname_found = false;
632  bool end = false;
633 
634  SyncSourceLink* srcLink = getLink(source);
635  Participant* part = source.getParticipant();
636 
637  size_t pointer = sizeof(chunk.ssrc);
638 
639  // process chunk items
640  while ( (pointer < len) && !end ) {
641  SDESItem* item =
642  reinterpret_cast<SDESItem*>(size_t(&(chunk)) + pointer);
643  if ( item->type > SDESItemTypeEND && item->type <= SDESItemTypeLast) {
644  pointer += sizeof(item->type) + sizeof(item->len) +
645  item->len;
646  if ( NULL == part && SDESItemTypeCNAME == item->type ) {
647  const RTPApplication& app = getApplication();
648  std::string cname = std::string(item->data,item->len);
649  const Participant* p = app.getParticipant(cname);
650  if ( p ) {
651  part = const_cast<Participant*>(p);
652  setParticipant(*(srcLink->getSource()),*part);
653  } else {
654  part = new Participant("-");
655  addParticipant(const_cast<RTPApplication&>(getApplication()),*part);
656  }
657  setParticipant(*(srcLink->getSource()),*part);
658  }
659 
660  // support for CNAME updates
661  if ( part )
662  setSDESItem(part,(SDESItemType)item->type, item->data,item->len);
663 
664  if ( item->type == SDESItemTypeCNAME) {
665  cname_found = true;
666  // note that CNAME must be send in
667  // every RTCP compound, so we only
668  // trust sources that include it.
669  setState(*(srcLink->getSource()),
671  }
672  } else if ( item->type == SDESItemTypeEND) {
673  end = true;
674  pointer++;
675  pointer += (pointer & 0x03); // padding
676  } else if ( item->type == SDESItemTypePRIV ) {
677  std::ptrdiff_t prevpointer = pointer;
678  uint8 plength = *( &(item->len) + 1 );
679  pointer += sizeof(item->type) + sizeof(item->len) + 1;
680 
681  if ( part )
683  reinterpret_cast<char*>(item + pointer),plength);
684  pointer += plength;
685  setPRIVPrefix(part,
686  reinterpret_cast<char*>(item + pointer),
687  (item->len - 1 - plength));
688  pointer = prevpointer + item->len;
689  } else {
690  pointer++;
691  // TODO: error: SDES unknown
692  I( false );
693  }
694  }
695  return cname_found;
696 }
697 
699 {
700  float bwfract = controlBwFract * getSessionBandwidth();
701  uint32 participants = getMembersCount();
702  if ( getSendersCount() > 0 &&
704  // reserve "sendControlBwFract" fraction of the total
705  // RTCP bandwith for senders.
706  if (rtcpWeSent) {
707  // we take the side of active senders
708  bwfract *= sendControlBwFract;
709  participants = getSendersCount();
710  } else {
711  // we take the side of passive receivers
712  bwfract *= recvControlBwFract;
713  participants = getMembersCount() - getSendersCount();
714  }
715  }
716 
717  microtimeout_t min_interval = rtcpMinInterval;
718  // be a bit quicker at first
719  if ( rtcpInitial )
720  min_interval /= 2;
721  // this is the real computation:
722  microtimeout_t interval = 0;
723  if ( bwfract != 0 ) {
724  interval = static_cast<microtimeout_t>
725  ((participants * rtcpAvgSize / bwfract) * 1000000);
726 
727  if ( interval < rtcpMinInterval )
728  interval = rtcpMinInterval;
729  } else {
730  // 100 seconds instead of infinite
731  interval = 100000000;
732  }
733 
734  interval = static_cast<microtimeout_t>(interval * ( 0.5 +
735  (rand() / (RAND_MAX + 1.0))));
736 
737  timeval result;
738  result.tv_sec = interval / 1000000;
739  result.tv_usec = interval % 1000000;
740  return result;
741 }
742 
743 #define BYE_BUFFER_LENGTH 500
744 
745 size_t QueueRTCPManager::dispatchBYE(const std::string& reason)
746 {
747  // for this method, see section 6.3.7 in RFC 3550
748  // never send a BYE packet if never sent an RTP or RTCP packet
749  // before
751  return 0;
752 
753  if ( getMembersCount() > 50) {
754  // Usurp the scheduler role and apply a back-off
755  // algorithm to avoid BYE floods.
756  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
757  reconsInfo.rtcpTp = reconsInfo.rtcpTc;
758  setMembersCount(1);
760  rtcpInitial = true;
761  rtcpWeSent = false;
762  rtcpAvgSize = (uint16)(sizeof(RTCPFixedHeader) + sizeof(uint32) +
763  strlen(reason.c_str()) +
764  (4 - (strlen(reason.c_str()) & 0x03)));
765  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
766  timeval T = computeRTCPInterval();
767  timeradd(&(reconsInfo.rtcpTp),&T,&(reconsInfo.rtcpTn));
768  while ( timercmp(&(reconsInfo.rtcpTc),&(reconsInfo.rtcpTn),<) ) {
769  getOnlyBye();
770  if ( timerReconsideration() )
771  break;
772  SysTime::gettimeofday(&(reconsInfo.rtcpTc),NULL);
773  }
774  }
775 
776 
777  unsigned char buffer[BYE_BUFFER_LENGTH] = {0};
778  // Build an empty RR as first packet in the compound.
779  // TODO: provide more information if available. Not really
780  // important, since this is the last packet being sent.
781  RTCPPacket* pkt = reinterpret_cast<RTCPPacket*>(buffer);
782  pkt->fh.version = CCRTP_VERSION;
783  pkt->fh.padding = 0;
784  pkt->fh.block_count = 0;
785  pkt->fh.type = RTCPPacket::tRR;
787  uint16 len1 = sizeof(RTCPFixedHeader) + sizeof(uint32); // 1st pkt len.
788  pkt->fh.length = htons((len1 >> 2) - 1);
789  uint16 len = len1; // whole compound len.
790  // build a BYE packet
791  uint16 padlen = 0;
792  pkt = reinterpret_cast<RTCPPacket*>(buffer + len1);
793  pkt->fh.version = CCRTP_VERSION;
794  pkt->fh.block_count = 1;
795  pkt->fh.type = RTCPPacket::tBYE;
796  // add the SSRC identifier
797  pkt->info.BYE.ssrc = getLocalSSRCNetwork();
798  len += sizeof(RTCPFixedHeader) + sizeof(BYEPacket);
799  // add the optional reason
800  if ( reason.c_str() != NULL ){
801  pkt->info.BYE.length = (uint8)strlen(reason.c_str());
802  memcpy(buffer + len,reason.c_str(),pkt->info.BYE.length);
803  len += pkt->info.BYE.length;
804  padlen = 4 - ((len - len1) & 0x03);
805  if ( padlen ) {
806  memset(buffer + len,0,padlen);
807  len += padlen;
808  pkt->info.BYE.length += padlen;
809  }
810  }
811  pkt->fh.length = htons(((len - len1) >> 2) - 1);
812 
813  return sendControlToDestinations(buffer,len);
814 }
815 
817 {
818  // This method is kind of simplified recvControl
819  timeval wait;
820  timersub(&(reconsInfo.rtcpTn),&(reconsInfo.rtcpTc),&wait);
821  microtimeout_t timer = wait.tv_usec/1000 + wait.tv_sec * 1000;
822  // wait up to reconsInfo.rtcpTn
823  if ( !isPendingControl(timer) )
824  return;
825 
826  size_t len = 0;
827  InetHostAddress network_address;
828  tpport_t transport_port;
829  while ( (len = recvControl(rtcpRecvBuffer,getPathMTU(),
830  network_address,transport_port)) ) {
831  // Process a <code>len<code> octets long RTCP compound packet
832  // Check validity of the header fields of the compound packet
834  return;
835 
836  // TODO: For now, we do nothing with the padding bit
837  // in the header.
838  uint32 pointer = 0;
839  RTCPPacket* pkt;
840  while ( pointer < len) {
841  pkt = reinterpret_cast<RTCPPacket*>
842  (rtcpRecvBuffer + pointer);
843 
844  if (pkt->fh.type == RTCPPacket::tBYE ) {
845  bool created;
846  SyncSourceLink* srcLink =
847  getSourceBySSRC(pkt->getSSRC(),
848  created);
849  if( srcLink->getGoodbye() )
850  onGotGoodbye(*(srcLink->getSource()), "");
851  BYESource(pkt->getSSRC());
852  }
853  pointer += pkt->getLength();
854  }
855  }
856 }
857 
859 {
860  rtcpInitial = false;
861  // Keep in mind: always include a report (in SR or RR) and at
862  // least a SDES with the local CNAME. It is mandatory.
863 
864  // (A) SR or RR, depending on whether we sent.
865  // pkt will point to the packets of the compound
866 
867  RTCPPacket* pkt = reinterpret_cast<RTCPPacket*>(rtcpSendBuffer);
868  // Fixed header of the first report
869  pkt->fh.padding = 0;
870  pkt->fh.version = CCRTP_VERSION;
871  // length of the RTCP compound packet. It will increase till
872  // the end of this routine. Both sender and receiver report
873  // carry the general 32-bit long fixed header and a 32-bit
874  // long SSRC identifier.
875  uint16 len = sizeof(RTCPFixedHeader) + sizeof(uint32);
876 
877  // the fields block_count and length will be filled in later
878  // now decide whether to send a SR or a SR
880  // we have sent rtp packets since last RTCP -> send SR
882  pkt->fh.type = RTCPPacket::tSR;
883  pkt->info.SR.ssrc = getLocalSSRCNetwork();
884 
885  // Fill in sender info block. It would be more
886  // accurate if this were done as late as possible.
887  timeval now;
888  SysTime::gettimeofday(&now,NULL);
889  // NTP MSB and MSB: dependent on current payload type.
890  pkt->info.SR.sinfo.NTPMSW = htonl(now.tv_sec + NTP_EPOCH_OFFSET);
891  pkt->info.SR.sinfo.NTPLSW = htonl((uint32)(((double)(now.tv_usec)*(uint32)(~0))/1000000.0));
892  // RTP timestamp
893  int32 tstamp = now.tv_usec - getInitialTime().tv_usec;
894  tstamp *= (getCurrentRTPClockRate()/1000);
895  tstamp /= 1000;
896  tstamp += (now.tv_sec - getInitialTime().tv_sec) *
898  tstamp += getInitialTimestamp();
899  pkt->info.SR.sinfo.RTPTimestamp = htonl(tstamp);
900  // sender's packet and octet count
901  pkt->info.SR.sinfo.packetCount = htonl(getSendPacketCount());
902  pkt->info.SR.sinfo.octetCount = htonl(getSendOctetCount());
903  len += sizeof(SenderInfo);
904  } else {
905  // RR
906  pkt->fh.type = RTCPPacket::tRR;
907  pkt->info.RR.ssrc = getLocalSSRCNetwork();
908  }
909 
910  // (B) put report blocks
911  // After adding report blocks, we have to leave room for at
912  // least a CNAME SDES item
913  uint16 available = (uint16)(getPathMTU()
915  - len
916  - (sizeof(RTCPFixedHeader) +
917  2*sizeof(uint8) +
919  - 100);
920 
921  // if we have to go to a new RR packet
922  bool another = false;
923  uint16 prevlen = 0;
924  RRBlock* reports;
925  if ( RTCPPacket::tRR == pkt->fh.type )
926  reports = pkt->info.RR.blocks;
927  else // ( RTCPPacket::tSR == pkt->fh.type )
928  reports = pkt->info.SR.blocks;
929  do {
930  uint8 blocks = 0;
931  pkt->fh.block_count = blocks = packReportBlocks(reports,len,available);
932  // the length field specifies 32-bit words
933  pkt->fh.length = htons( ((len - prevlen) >> 2) - 1);
934  prevlen = len;
935  if ( 31 == blocks ) {
936  // we would need room for a new RR packet and
937  // a CNAME SDES
938  if ( len < (available -
939  ( sizeof(RTCPFixedHeader) + sizeof(uint32) +
940  sizeof(RRBlock))) ) {
941  another = true;
942  // Header for this new packet in the compound
943  pkt = reinterpret_cast<RTCPPacket*>
944  (rtcpSendBuffer + len);
945  pkt->fh.version = CCRTP_VERSION;
946  pkt->fh.padding = 0;
947  pkt->fh.type = RTCPPacket::tRR;
948  pkt->info.RR.ssrc = getLocalSSRCNetwork();
949  // appended a new Header and a report block
950 
951  len += sizeof(RTCPFixedHeader)+ sizeof(uint32);
952  reports = pkt->info.RR.blocks;
953  } else {
954  another = false;
955  }
956  } else {
957  another = false;
958  }
959  } while ( (len < available) && another );
960 
961  // (C) SDES (CNAME)
962  // each SDES chunk must be 32-bit multiple long
963  // fill the padding with 0s
964  packSDES(len);
965 
966  // TODO: virtual for sending APP RTCP packets?
967 
968  // actually send the packet.
969  size_t count = sendControlToDestinations(rtcpSendBuffer,len);
970  ctrlSendCount++;
971  // Everything went right, update the RTCP average size
972  updateAvgRTCPSize(len);
973 
974  return count;
975 }
976 
977 void QueueRTCPManager::packSDES(uint16 &len)
978 {
979  uint16 prevlen = len;
980  RTCPPacket* pkt = reinterpret_cast<RTCPPacket*>(rtcpSendBuffer + len);
981  // Fill RTCP fixed header. Note fh.length is not set till the
982  // end of this routine.
983  pkt->fh.version = CCRTP_VERSION;
984  pkt->fh.padding = 0;
985  pkt->fh.block_count = 1;
986  pkt->fh.type = RTCPPacket::tSDES;
989  // put CNAME
990  size_t cnameLen =
992  const char* cname =
994  pkt->info.SDES.item.len = (uint8)cnameLen;
995  len += sizeof(RTCPFixedHeader) + sizeof(pkt->info.SDES.ssrc) +
996  sizeof(pkt->info.SDES.item.type) +
997  sizeof(pkt->info.SDES.item.len);
998 
999  memcpy((rtcpSendBuffer + len),cname,cnameLen);
1000  len += (uint16)cnameLen;
1001  // pack items other than CNAME (following priorities
1002  // stablished inside scheduleSDESItem()).
1003  SDESItemType nexttype = scheduleSDESItem();
1004  if ( (nexttype > SDESItemTypeCNAME) &&
1005  (nexttype <= SDESItemTypeLast ) ) {
1006  SDESItem *item = reinterpret_cast<SDESItem *>(rtcpSendBuffer + len);
1007  item->type = nexttype;
1008  const char *content =
1009  getApplication().getSDESItem(nexttype).c_str();
1010  item->len = (uint8)strlen(content);
1011  len += 2;
1012  memcpy(reinterpret_cast<char *>(rtcpSendBuffer + len),
1013  content,item->len);
1014  len += item->len;
1015  }
1016 
1017  // pack END item (terminate list of items in this chunk)
1019  len++;
1020 
1021  uint8 padding = len & 0x03;
1022  if ( padding ) {
1023  padding = 4 - padding;
1024  memset((rtcpSendBuffer + len),SDESItemTypeEND,padding);
1025  len += padding;
1026  }
1027  pkt->fh.length = htons((len - prevlen - 1) >>2);
1028 }
1029 
1030 uint8 QueueRTCPManager::packReportBlocks(RRBlock* blocks, uint16 &len, uint16& available)
1031 {
1032  uint8 j = 0;
1033  // pack as many report blocks as we can
1034  SyncSourceLink* i = getFirst();
1035  for ( ;
1036  ( ( i != NULL ) &&
1037  ( len < (available - sizeof(RTCPCompoundHandler::RRBlock)) ) &&
1038  ( j < 31 ) );
1039  i = i->getNext() ) {
1040  SyncSourceLink& srcLink = *i;
1041  // update stats.
1042  srcLink.computeStats();
1043  blocks[j].ssrc = htonl(srcLink.getSource()->getID());
1044  blocks[j].rinfo.fractionLost = srcLink.getFractionLost();
1045  blocks[j].rinfo.lostMSB =
1046  (srcLink.getCumulativePacketLost() & 0xFF0000) >> 16;
1047  blocks[j].rinfo.lostLSW =
1048  htons(srcLink.getCumulativePacketLost() & 0xFFFF);
1049  blocks[j].rinfo.highestSeqNum =
1050  htonl(srcLink.getExtendedMaxSeqNum());
1051  blocks[j].rinfo.jitter =
1052  htonl(static_cast<uint32>(srcLink.getJitter()));
1054  reinterpret_cast<RTCPCompoundHandler::SenderInfo*>(srcLink.getSenderInfo());
1055  if ( NULL == si ) {
1056  blocks[j].rinfo.lsr = 0;
1057  blocks[j].rinfo.dlsr = 0;
1058  } else {
1059  blocks[j].rinfo.lsr =
1060  htonl( ((ntohl(si->NTPMSW) & 0x0FFFF) << 16 )+
1061  ((ntohl(si->NTPLSW) & 0xFFFF0000) >> 16)
1062  );
1063  timeval now, diff;
1064  SysTime::gettimeofday(&now,NULL);
1065  timeval last = srcLink.getLastRTCPSRTime();
1066  timersub(&now,&last,&diff);
1067  blocks[j].rinfo.dlsr =
1068  htonl(timevalIntervalTo65536(diff));
1069  }
1070  len += sizeof(RTCPCompoundHandler::RRBlock);
1071  j++;
1072  }
1073  return j;
1074 }
1075 
1077 const char* const value, size_t len)
1078 {
1079  char* buf = new char[len + 1];
1080  memcpy(buf,value,len);
1081  buf[len] = '\0';
1082  ParticipantHandler::setSDESItem(part,type,buf);
1083  delete [] buf;
1084 }
1085 
1086 void QueueRTCPManager::setPRIVPrefix(Participant* part, const char* const value, size_t len)
1087 {
1088  char *buf = new char[len + 1];
1089  memcpy(buf,value,len);
1090  buf[len] = '\0';
1092  delete [] buf;
1093 }
1094 
1096 {
1097  uint8 i = 0;
1098  // TODO: follow, at least, standard priorities
1100 
1101  while ( (queueApplication.getSDESItem(type).length() <= 0) &&
1102  i < (lastSchedulable - firstSchedulable) ) {
1103  i++;
1104  type = nextSDESType(type);
1105  }
1106  bool empty = true;
1107  if ( queueApplication.getSDESItem(type).length() > 0 )
1108  empty = false;
1110  if ( empty )
1111  return SDESItemTypeEND;
1112  else
1113  return type;
1114 }
1115 
1117 {
1118  t = static_cast<SDESItemType>( static_cast<int>(t) + 1 );
1119  if ( t > lastSchedulable )
1120  t = firstSchedulable;
1121  return t;
1122 }
1123 
1124 size_t QueueRTCPManager::sendControlToDestinations(unsigned char* buffer, size_t len)
1125 {
1126  size_t count = 0;
1128 
1129  // Cast to have easy access to ssrc et al
1130  RTCPPacket *pkt = reinterpret_cast<RTCPPacket *>(buffer);
1131 
1133  if (pcc == NULL) {
1135  if (pcc != NULL) {
1136  pcc = pcc->newCryptoContextForSSRC(pkt->getSSRC());
1137  if (pcc != NULL) {
1138  pcc->deriveSrtcpKeys();
1140  }
1141  }
1142  }
1143  // If no crypto context: then SRTP/SRTCP is off
1144  // If crypto context is available then unprotect data here. If an error
1145  // occurs report the error and discard the packet.
1146  if (pcc != NULL) {
1147  len = protect(buffer, len, pcc);
1148  }
1149 
1150  if ( isSingleDestination() ) {
1151  count = sendControl(buffer,len);
1152  } else {
1153  // when no destination has been added, NULL == dest.
1154  for (std::list<TransportAddress*>::iterator i =
1155  destList.begin(); destList.end() != i; i++) {
1156  TransportAddress* dest = *i;
1158  dest->getControlTransportPort());
1159  count += sendControl(buffer,len);
1160  }
1161  }
1163 
1164  return count;
1165 }
1166 
1167 int32
1168 QueueRTCPManager::protect(uint8* pkt, size_t len, CryptoContextCtrl* pcc) {
1169  /* Encrypt the packet */
1170 
1171  uint32 ssrc = *(reinterpret_cast<uint32*>(pkt + 4)); // always SSRC of sender
1172  ssrc =ntohl(ssrc);
1173 
1174  pcc->srtcpEncrypt(pkt + 8, len - 8, srtcpIndex, ssrc);
1175 
1176  uint32 encIndex = srtcpIndex | 0x80000000; // set the E flag
1177 
1178  uint32* ip = reinterpret_cast<uint32*>(pkt+len);
1179  *ip = htonl(encIndex);
1180 
1181  // NO MKI support yet - here we assume MKI is zero. To build in MKI
1182  // take MKI length into account when storing the authentication tag.
1183 
1184  // Compute MAC and store in packet after the SRTCP index field
1185  pcc->srtcpAuthenticate(pkt, len, encIndex, pkt + len + sizeof(uint32));
1186 
1187  srtcpIndex++;
1188  srtcpIndex &= ~0x80000000; // clear possible overflow
1189 
1190  return len + pcc->getTagLength() + sizeof(uint32);
1191 }
1192 
1193 int32
1194 QueueRTCPManager::unprotect(uint8* pkt, size_t len, CryptoContextCtrl* pcc) {
1195  if (pcc == NULL) {
1196  return true;
1197  }
1198 
1199  // Compute the total length of the payload
1200  uint32 payloadLen = len - (pcc->getTagLength() + pcc->getMkiLength() + 4);
1201 
1202  // point to the SRTCP index field just after the real payload
1203  const uint32* index = reinterpret_cast<uint32*>(pkt + payloadLen);
1204  uint32 ssrc = *(reinterpret_cast<uint32*>(pkt + 4)); // always SSRC of sender
1205  ssrc =ntohl(ssrc);
1206 
1207  uint32 encIndex = ntohl(*index);
1208  uint32 remoteIndex = encIndex & ~0x80000000; // index without Encryption flag
1209 
1210  if (!pcc->checkReplay(remoteIndex)) {
1211  return -2;
1212  }
1213 
1214  uint8 mac[20];
1215 
1216  // Now get a pointer to the authentication tag field
1217  const uint8* tag = pkt + (len - pcc->getTagLength());
1218 
1219  // Authenticate includes the index, but not MKI and not (obviously) the tag itself
1220  pcc->srtcpAuthenticate(pkt, payloadLen, encIndex, mac);
1221  if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
1222  return -1;
1223  }
1224 
1225  // Decrypt the content, exclude the very first SRTCP header (fixed, 8 bytes)
1226  if (encIndex & 0x80000000)
1227  pcc->srtcpEncrypt(pkt + 8, payloadLen - 8, remoteIndex, ssrc);
1228 
1229  // Update the Crypto-context
1230  pcc->update(remoteIndex);
1231 
1232  return payloadLen;
1233 }
1234 
1235 
1236 void
1238 {
1239  std::list<CryptoContextCtrl *>::iterator i;
1240 
1241  MutexLock lock(outCryptoMutex);
1242  // check if a CryptoContext for a SSRC already exists. If yes
1243  // remove it from list before inserting the new one.
1244  for( i = outCryptoContexts.begin(); i!= outCryptoContexts.end(); i++ ) {
1245  if( (*i)->getSsrc() == cc->getSsrc() ) {
1246  CryptoContextCtrl* tmp = *i;
1247  outCryptoContexts.erase(i);
1248  delete tmp;
1249  break;
1250  }
1251  }
1252  outCryptoContexts.push_back(cc);
1253 }
1254 
1255 void
1257 {
1258  std::list<CryptoContextCtrl *>::iterator i;
1259 
1260  MutexLock lock(outCryptoMutex);
1261  if (cc == NULL) { // Remove any incoming crypto contexts
1262  for (i = outCryptoContexts.begin(); i != outCryptoContexts.end(); ) {
1263  CryptoContextCtrl* tmp = *i;
1264  i = outCryptoContexts.erase(i);
1265  delete tmp;
1266  }
1267  }
1268  else {
1269  for( i = outCryptoContexts.begin(); i != outCryptoContexts.end(); i++ ) {
1270  if( (*i)->getSsrc() == cc->getSsrc() ) {
1271  CryptoContextCtrl* tmp = *i;
1272  outCryptoContexts.erase(i);
1273  delete tmp;
1274  return;
1275  }
1276  }
1277  }
1278 }
1279 
1282 {
1283  std::list<CryptoContextCtrl *>::iterator i;
1284 
1285  MutexLock lock(outCryptoMutex);
1286  for( i = outCryptoContexts.begin(); i != outCryptoContexts.end(); i++ ){
1287  if( (*i)->getSsrc() == ssrc) {
1288  return (*i);
1289  }
1290  }
1291  return NULL;
1292 }
1293 
1294 void
1296 {
1297  std::list<CryptoContextCtrl *>::iterator i;
1298 
1299  MutexLock lock(inCryptoMutex);
1300  // check if a CryptoContext for a SSRC already exists. If yes
1301  // remove it from list before inserting the new one.
1302  for( i = inCryptoContexts.begin(); i!= inCryptoContexts.end(); i++ ) {
1303  if( (*i)->getSsrc() == cc->getSsrc() ) {
1304  CryptoContextCtrl* tmp = *i;
1305  inCryptoContexts.erase(i);
1306  delete tmp;
1307  break;
1308  }
1309  }
1310  inCryptoContexts.push_back(cc);
1311 }
1312 
1313 void
1315 {
1316  std::list<CryptoContextCtrl *>::iterator i;
1317 
1318  MutexLock lock(inCryptoMutex);
1319  if (cc == NULL) { // Remove any incoming crypto contexts
1320  for (i = inCryptoContexts.begin(); i != inCryptoContexts.end(); ) {
1321  CryptoContextCtrl* tmp = *i;
1322  i = inCryptoContexts.erase(i);
1323  delete tmp;
1324  }
1325  }
1326  else {
1327  for( i = inCryptoContexts.begin(); i!= inCryptoContexts.end(); i++ ){
1328  if( (*i)->getSsrc() == cc->getSsrc() ) {
1329  CryptoContextCtrl* tmp = *i;
1330  inCryptoContexts.erase(i);
1331  delete tmp;
1332  return;
1333  }
1334  }
1335  }
1336 }
1337 
1340 {
1341  std::list<CryptoContextCtrl *>::iterator i;
1342 
1343  MutexLock lock(inCryptoMutex);
1344  for( i = inCryptoContexts.begin(); i!= inCryptoContexts.end(); i++ ){
1345  if( (*i)->getSsrc() == ssrc) {
1346  return (*i);
1347  }
1348  }
1349  return NULL;
1350 }
1351 
1352 END_NAMESPACE
1353 
uint32 getSendPacketCount() const
Get the total number of packets sent so far.
Definition: oqueue.h:391
Struct for a receiver info block in a SR (sender report) or an RR (receiver report) RTCP packet...
Definition: rtcppkt.h:125
uint32 lsr
last sender report timestamp.
Definition: rtcppkt.h:115
uint32 getNTPTimestampFrac() const
Get fractional part of the NTP timestamp of this packet.
Definition: rtcppkt.h:481
unsigned char block_count
< For little endian boxes
Definition: rtcppkt.h:259
uint32 getSendOctetCount() const
Get the total number of octets (payload only) sent so far.
Definition: oqueue.h:400
void deriveSrtcpKeys()
Perform key derivation according to SRTP specification.
void addParticipant(RTPApplication &app, Participant &part)
Definition: iqueue.h:209
uint32 getNTPTimestampInt() const
Get integer part of the NTP timestamp of this packet.
Definition: rtcppkt.h:473
microtimeout_t getDefaultEnd2EndDelay() const
Definition: cqueue.h:136
int32 protect(uint8 *pkt, size_t len, CryptoContextCtrl *cc)
Definition: control.cpp:1168
The implementation for a SRTCP cryptographic context.
int32 getTagLength() const
Get the length of the SRTP authentication tag in bytes.
SDESItemType nextSDESType(SDESItemType t)
Definition: control.cpp:1116
microtimeout_t getEnd2EndDelay() const
Definition: cqueue.h:140
tpport_t getDataTransportPort() const
Definition: sources.h:271
virtual bool isPendingControl(microtimeout_t timeout)=0
unsigned char * rtcpSendBuffer
Definition: rtcppkt.h:352
low level structs and RTCP packet parsing and building methods.
Definition: rtcppkt.h:89
std::list< CryptoContextCtrl * > outCryptoContexts
Definition: cqueue.h:693
Last defined code.
Definition: rtcppkt.h:76
An RTP application, holding identifying RTCP SDES item values.
Definition: sources.h:364
End of participation.
Definition: rtcppkt.h:288
NAMESPACE_COMMONCPP const uint32 NTP_EPOCH_OFFSET
Definition: private.h:142
ReceiverInfo rinfo
info about the source.
Definition: rtcppkt.h:128
Synchronization source in an RTP session.
Definition: sources.h:192
void renewLocalSSRC()
Definition: ioqueue.h:281
static const SDESItemType firstSchedulable
Definition: cqueue.h:650
bool getBYE(RTCPPacket &pkt, size_t &pointer, size_t len)
Process a BYE packet just received and identified.
Definition: control.cpp:529
uint32 highestSeqNum
highest sequence number.
Definition: rtcppkt.h:113
void setPRIVPrefix(Participant *part, const std::string val)
Definition: iqueue.h:188
volatile bool controlServiceActive
Definition: cqueue.h:640
uint32 ssrc
ssrc identifier of source leaving.
Definition: rtcppkt.h:203
const uint8 CCRTP_VERSION
RTP protocol version supported.
Definition: base.h:64
uint32 jitter
arrival jitter.
Definition: rtcppkt.h:114
uint32 getMembersCount()
Definition: iqueue.h:843
virtual size_t sendControl(const unsigned char *const buffer, size_t len)=0
virtual bool onGotSDESChunk(SyncSource &source, SDESChunk &chunk, size_t len)
Plug-in for handling of SDES chunks.
Definition: control.cpp:629
void updateAvgRTCPSize(size_t len)
This must be called in order to update the average RTCP compound packet size estimation when: ...
Definition: control.cpp:522
uint32 octetCount
cumulative octet counter.
Definition: rtcppkt.h:155
bool checkCompoundRTCPHeader(size_t len)
Perform RTCP compound packet header validity check as specified in draft-ietv-avt-rtp-new.
Definition: rtcppkt.cpp:107
uint32 microtimeout_t
Time interval expressed in microseconds.
Definition: base.h:67
uint32 getSendersCount()
Definition: iqueue.h:851
virtual ~QueueRTCPManager()
Definition: control.cpp:162
Sender block information of SR RTCP reports.
Definition: rtcppkt.h:453
APPlication specific.
Definition: rtcppkt.h:289
Canonical end-point identifier.
Definition: rtcppkt.h:67
int32 unprotect(uint8 *pkt, size_t len, CryptoContextCtrl *cc)
Definition: control.cpp:1194
uint32 getSessionBandwidth() const
Definition: ioqueue.h:219
void srtcpEncrypt(uint8 *rtp, size_t len, uint64 index, uint32 ssrc)
Perform SRTP encryption.
virtual SDESItemType scheduleSDESItem()
Choose which should be the type of the next SDES item sent.
Definition: control.cpp:1095
void setState(SyncSource &source, SyncSource::State ns)
Definition: iqueue.h:146
bool checkSSRCInRTCPPkt(SyncSourceLink &sourceLink, bool is_new, InetAddress &na, tpport_t tp)
Appy collision and loop detection and correction algorithm when receiving RTCP packets.
Definition: control.cpp:176
microtimeout_t end2EndDelay
Definition: cqueue.h:684
unsigned char padding
Padding bit.
Definition: rtcppkt.h:260
uint16 lowerHeadersSize
Definition: cqueue.h:647
bool timerReconsideration()
Definition: control.cpp:294
void endQueueRTCPManager()
Definition: control.cpp:167
void reverseReconsideration()
Apply reverse reconsideration adjustment to timing parameters when receiving BYE packets and not wait...
Definition: control.cpp:568
uint32 getLength() const
Get the packet length specified in its header, in octets and in host order.
Definition: rtcppkt.h:299
microtimeout_t timeval2microtimeout(const timeval &t)
Convert a time interval, expressed as a timeval value into a microseconds counter.
Definition: base.h:90
std::list< TransportAddress * > destList
Definition: oqueue.h:68
timeval rtcpCheckInterval
Definition: cqueue.h:667
CryptoContextCtrl * getInQueueCryptoContextCtrl(uint32 ssrc)
Get an input queue CryptoContext identified by SSRC.
Definition: control.cpp:1339
virtual void onNewSyncSource(const SyncSource &)
Virtual called when a new synchronization source has joined the session.
Definition: iqueue.h:1185
uint32 ctrlSendCount
Definition: cqueue.h:643
timeval rtcpNextCheck
Definition: cqueue.h:669
uint8 getMinValidPacketSequence() const
Get the minimun number of consecutive packets that must be received from a source before accepting it...
Definition: iqueue.h:1010
static const microtimeout_t defaultEnd2EndDelay
maximum end to end delay: unlimited
Definition: cqueue.h:681
uint32 dlsr
delay since last sender report.
Definition: rtcppkt.h:116
Fixed RTCP packet header.
Definition: rtcppkt.h:250
virtual void onGotSR(SyncSource &source, SendReport &SR, uint8 blocks)
Plug-in for processing (acquire information carried in) an incoming RTCP Sender Report.
Definition: control.cpp:502
void removeInQueueCryptoContextCtrl(CryptoContextCtrl *cc)
Remove input queue CryptoContext.
Definition: control.cpp:1314
timeval getInitialTime() const
Definition: queuebase.h:201
void lockDestinationList() const
Definition: oqueue.h:85
Declaration of ccRTP internal stuff.
virtual void onGotAPP(SyncSource &, RTCPCompoundHandler::APPPacket &, size_t)
Plug-in for handling of APP (application specific) RTCP packets.
Definition: cqueue.h:357
virtual void onGotRR(SyncSource &source, RecvReport &RR, uint8 blocks)
Plug-in for processing (acquire information carried in) an incoming RTCP Receiver Report...
Definition: control.cpp:509
uint8 packReportBlocks(RRBlock *blocks, uint16 &len, uint16 &available)
Definition: control.cpp:1030
uint16 lostLSW
cumulative lost two LSB.
Definition: rtcppkt.h:112
void setInQueueCryptoContextCtrl(CryptoContextCtrl *cc)
Set input queue CryptoContext.
Definition: control.cpp:1295
bool rtcpWeSent
Definition: cqueue.h:661
virtual void onGotGoodbye(const SyncSource &, const std::string &)
A plugin point for goodbye message.
Definition: cqueue.h:499
size_t sendControlToDestinations(unsigned char *buffer, size_t len)
Definition: control.cpp:1124
void getOnlyBye()
To be executed when whe are leaving the session.
Definition: control.cpp:816
uint32 getSendRTCPPacketCount() const
Get the total number of RTCP packets sent until now.
Definition: cqueue.h:177
static const double RECONSIDERATION_COMPENSATION
Definition: cqueue.h:690
void setSDESItem(Participant *part, SDESItemType type, const char *const value, size_t len)
Set item value from a string without null termination (as it is transported in RTCP packets)...
Definition: control.cpp:1076
Struct for BYE (leaving session) RTCP packets.
Definition: rtcppkt.h:201
uint8 lostMSB
cumulative lost MSB of 3 octets.
Definition: rtcppkt.h:111
uint8 len
item len in octets.
Definition: rtcppkt.h:178
uint8 type
type of RTCP packet.
Definition: rtcppkt.h:263
uint32 getInitialTimestamp()
Definition: oqueue.h:534
uint32 ssrc
SSRC identifer from sender.
Definition: rtcppkt.h:192
uint32 NTPMSW
NTP timestamp higher octets.
Definition: rtcppkt.h:151
A class of objects representing remote participants (RTP applications) in a multimedia session...
Definition: sources.h:124
uint32 getTimestamp() const
Definition: rtppkt.h:149
Mutex outCryptoMutex
Definition: cqueue.h:692
Struct for the sender info block in a SR (sender report) RTCP packet.
Definition: rtcppkt.h:149
Struct for SR (sender report) RTCP packets.
Definition: rtcppkt.h:163
float controlBwFract
Definition: cqueue.h:641
CryptoContextCtrl * getOutQueueCryptoContextCtrl(uint32 ssrc)
Get an output queue CryptoContext identified by SSRC.
Definition: control.cpp:1281
uint8 length
[optional] length of reason.
Definition: rtcppkt.h:204
uint32 getSSRC() const
Definition: rtcppkt.h:189
QueueRTCPManager(uint32 size=RTPDataQueue::defaultMembersHashSize, RTPApplication &app=defaultApplication())
Definition: control.cpp:61
void setNetworkAddress(SyncSource &source, InetAddress addr)
Definition: iqueue.h:162
SyncSourceLink * last
Definition: iqueue.h:874
virtual uint16 transportHeaderSize()
For certain control calculations in RTCP, the size of the underlying network and transport protocols ...
Definition: cqueue.h:618
microtimeout_t rtcpMinInterval
Definition: cqueue.h:678
RRBlock blocks[1]
receiver report blocks.
Definition: rtcppkt.h:140
uint8 type
item identifier.
Definition: rtcppkt.h:177
SenderInfo sinfo
actual sender info.
Definition: rtcppkt.h:166
void expireSSRCs()
Purge sources that do not seem active any more.
Definition: control.cpp:310
void setSDESItem(Participant *part, SDESItemType item, const std::string &val)
Definition: iqueue.h:183
SDESItem item
SDES item from sender.
Definition: rtcppkt.h:193
Struct for a chunk of items in a SDES RTCP packet.
Definition: rtcppkt.h:187
void removeOutQueueCryptoContextCtrl(CryptoContextCtrl *cc)
Remove output queue CryptoContext.
Definition: control.cpp:1256
Participant * getParticipant() const
Get the participant this synchronization source is asociated to.
Definition: sources.h:268
void setParticipant(SyncSource &source, Participant &p)
Definition: iqueue.h:142
END of SDES item list.
Definition: rtcppkt.h:66
RRBlock blocks[1]
possibly several receiver info blocks.
Definition: rtcppkt.h:167
Struct representing general RTCP packet headers as they are sent through the network.
Definition: rtcppkt.h:277
bool BYESource(uint32 ssrc)
Mark the source identified by ssrc as having sent a BYE packet.
Definition: members.cpp:282
Generic RTCP control queues.
Private extension.
Definition: rtcppkt.h:74
void controlReceptionService()
Process incoming RTCP packets pending in the control reception socket.
Definition: control.cpp:242
SDESItemType nextScheduledSDESItem
Definition: cqueue.h:649
virtual void setControlPeer(const InetAddress &host, tpport_t port)
Definition: oqueue.h:540
uint32 timevalIntervalTo65536(timeval &t)
Convert a time interval, expressed as a timeval, into a 32-bit time interval expressed in units of 1/...
Definition: rtcppkt.cpp:67
#define BYE_BUFFER_LENGTH
Definition: control.cpp:743
const RTPApplication & getApplication()
Definition: cqueue.h:259
uint32 srtcpIndex
Definition: cqueue.h:694
uint32 getSsrc() const
Get the SSRC of this SRTP Cryptograhic context.
const InetAddress & getNetworkAddress() const
Definition: sources.h:277
uint16 rtcpAvgSize
Definition: cqueue.h:662
void takeInControlPacket()
For picking up incoming RTCP packets if they are waiting.
Definition: control.cpp:314
bool rtcpInitial
Definition: cqueue.h:663
tpport_t getControlTransportPort() const
Definition: sources.h:274
received, but source validity not yet guaranteed.
Definition: sources.h:230
#define I(e)
Definition: private.h:108
struct QueueRTCPManager::@0 reconsInfo
bool checkReplay(uint32 newSeqNumber)
Check for packet replay.
void srtcpAuthenticate(uint8 *rtp, size_t len, uint32 roc, uint8 *tag)
Compute the authentication tag.
char data[1]
item content.
Definition: rtcppkt.h:179
Personal NAME of the user.
Definition: rtcppkt.h:68
SyncSourceLink * getSourceBySSRC(uint32 ssrc, bool &created)
Get the description of a source by its ssrc identifier.
Definition: members.cpp:226
timeval rtcpLastCheck
Definition: cqueue.h:665
uint32 getLocalSSRCNetwork() const
Definition: queuebase.h:214
static const SDESItemType lastSchedulable
Definition: cqueue.h:651
uint16 getPathMTU()
Definition: rtcppkt.h:95
uint32 RTPTimestamp
RTP timestamp.
Definition: rtcppkt.h:153
virtual uint16 networkHeaderSize()
For certain control calculations in RTCP, the size of the underlying network and transport protocols ...
Definition: cqueue.h:603
tpport_t getControlTransportPort() const
Definition: oqueue.h:122
raw structure of the source and every receiver report in an SR or RR RTCP packet. ...
Definition: rtcppkt.h:137
const InetAddress & getNetworkAddress() const
Definition: oqueue.h:116
unsigned char * rtcpRecvBuffer
Definition: rtcppkt.h:355
int32 getMkiLength() const
Get the length of the MKI in bytes.
size_t dispatchControlPacket()
Posting of RTCP messages.
Definition: control.cpp:858
uint32 ssrc
source identifier.
Definition: rtcppkt.h:139
uint32 getSSRC() const
Get the SSRC identifier specified in the packet header, in host order.
Definition: rtcppkt.h:306
static const uint16 TIMEOUT_MULTIPLIER
Definition: cqueue.h:689
void setMembersCount(uint32 n)
Definition: iqueue.h:847
uint32 getLocalSSRC() const
Definition: queuebase.h:184
void setPRIVPrefix(Participant *part, const char *const value, size_t len)
Set PRIV item previx value from a string without null termination (as it is transported in RTCP packe...
Definition: control.cpp:1086
uint16 length
number of 32-bit words in the packet (minus one).
Definition: rtcppkt.h:264
Struct for an item description of a SDES packet.
Definition: rtcppkt.h:175
CryptoContextCtrl * newCryptoContextForSSRC(uint32 ssrc)
Derive a new Crypto Context for use with a new SSRC.
uint32 getRTPTimestamp() const
Definition: rtcppkt.h:485
Mutex inCryptoMutex
Definition: cqueue.h:696
virtual bool end2EndDelayed(IncomingRTPPktLink &p)
Virtual reimplemented from RTPDataQueue.
Definition: control.cpp:471
uint8 fractionLost
packet fraction lost.
Definition: rtcppkt.h:110
float sendControlBwFract
Definition: cqueue.h:641
timeval NTP2Timeval(uint32 msw, uint32 lsw)
Convert a NTP timestamp, expressed as two 32-bit long words, into a timeval value.
Definition: rtcppkt.cpp:58
microtimeout_t leavingDelay
Definition: cqueue.h:680
SyncSourceLink * getFirst()
Definition: iqueue.h:836
std::list< CryptoContextCtrl * > inCryptoContexts
Definition: cqueue.h:697
void controlTransmissionService()
Build and send RTCP packets following timing rules (including the "timer reconsideration" algorithm)...
Definition: control.cpp:264
uint32 getCurrentRTPClockRate() const
Get the clock rate in RTP clock units (for instance, 8000 units per second for PCMU, or 90000 units per second for MP2T).
Definition: queuebase.h:195
bool onGotSDES(SyncSource &source, RTCPPacket &pkt)
Definition: control.cpp:597
virtual void onGotRRSRExtension(unsigned char *, size_t)
Plug-in for processing of SR/RR RTCP packet profile-specific extensions (third part of SR reports or ...
Definition: cqueue.h:486
uint32 ssrc
source identifier.
Definition: rtcppkt.h:127
uint32 getID() const
Definition: sources.h:257
void addConflict(const InetAddress &na, tpport_t dtp, tpport_t ctp)
Definition: incqueue.cpp:75
void packSDES(uint16 &len)
Builds an SDES RTCP packet.
Definition: control.cpp:977
const std::string & getSDESItem(SDESItemType item) const
Definition: sources.h:390
SyncSourceLink * getLink(const SyncSource &source) const
Definition: iqueue.h:336
union RTCPCompoundHandler::RTCPPacket::@6 info
Union for SR, RR, SDES, BYE and APP.
unsigned char version
Version, currently 2.
Definition: rtcppkt.h:261
RTCPFixedHeader fh
Fixed RTCP header.
Definition: rtcppkt.h:310
bool isSingleDestination() const
Get whether there is only a destination in the list.
Definition: oqueue.h:79
SyncSourcesIterator end()
Definition: iqueue.h:941
uint32 packetCount
cumulative packet counter.
Definition: rtcppkt.h:154
const Participant * getParticipant(const std::string &cname) const
Definition: source.cpp:173
void updateConflict(ConflictingTransportAddress &ca)
Definition: iqueue.h:273
void setOutQueueCryptoContextCtrl(CryptoContextCtrl *cc)
Set ouput queue CryptoContext.
Definition: control.cpp:1237
void setPrevMembersNum(uint32 n)
Definition: cqueue.h:377
virtual size_t recvControl(unsigned char *buffer, size_t len, InetHostAddress &na, tpport_t &tp)=0
uint32 NTPLSW
NTP timestamp lower octets.
Definition: rtcppkt.h:152
virtual timeval computeRTCPInterval()
Computes the interval for sending RTCP compound packets, based on the average size of RTCP packets se...
Definition: control.cpp:698
uint32 lastSendPacketCount
Definition: cqueue.h:673
__EXPORT timeval microtimeout2Timeval(microtimeout_t to)
Convert a time interval, expressed as a microtimeout_t (number of microseconds), into a timeval value...
Definition: rtcppkt.cpp:76
void update(uint32 newSeqNumber)
Update the SRTP packet index.
no packet from this source has been received lately.
Definition: sources.h:235
A packet queue handler for building different kinds of RTP protocol systems.
Definition: ioqueue.h:74
ConflictingTransportAddress * searchControlConflict(InetAddress na, tpport_t ctp)
Definition: incqueue.cpp:64
SDESItemType
SDES items that may be carried in a Source DEScription RTCP packet.
Definition: rtcppkt.h:64
RTPApplication & queueApplication
Definition: cqueue.h:686
size_t dispatchBYE(const std::string &reason)
This method is used to send an RTCP BYE packet.
Definition: control.cpp:745
void unlockDestinationList() const
Definition: oqueue.h:88
uint32 ssrc
source identifier.
Definition: rtcppkt.h:165
void setControlTransportPort(SyncSource &source, tpport_t p)
Definition: iqueue.h:158
float recvControlBwFract
Definition: cqueue.h:641