1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// RTCP
19// Implementation
20
21#include "RTCP.hh"
22#include "GroupsockHelper.hh"
23#include "rtcp_from_spec.h"
24#if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)
25#define snprintf _snprintf
26#endif
27
28////////// RTCPMemberDatabase //////////
29
30class RTCPMemberDatabase {
31public:
32 RTCPMemberDatabase(RTCPInstance& ourRTCPInstance)
33 : fOurRTCPInstance(ourRTCPInstance), fNumMembers(1 /*ourself*/),
34 fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
35 }
36
37 virtual ~RTCPMemberDatabase() {
38 delete fTable;
39 }
40
41 Boolean isMember(u_int32_t ssrc) const {
42 return fTable->Lookup((char*)(long)ssrc) != NULL;
43 }
44
45 Boolean noteMembership(u_int32_t ssrc, unsigned curTimeCount) {
46 Boolean isNew = !isMember(ssrc);
47
48 if (isNew) {
49 ++fNumMembers;
50 }
51
52 // Record the current time, so we can age stale members
53 fTable->Add((char*)(long)ssrc, (void*)(long)curTimeCount);
54
55 return isNew;
56 }
57
58 Boolean remove(u_int32_t ssrc) {
59 Boolean wasPresent = fTable->Remove((char*)(long)ssrc);
60 if (wasPresent) {
61 --fNumMembers;
62 }
63 return wasPresent;
64 }
65
66 unsigned numMembers() const {
67 return fNumMembers;
68 }
69
70 void reapOldMembers(unsigned threshold);
71
72private:
73 RTCPInstance& fOurRTCPInstance;
74 unsigned fNumMembers;
75 HashTable* fTable;
76};
77
78void RTCPMemberDatabase::reapOldMembers(unsigned threshold) {
79 Boolean foundOldMember;
80 u_int32_t oldSSRC = 0;
81
82 do {
83 foundOldMember = False;
84
85 HashTable::Iterator* iter
86 = HashTable::Iterator::create(*fTable);
87 uintptr_t timeCount;
88 char const* key;
89 while ((timeCount = (uintptr_t)(iter->next(key))) != 0) {
90#ifdef DEBUG
91 fprintf(stderr, "reap: checking SSRC 0x%lx: %ld (threshold %d)\n", (unsigned long)key, timeCount, threshold);
92#endif
93 if (timeCount < (uintptr_t)threshold) { // this SSRC is old
94 uintptr_t ssrc = (uintptr_t)key;
95 oldSSRC = (u_int32_t)ssrc;
96 foundOldMember = True;
97 }
98 }
99 delete iter;
100
101 if (foundOldMember) {
102#ifdef DEBUG
103 fprintf(stderr, "reap: removing SSRC 0x%x\n", oldSSRC);
104#endif
105 fOurRTCPInstance.removeSSRC(oldSSRC, True);
106 }
107 } while (foundOldMember);
108}
109
110
111////////// RTCPInstance //////////
112
113static double dTimeNow() {
114 struct timeval timeNow;
115 gettimeofday(&timeNow, NULL);
116 return (double) (timeNow.tv_sec + timeNow.tv_usec/1000000.0);
117}
118
119static unsigned const maxRTCPPacketSize = 1456;
120 // bytes (1500, minus some allowance for IP, UDP, UMTP headers)
121static unsigned const preferredRTCPPacketSize = 1000; // bytes
122
123RTCPInstance::RTCPInstance(UsageEnvironment& env, Groupsock* RTCPgs,
124 unsigned totSessionBW,
125 unsigned char const* cname,
126 RTPSink* sink, RTPSource* source,
127 Boolean isSSMSource)
128 : Medium(env), fRTCPInterface(this, RTCPgs), fTotSessionBW(totSessionBW),
129 fSink(sink), fSource(source), fIsSSMSource(isSSMSource),
130 fCNAME(RTCP_SDES_CNAME, cname), fOutgoingReportCount(1),
131 fAveRTCPSize(0), fIsInitial(1), fPrevNumMembers(0),
132 fLastSentSize(0), fLastReceivedSize(0), fLastReceivedSSRC(0),
133 fTypeOfEvent(EVENT_UNKNOWN), fTypeOfPacket(PACKET_UNKNOWN_TYPE),
134 fHaveJustSentPacket(False), fLastPacketSentSize(0),
135 fByeHandlerTask(NULL), fByeWithReasonHandlerTask(NULL), fByeHandlerClientData(NULL),
136 fSRHandlerTask(NULL), fSRHandlerClientData(NULL),
137 fRRHandlerTask(NULL), fRRHandlerClientData(NULL),
138 fSpecificRRHandlerTable(NULL),
139 fAppHandlerTask(NULL), fAppHandlerClientData(NULL) {
140#ifdef DEBUG
141 fprintf(stderr, "RTCPInstance[%p]::RTCPInstance()\n", this);
142#endif
143 if (fTotSessionBW == 0) { // not allowed!
144 env << "RTCPInstance::RTCPInstance error: totSessionBW parameter should not be zero!\n";
145 fTotSessionBW = 1;
146 }
147
148 if (isSSMSource) RTCPgs->multicastSendOnly(); // don't receive multicast
149
150 double timeNow = dTimeNow();
151 fPrevReportTime = fNextReportTime = timeNow;
152
153 fKnownMembers = new RTCPMemberDatabase(*this);
154 fInBuf = new unsigned char[maxRTCPPacketSize];
155 if (fKnownMembers == NULL || fInBuf == NULL) return;
156 fNumBytesAlreadyRead = 0;
157
158 fOutBuf = new OutPacketBuffer(preferredRTCPPacketSize, maxRTCPPacketSize, maxRTCPPacketSize);
159 if (fOutBuf == NULL) return;
160
161 if (fSource != NULL && fSource->RTPgs() == RTCPgs) {
162 // We're receiving RTCP reports that are multiplexed with RTP, so ask the RTP source
163 // to give them to us:
164 fSource->registerForMultiplexedRTCPPackets(this);
165 } else {
166 // Arrange to handle incoming reports from the network:
167 TaskScheduler::BackgroundHandlerProc* handler
168 = (TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler;
169 fRTCPInterface.startNetworkReading(handler);
170 }
171
172 // Send our first report.
173 fTypeOfEvent = EVENT_REPORT;
174 onExpire(this);
175}
176
177struct RRHandlerRecord {
178 TaskFunc* rrHandlerTask;
179 void* rrHandlerClientData;
180};
181
182RTCPInstance::~RTCPInstance() {
183#ifdef DEBUG
184 fprintf(stderr, "RTCPInstance[%p]::~RTCPInstance()\n", this);
185#endif
186 // Begin by sending a BYE. We have to do this immediately, without
187 // 'reconsideration', because "this" is going away.
188 fTypeOfEvent = EVENT_BYE; // not used, but...
189 sendBYE();
190
191 if (fSource != NULL && fSource->RTPgs() == fRTCPInterface.gs()) {
192 // We were receiving RTCP reports that were multiplexed with RTP, so tell the RTP source
193 // to stop giving them to us:
194 fSource->deregisterForMultiplexedRTCPPackets();
195 fRTCPInterface.forgetOurGroupsock();
196 // so that the "fRTCPInterface" destructor doesn't turn off background read handling
197 }
198
199 if (fSpecificRRHandlerTable != NULL) {
200 AddressPortLookupTable::Iterator iter(*fSpecificRRHandlerTable);
201 RRHandlerRecord* rrHandler;
202 while ((rrHandler = (RRHandlerRecord*)iter.next()) != NULL) {
203 delete rrHandler;
204 }
205 delete fSpecificRRHandlerTable;
206 }
207
208 delete fKnownMembers;
209 delete fOutBuf;
210 delete[] fInBuf;
211}
212
213void RTCPInstance::noteArrivingRR(struct sockaddr_in const& fromAddressAndPort,
214 int tcpSocketNum, unsigned char tcpStreamChannelId) {
215 // If a 'RR handler' was set, call it now:
216
217 // Specific RR handler:
218 if (fSpecificRRHandlerTable != NULL) {
219 netAddressBits fromAddr;
220 portNumBits fromPortNum;
221 if (tcpSocketNum < 0) {
222 // Normal case: We read the RTCP packet over UDP
223 fromAddr = fromAddressAndPort.sin_addr.s_addr;
224 fromPortNum = ntohs(fromAddressAndPort.sin_port);
225 } else {
226 // Special case: We read the RTCP packet over TCP (interleaved)
227 // Hack: Use the TCP socket and channel id to look up the handler
228 fromAddr = tcpSocketNum;
229 fromPortNum = tcpStreamChannelId;
230 }
231 Port fromPort(fromPortNum);
232 RRHandlerRecord* rrHandler
233 = (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));
234 if (rrHandler != NULL) {
235 if (rrHandler->rrHandlerTask != NULL) {
236 (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);
237 }
238 }
239 }
240
241 // General RR handler:
242 if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);
243}
244
245RTCPInstance* RTCPInstance::createNew(UsageEnvironment& env, Groupsock* RTCPgs,
246 unsigned totSessionBW,
247 unsigned char const* cname,
248 RTPSink* sink, RTPSource* source,
249 Boolean isSSMSource) {
250 return new RTCPInstance(env, RTCPgs, totSessionBW, cname, sink, source,
251 isSSMSource);
252}
253
254Boolean RTCPInstance::lookupByName(UsageEnvironment& env,
255 char const* instanceName,
256 RTCPInstance*& resultInstance) {
257 resultInstance = NULL; // unless we succeed
258
259 Medium* medium;
260 if (!Medium::lookupByName(env, instanceName, medium)) return False;
261
262 if (!medium->isRTCPInstance()) {
263 env.setResultMsg(instanceName, " is not a RTCP instance");
264 return False;
265 }
266
267 resultInstance = (RTCPInstance*)medium;
268 return True;
269}
270
271Boolean RTCPInstance::isRTCPInstance() const {
272 return True;
273}
274
275unsigned RTCPInstance::numMembers() const {
276 if (fKnownMembers == NULL) return 0;
277
278 return fKnownMembers->numMembers();
279}
280
281void RTCPInstance::setByeHandler(TaskFunc* handlerTask, void* clientData,
282 Boolean handleActiveParticipantsOnly) {
283 fByeHandlerTask = handlerTask;
284 fByeWithReasonHandlerTask = NULL;
285 fByeHandlerClientData = clientData;
286 fByeHandleActiveParticipantsOnly = handleActiveParticipantsOnly;
287}
288
289void RTCPInstance::setByeWithReasonHandler(ByeWithReasonHandlerFunc* handlerTask, void* clientData,
290 Boolean handleActiveParticipantsOnly) {
291 fByeHandlerTask = NULL;
292 fByeWithReasonHandlerTask = handlerTask;
293 fByeHandlerClientData = clientData;
294 fByeHandleActiveParticipantsOnly = handleActiveParticipantsOnly;
295}
296
297void RTCPInstance::setSRHandler(TaskFunc* handlerTask, void* clientData) {
298 fSRHandlerTask = handlerTask;
299 fSRHandlerClientData = clientData;
300}
301
302void RTCPInstance::setRRHandler(TaskFunc* handlerTask, void* clientData) {
303 fRRHandlerTask = handlerTask;
304 fRRHandlerClientData = clientData;
305}
306
307void RTCPInstance
308::setSpecificRRHandler(netAddressBits fromAddress, Port fromPort,
309 TaskFunc* handlerTask, void* clientData) {
310 if (handlerTask == NULL && clientData == NULL) {
311 unsetSpecificRRHandler(fromAddress, fromPort);
312 return;
313 }
314
315 RRHandlerRecord* rrHandler = new RRHandlerRecord;
316 rrHandler->rrHandlerTask = handlerTask;
317 rrHandler->rrHandlerClientData = clientData;
318 if (fSpecificRRHandlerTable == NULL) {
319 fSpecificRRHandlerTable = new AddressPortLookupTable;
320 }
321 RRHandlerRecord* existingRecord = (RRHandlerRecord*)fSpecificRRHandlerTable->Add(fromAddress, (~0), fromPort, rrHandler);
322 delete existingRecord; // if any
323
324}
325
326void RTCPInstance
327::unsetSpecificRRHandler(netAddressBits fromAddress, Port fromPort) {
328 if (fSpecificRRHandlerTable == NULL) return;
329
330 RRHandlerRecord* rrHandler
331 = (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddress, (~0), fromPort));
332 if (rrHandler != NULL) {
333 fSpecificRRHandlerTable->Remove(fromAddress, (~0), fromPort);
334 delete rrHandler;
335 }
336}
337
338void RTCPInstance::setAppHandler(RTCPAppHandlerFunc* handlerTask, void* clientData) {
339 fAppHandlerTask = handlerTask;
340 fAppHandlerClientData = clientData;
341}
342
343void RTCPInstance::sendAppPacket(u_int8_t subtype, char const* name,
344 u_int8_t* appDependentData, unsigned appDependentDataSize) {
345 // Set up the first 4 bytes: V,PT,subtype,PT,length:
346 u_int32_t rtcpHdr = 0x80000000; // version 2, no padding
347 rtcpHdr |= (subtype&0x1F)<<24;
348 rtcpHdr |= (RTCP_PT_APP<<16);
349 unsigned length = 2 + (appDependentDataSize+3)/4;
350 rtcpHdr |= (length&0xFFFF);
351 fOutBuf->enqueueWord(rtcpHdr);
352
353 // Set up the next 4 bytes: SSRC:
354 fOutBuf->enqueueWord(fSource != NULL ? fSource->SSRC() : fSink != NULL ? fSink->SSRC() : 0);
355
356 // Set up the next 4 bytes: name:
357 char nameBytes[4];
358 nameBytes[0] = nameBytes[1] = nameBytes[2] = nameBytes[3] = '\0'; // by default
359 if (name != NULL) {
360 snprintf(nameBytes, 4, "%s", name);
361 }
362 fOutBuf->enqueue((u_int8_t*)nameBytes, 4);
363
364 // Set up the remaining bytes (if any): application-dependent data (+ padding):
365 if (appDependentData != NULL && appDependentDataSize > 0) {
366 fOutBuf->enqueue(appDependentData, appDependentDataSize);
367
368 unsigned modulo = appDependentDataSize%4;
369 unsigned paddingSize = modulo == 0 ? 0 : 4-modulo;
370 u_int8_t const paddingByte = 0x00;
371 for (unsigned i = 0; i < paddingSize; ++i) fOutBuf->enqueue(&paddingByte, 1);
372 }
373
374 // Finally, send the packet:
375 sendBuiltPacket();
376}
377
378void RTCPInstance::setStreamSocket(int sockNum,
379 unsigned char streamChannelId) {
380 // Turn off background read handling:
381 fRTCPInterface.stopNetworkReading();
382
383 // Switch to RTCP-over-TCP:
384 fRTCPInterface.setStreamSocket(sockNum, streamChannelId);
385
386 // Turn background reading back on:
387 TaskScheduler::BackgroundHandlerProc* handler
388 = (TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler;
389 fRTCPInterface.startNetworkReading(handler);
390}
391
392void RTCPInstance::addStreamSocket(int sockNum,
393 unsigned char streamChannelId) {
394 // First, turn off background read handling for the default (UDP) socket:
395 envir().taskScheduler().turnOffBackgroundReadHandling(fRTCPInterface.gs()->socketNum());
396
397 // Add the RTCP-over-TCP interface:
398 fRTCPInterface.addStreamSocket(sockNum, streamChannelId);
399
400 // Turn on background reading for this socket (in case it's not on already):
401 TaskScheduler::BackgroundHandlerProc* handler
402 = (TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler;
403 fRTCPInterface.startNetworkReading(handler);
404}
405
406void RTCPInstance
407::injectReport(u_int8_t const* packet, unsigned packetSize, struct sockaddr_in const& fromAddress) {
408 if (packetSize > maxRTCPPacketSize) packetSize = maxRTCPPacketSize;
409 memmove(fInBuf, packet, packetSize);
410
411 processIncomingReport(packetSize, fromAddress, -1, 0xFF); // assume report received over UDP
412}
413
414static unsigned const IP_UDP_HDR_SIZE = 28;
415 // overhead (bytes) of IP and UDP hdrs
416
417#define ADVANCE(n) pkt += (n); packetSize -= (n)
418
419void RTCPInstance::incomingReportHandler(RTCPInstance* instance,
420 int /*mask*/) {
421 instance->incomingReportHandler1();
422}
423
424void RTCPInstance::incomingReportHandler1() {
425 do {
426 if (fNumBytesAlreadyRead >= maxRTCPPacketSize) {
427 envir() << "RTCPInstance error: Hit limit when reading incoming packet over TCP. (fNumBytesAlreadyRead ("
428 << fNumBytesAlreadyRead << ") >= maxRTCPPacketSize (" << maxRTCPPacketSize
429 << ")). The remote endpoint is using a buggy implementation of RTP/RTCP-over-TCP. Please upgrade it!\n";
430 break;
431 }
432
433 unsigned numBytesRead;
434 struct sockaddr_in fromAddress;
435 int tcpSocketNum;
436 unsigned char tcpStreamChannelId;
437 Boolean packetReadWasIncomplete;
438 Boolean readResult
439 = fRTCPInterface.handleRead(&fInBuf[fNumBytesAlreadyRead], maxRTCPPacketSize - fNumBytesAlreadyRead,
440 numBytesRead, fromAddress,
441 tcpSocketNum, tcpStreamChannelId,
442 packetReadWasIncomplete);
443
444 unsigned packetSize = 0;
445 if (packetReadWasIncomplete) {
446 fNumBytesAlreadyRead += numBytesRead;
447 return; // more reads are needed to get the entire packet
448 } else { // normal case: We've read the entire packet
449 packetSize = fNumBytesAlreadyRead + numBytesRead;
450 fNumBytesAlreadyRead = 0; // for next time
451 }
452 if (!readResult) break;
453
454 // Ignore the packet if it was looped-back from ourself:
455 Boolean packetWasFromOurHost = False;
456 if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {
457 packetWasFromOurHost = True;
458 // However, we still want to handle incoming RTCP packets from
459 // *other processes* on the same machine. To distinguish this
460 // case from a true loop-back, check whether we've just sent a
461 // packet of the same size. (This check isn't perfect, but it seems
462 // to be the best we can do.)
463 if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) {
464 // This is a true loop-back:
465 fHaveJustSentPacket = False;
466 break; // ignore this packet
467 }
468 }
469
470 if (fIsSSMSource && !packetWasFromOurHost) {
471 // This packet is assumed to have been received via unicast (because we're a SSM source,
472 // and SSM receivers send back RTCP "RR" packets via unicast).
473 // 'Reflect' the packet by resending it to the multicast group, so that any other receivers
474 // can also get to see it.
475
476 // NOTE: Denial-of-service attacks are possible here.
477 // Users of this software may wish to add their own,
478 // application-specific mechanism for 'authenticating' the
479 // validity of this packet before reflecting it.
480
481 // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets
482 // that come from other processes on the same host as us. The reason for this is that the
483 // 'packet size' test above is not 100% reliable; some packets that were truly looped back
484 // from us might not be detected as such, and this might lead to infinite
485 // forwarding/receiving of some packets. To avoid this possibility, we reflect only
486 // RTCP packets that we know for sure originated elsewhere.
487 // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()",
488 // then we could remove the test for "!packetWasFromOurHost".)
489 fRTCPInterface.sendPacket(fInBuf, packetSize);
490 fHaveJustSentPacket = True;
491 fLastPacketSentSize = packetSize;
492 }
493
494 processIncomingReport(packetSize, fromAddress, tcpSocketNum, tcpStreamChannelId);
495 } while (0);
496}
497
498void RTCPInstance
499::processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddressAndPort,
500 int tcpSocketNum, unsigned char tcpStreamChannelId) {
501 do {
502 Boolean callByeHandler = False;
503 char* reason = NULL; // by default, unless/until a BYE packet with a 'reason' arrives
504 unsigned char* pkt = fInBuf;
505
506#ifdef DEBUG
507 fprintf(stderr, "[%p]saw incoming RTCP packet (from ", this);
508 if (tcpSocketNum < 0) {
509 // Note that "fromAddressAndPort" is valid only if we're receiving over UDP (not over TCP):
510 fprintf(stderr, "address %s, port %d", AddressString(fromAddressAndPort).val(), ntohs(fromAddressAndPort.sin_port));
511 } else {
512 fprintf(stderr, "TCP socket #%d, stream channel id %d", tcpSocketNum, tcpStreamChannelId);
513 }
514 fprintf(stderr, ")\n");
515 for (unsigned i = 0; i < packetSize; ++i) {
516 if (i%4 == 0) fprintf(stderr, " ");
517 fprintf(stderr, "%02x", pkt[i]);
518 }
519 fprintf(stderr, "\n");
520#endif
521 int totPacketSize = IP_UDP_HDR_SIZE + packetSize;
522
523 // Check the RTCP packet for validity:
524 // It must at least contain a header (4 bytes), and this header
525 // must be version=2, with no padding bit, and a payload type of
526 // SR (200), RR (201), or APP (204):
527 if (packetSize < 4) break;
528 unsigned rtcpHdr = ntohl(*(u_int32_t*)pkt);
529 if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16)) &&
530 (rtcpHdr & 0xE0FF0000) != (0x80000000 | (RTCP_PT_APP<<16))) {
531#ifdef DEBUG
532 fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);
533#endif
534 break;
535 }
536
537 // Process each of the individual RTCP 'subpackets' in (what may be)
538 // a compound RTCP packet.
539 int typeOfPacket = PACKET_UNKNOWN_TYPE;
540 unsigned reportSenderSSRC = 0;
541 Boolean packetOK = False;
542 while (1) {
543 u_int8_t rc = (rtcpHdr>>24)&0x1F;
544 u_int8_t pt = (rtcpHdr>>16)&0xFF;
545 unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr
546 ADVANCE(4); // skip over the header
547 if (length > packetSize) break;
548
549 // Assume that each RTCP subpacket begins with a 4-byte SSRC:
550 if (length < 4) break; length -= 4;
551 reportSenderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
552#ifdef HACK_FOR_CHROME_WEBRTC_BUG
553 if (reportSenderSSRC == 0x00000001 && pt == RTCP_PT_RR) {
554 // Chrome (and Opera) WebRTC receivers have a bug that causes them to always send
555 // SSRC 1 in their "RR"s. To work around this (to help us distinguish between different
556 // receivers), we use a fake SSRC in this case consisting of the IP address, XORed with
557 // the port number:
558 reportSenderSSRC = fromAddressAndPort.sin_addr.s_addr^fromAddressAndPort.sin_port;
559 }
560#endif
561
562 Boolean subPacketOK = False;
563 switch (pt) {
564 case RTCP_PT_SR: {
565#ifdef DEBUG
566 fprintf(stderr, "SR\n");
567#endif
568 if (length < 20) break; length -= 20;
569
570 // Extract the NTP timestamp, and note this:
571 unsigned NTPmsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
572 unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
573 unsigned rtpTimestamp = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
574 if (fSource != NULL) {
575 RTPReceptionStatsDB& receptionStats
576 = fSource->receptionStatsDB();
577 receptionStats.noteIncomingSR(reportSenderSSRC,
578 NTPmsw, NTPlsw, rtpTimestamp);
579 }
580 ADVANCE(8); // skip over packet count, octet count
581
582 // If a 'SR handler' was set, call it now:
583 if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);
584
585 // The rest of the SR is handled like a RR (so, no "break;" here)
586 }
587 case RTCP_PT_RR: {
588#ifdef DEBUG
589 fprintf(stderr, "RR\n");
590#endif
591 unsigned reportBlocksSize = rc*(6*4);
592 if (length < reportBlocksSize) break;
593 length -= reportBlocksSize;
594
595 if (fSink != NULL) {
596 // Use this information to update stats about our transmissions:
597 RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();
598 for (unsigned i = 0; i < rc; ++i) {
599 unsigned senderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
600 // We care only about reports about our own transmission, not others'
601 if (senderSSRC == fSink->SSRC()) {
602 unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
603 unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
604 unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
605 unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
606 unsigned timeSinceLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
607 transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddressAndPort,
608 lossStats,
609 highestReceived, jitter,
610 timeLastSR, timeSinceLastSR);
611 } else {
612 ADVANCE(4*5);
613 }
614 }
615 } else {
616 ADVANCE(reportBlocksSize);
617 }
618
619 if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'
620 noteArrivingRR(fromAddressAndPort, tcpSocketNum, tcpStreamChannelId);
621 }
622
623 subPacketOK = True;
624 typeOfPacket = PACKET_RTCP_REPORT;
625 break;
626 }
627 case RTCP_PT_BYE: {
628#ifdef DEBUG
629 fprintf(stderr, "BYE");
630#endif
631 // Check whether there was a 'reason for leaving':
632 if (length > 0) {
633 u_int8_t reasonLength = *pkt;
634 if (reasonLength > length-1) {
635 // The 'reason' length field is too large!
636#ifdef DEBUG
637 fprintf(stderr, "\nError: The 'reason' length %d is too large (it should be <= %d)\n",
638 reasonLength, length-1);
639#endif
640 reasonLength = length-1;
641 }
642 reason = new char[reasonLength + 1];
643 for (unsigned i = 0; i < reasonLength; ++i) {
644 reason[i] = pkt[1+i];
645 }
646 reason[reasonLength] = '\0';
647#ifdef DEBUG
648 fprintf(stderr, " (reason:%s)", reason);
649#endif
650 }
651#ifdef DEBUG
652 fprintf(stderr, "\n");
653#endif
654 // If a 'BYE handler' was set, arrange for it to be called at the end of this routine.
655 // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.)
656 if ((fByeHandlerTask != NULL || fByeWithReasonHandlerTask != NULL)
657 && (!fByeHandleActiveParticipantsOnly
658 || (fSource != NULL
659 && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)
660 || (fSink != NULL
661 && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {
662 callByeHandler = True;
663 }
664
665 // We should really check for & handle >1 SSRCs being present #####
666
667 subPacketOK = True;
668 typeOfPacket = PACKET_BYE;
669 break;
670 }
671 case RTCP_PT_APP: {
672 u_int8_t& subtype = rc; // In "APP" packets, the "rc" field gets used as "subtype"
673#ifdef DEBUG
674 fprintf(stderr, "APP (subtype 0x%02x)\n", subtype);
675#endif
676 if (length < 4) {
677#ifdef DEBUG
678 fprintf(stderr, "\tError: No \"name\" field!\n");
679#endif
680 break;
681 }
682 length -= 4;
683#ifdef DEBUG
684 fprintf(stderr, "\tname:%c%c%c%c\n", pkt[0], pkt[1], pkt[2], pkt[3]);
685#endif
686 u_int32_t nameBytes = (pkt[0]<<24)|(pkt[1]<<16)|(pkt[2]<<8)|(pkt[3]);
687 ADVANCE(4); // skip over "name", to the 'application-dependent data'
688#ifdef DEBUG
689 fprintf(stderr, "\tapplication-dependent data size: %d bytes\n", length);
690#endif
691
692 // If an 'APP' packet handler was set, call it now:
693 if (fAppHandlerTask != NULL) {
694 (*fAppHandlerTask)(fAppHandlerClientData, subtype, nameBytes, pkt, length);
695 }
696 subPacketOK = True;
697 typeOfPacket = PACKET_RTCP_APP;
698 break;
699 }
700 // Other RTCP packet types that we don't yet handle:
701 case RTCP_PT_SDES: {
702#ifdef DEBUG
703 // 'Handle' SDES packets only in debugging code, by printing out the 'SDES items':
704 fprintf(stderr, "SDES\n");
705
706 // Process each 'chunk':
707 Boolean chunkOK = False;
708 ADVANCE(-4); length += 4; // hack so that we see the first SSRC/CSRC again
709 while (length >= 8) { // A valid chunk must be at least 8 bytes long
710 chunkOK = False; // until we learn otherwise
711
712 u_int32_t SSRC_CSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4); length -= 4;
713 fprintf(stderr, "\tSSRC/CSRC: 0x%08x\n", SSRC_CSRC);
714
715 // Process each 'SDES item' in the chunk:
716 u_int8_t itemType = *pkt; ADVANCE(1); --length;
717 while (itemType != 0) {
718 unsigned itemLen = *pkt; ADVANCE(1); --length;
719 // Make sure "itemLen" allows for at least 1 zero byte at the end of the chunk:
720 if (itemLen + 1 > length || pkt[itemLen] != 0) break;
721
722 fprintf(stderr, "\t\t%s:%s\n",
723 itemType == 1 ? "CNAME" :
724 itemType == 2 ? "NAME" :
725 itemType == 3 ? "EMAIL" :
726 itemType == 4 ? "PHONE" :
727 itemType == 5 ? "LOC" :
728 itemType == 6 ? "TOOL" :
729 itemType == 7 ? "NOTE" :
730 itemType == 8 ? "PRIV" :
731 "(unknown)",
732 itemType < 8 ? (char*)pkt // hack, because we know it's '\0'-terminated
733 : "???"/* don't try to print out PRIV or unknown items */);
734 ADVANCE(itemLen); length -= itemLen;
735
736 itemType = *pkt; ADVANCE(1); --length;
737 }
738 if (itemType != 0) break; // bad 'SDES item'
739
740 // Thus, itemType == 0. This zero 'type' marks the end of the list of SDES items.
741 // Skip over remaining zero padding bytes, so that this chunk ends on a 4-byte boundary:
742 while (length%4 > 0 && *pkt == 0) { ADVANCE(1); --length; }
743 if (length%4 > 0) break; // Bad (non-zero) padding byte
744
745 chunkOK = True;
746 }
747 if (!chunkOK || length > 0) break; // bad chunk, or not enough bytes for the last chunk
748#endif
749 subPacketOK = True;
750 break;
751 }
752 case RTCP_PT_RTPFB: {
753#ifdef DEBUG
754 fprintf(stderr, "RTPFB(unhandled)\n");
755#endif
756 subPacketOK = True;
757 break;
758 }
759 case RTCP_PT_PSFB: {
760#ifdef DEBUG
761 fprintf(stderr, "PSFB(unhandled)\n");
762 // Temporary code to show "Receiver Estimated Maximum Bitrate" (REMB) feedback reports:
763 //#####
764 if (length >= 12 && pkt[4] == 'R' && pkt[5] == 'E' && pkt[6] == 'M' && pkt[7] == 'B') {
765 u_int8_t exp = pkt[9]>>2;
766 u_int32_t mantissa = ((pkt[9]&0x03)<<16)|(pkt[10]<<8)|pkt[11];
767 double remb = (double)mantissa;
768 while (exp > 0) {
769 remb *= 2.0;
770 exp /= 2;
771 }
772 fprintf(stderr, "\tReceiver Estimated Max Bitrate (REMB): %g bps\n", remb);
773 }
774#endif
775 subPacketOK = True;
776 break;
777 }
778 case RTCP_PT_XR: {
779#ifdef DEBUG
780 fprintf(stderr, "XR(unhandled)\n");
781#endif
782 subPacketOK = True;
783 break;
784 }
785 case RTCP_PT_AVB: {
786#ifdef DEBUG
787 fprintf(stderr, "AVB(unhandled)\n");
788#endif
789 subPacketOK = True;
790 break;
791 }
792 case RTCP_PT_RSI: {
793#ifdef DEBUG
794 fprintf(stderr, "RSI(unhandled)\n");
795#endif
796 subPacketOK = True;
797 break;
798 }
799 case RTCP_PT_TOKEN: {
800#ifdef DEBUG
801 fprintf(stderr, "TOKEN(unhandled)\n");
802#endif
803 subPacketOK = True;
804 break;
805 }
806 case RTCP_PT_IDMS: {
807#ifdef DEBUG
808 fprintf(stderr, "IDMS(unhandled)\n");
809#endif
810 subPacketOK = True;
811 break;
812 }
813 default: {
814#ifdef DEBUG
815 fprintf(stderr, "UNKNOWN TYPE(0x%x)\n", pt);
816#endif
817 subPacketOK = True;
818 break;
819 }
820 }
821 if (!subPacketOK) break;
822
823 // need to check for (& handle) SSRC collision! #####
824
825#ifdef DEBUG
826 fprintf(stderr, "validated RTCP subpacket: rc:%d, pt:%d, bytes remaining:%d, report sender SSRC:0x%08x\n", rc, pt, length, reportSenderSSRC);
827#endif
828
829 // Skip over any remaining bytes in this subpacket:
830 ADVANCE(length);
831
832 // Check whether another RTCP 'subpacket' follows:
833 if (packetSize == 0) {
834 packetOK = True;
835 break;
836 } else if (packetSize < 4) {
837#ifdef DEBUG
838 fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);
839#endif
840 break;
841 }
842 rtcpHdr = ntohl(*(u_int32_t*)pkt);
843 if ((rtcpHdr & 0xC0000000) != 0x80000000) {
844#ifdef DEBUG
845 fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
846#endif
847 break;
848 }
849 }
850
851 if (!packetOK) {
852#ifdef DEBUG
853 fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
854#endif
855 break;
856 } else {
857#ifdef DEBUG
858 fprintf(stderr, "validated entire RTCP packet\n");
859#endif
860 }
861
862 onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);
863
864 // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted):
865 if (callByeHandler) {
866 if (fByeHandlerTask != NULL) { // call a BYE handler without including a 'reason'
867 TaskFunc* byeHandler = fByeHandlerTask;
868 fByeHandlerTask = NULL; // because we call the handler only once, by default
869 (*byeHandler)(fByeHandlerClientData);
870 } else if (fByeWithReasonHandlerTask != NULL) { // call a BYE handler that includes a 'reason'
871 ByeWithReasonHandlerFunc* byeHandler = fByeWithReasonHandlerTask;
872 fByeWithReasonHandlerTask = NULL; // because we call the handler only once, by default
873 (*byeHandler)(fByeHandlerClientData, reason);
874 // Note that the handler function is responsible for delete[]ing "reason"
875 }
876 }
877 } while (0);
878}
879
880void RTCPInstance::onReceive(int typeOfPacket, int totPacketSize, u_int32_t ssrc) {
881 fTypeOfPacket = typeOfPacket;
882 fLastReceivedSize = totPacketSize;
883 fLastReceivedSSRC = ssrc;
884
885 int members = (int)numMembers();
886 int senders = (fSink != NULL) ? 1 : 0;
887
888 OnReceive(this, // p
889 this, // e
890 &members, // members
891 &fPrevNumMembers, // pmembers
892 &senders, // senders
893 &fAveRTCPSize, // avg_rtcp_size
894 &fPrevReportTime, // tp
895 dTimeNow(), // tc
896 fNextReportTime);
897}
898
899void RTCPInstance::sendReport() {
900#ifdef DEBUG
901 fprintf(stderr, "sending REPORT\n");
902#endif
903 // Begin by including a SR and/or RR report:
904 if (!addReport()) return;
905
906 // Then, include a SDES:
907 addSDES();
908
909 // Send the report:
910 sendBuiltPacket();
911
912 // Periodically clean out old members from our SSRC membership database:
913 const unsigned membershipReapPeriod = 5;
914 if ((++fOutgoingReportCount) % membershipReapPeriod == 0) {
915 unsigned threshold = fOutgoingReportCount - membershipReapPeriod;
916 fKnownMembers->reapOldMembers(threshold);
917 }
918}
919
920void RTCPInstance::sendBYE(char const* reason) {
921#ifdef DEBUG
922 if (reason != NULL) {
923 fprintf(stderr, "sending BYE (reason:%s)\n", reason);
924 } else {
925 fprintf(stderr, "sending BYE\n");
926 }
927#endif
928 // The packet must begin with a SR and/or RR report:
929 (void)addReport(True);
930
931 addBYE(reason);
932 sendBuiltPacket();
933}
934
935void RTCPInstance::sendBuiltPacket() {
936#ifdef DEBUG
937 fprintf(stderr, "sending RTCP packet\n");
938 unsigned char* p = fOutBuf->packet();
939 for (unsigned i = 0; i < fOutBuf->curPacketSize(); ++i) {
940 if (i%4 == 0) fprintf(stderr," ");
941 fprintf(stderr, "%02x", p[i]);
942 }
943 fprintf(stderr, "\n");
944#endif
945 unsigned reportSize = fOutBuf->curPacketSize();
946 fRTCPInterface.sendPacket(fOutBuf->packet(), reportSize);
947 fOutBuf->resetOffset();
948
949 fLastSentSize = IP_UDP_HDR_SIZE + reportSize;
950 fHaveJustSentPacket = True;
951 fLastPacketSentSize = reportSize;
952}
953
954int RTCPInstance::checkNewSSRC() {
955 return fKnownMembers->noteMembership(fLastReceivedSSRC,
956 fOutgoingReportCount);
957}
958
959void RTCPInstance::removeLastReceivedSSRC() {
960 removeSSRC(fLastReceivedSSRC, False/*keep stats around*/);
961}
962
963void RTCPInstance::removeSSRC(u_int32_t ssrc, Boolean alsoRemoveStats) {
964 fKnownMembers->remove(ssrc);
965
966 if (alsoRemoveStats) {
967 // Also, remove records of this SSRC from any reception or transmission stats
968 if (fSource != NULL) fSource->receptionStatsDB().removeRecord(ssrc);
969 if (fSink != NULL) fSink->transmissionStatsDB().removeRecord(ssrc);
970 }
971}
972
973void RTCPInstance::onExpire(RTCPInstance* instance) {
974 instance->onExpire1();
975}
976
977// Member functions to build specific kinds of report:
978
979Boolean RTCPInstance::addReport(Boolean alwaysAdd) {
980 // Include a SR or a RR, depending on whether we have an associated sink or source:
981 if (fSink != NULL) {
982 if (!alwaysAdd) {
983 if (!fSink->enableRTCPReports()) return False;
984
985 // Hack: Don't send a SR during those (brief) times when the timestamp of the
986 // next outgoing RTP packet has been preset, to ensure that that timestamp gets
987 // used for that outgoing packet. (David Bertrand, 2006.07.18)
988 if (fSink->nextTimestampHasBeenPreset()) return False;
989 }
990
991 addSR();
992 }
993 if (fSource != NULL) {
994 if (!alwaysAdd) {
995 if (!fSource->enableRTCPReports()) return False;
996 }
997
998 addRR();
999 }
1000
1001 return True;
1002}
1003
1004void RTCPInstance::addSR() {
1005 // ASSERT: fSink != NULL
1006
1007 enqueueCommonReportPrefix(RTCP_PT_SR, fSink->SSRC(),
1008 5 /* extra words in a SR */);
1009
1010 // Now, add the 'sender info' for our sink
1011
1012 // Insert the NTP and RTP timestamps for the 'wallclock time':
1013 struct timeval timeNow;
1014 gettimeofday(&timeNow, NULL);
1015 fOutBuf->enqueueWord(timeNow.tv_sec + 0x83AA7E80);
1016 // NTP timestamp most-significant word (1970 epoch -> 1900 epoch)
1017 double fractionalPart = (timeNow.tv_usec/15625.0)*0x04000000; // 2^32/10^6
1018 fOutBuf->enqueueWord((unsigned)(fractionalPart+0.5));
1019 // NTP timestamp least-significant word
1020 unsigned rtpTimestamp = fSink->convertToRTPTimestamp(timeNow);
1021 fOutBuf->enqueueWord(rtpTimestamp); // RTP ts
1022
1023 // Insert the packet and byte counts:
1024 fOutBuf->enqueueWord(fSink->packetCount());
1025 fOutBuf->enqueueWord(fSink->octetCount());
1026
1027 enqueueCommonReportSuffix();
1028}
1029
1030void RTCPInstance::addRR() {
1031 // ASSERT: fSource != NULL
1032
1033 enqueueCommonReportPrefix(RTCP_PT_RR, fSource->SSRC());
1034 enqueueCommonReportSuffix();
1035}
1036
1037void RTCPInstance::enqueueCommonReportPrefix(unsigned char packetType,
1038 u_int32_t SSRC,
1039 unsigned numExtraWords) {
1040 unsigned numReportingSources;
1041 if (fSource == NULL) {
1042 numReportingSources = 0; // we don't receive anything
1043 } else {
1044 RTPReceptionStatsDB& allReceptionStats
1045 = fSource->receptionStatsDB();
1046 numReportingSources = allReceptionStats.numActiveSourcesSinceLastReset();
1047 // This must be <32, to fit in 5 bits:
1048 if (numReportingSources >= 32) { numReportingSources = 32; }
1049 // Later: support adding more reports to handle >32 sources (unlikely)#####
1050 }
1051
1052 unsigned rtcpHdr = 0x80000000; // version 2, no padding
1053 rtcpHdr |= (numReportingSources<<24);
1054 rtcpHdr |= (packetType<<16);
1055 rtcpHdr |= (1 + numExtraWords + 6*numReportingSources);
1056 // each report block is 6 32-bit words long
1057 fOutBuf->enqueueWord(rtcpHdr);
1058
1059 fOutBuf->enqueueWord(SSRC);
1060}
1061
1062void RTCPInstance::enqueueCommonReportSuffix() {
1063 // Output the report blocks for each source:
1064 if (fSource != NULL) {
1065 RTPReceptionStatsDB& allReceptionStats
1066 = fSource->receptionStatsDB();
1067
1068 RTPReceptionStatsDB::Iterator iterator(allReceptionStats);
1069 while (1) {
1070 RTPReceptionStats* receptionStats = iterator.next();
1071 if (receptionStats == NULL) break;
1072 enqueueReportBlock(receptionStats);
1073 }
1074
1075 allReceptionStats.reset(); // because we have just generated a report
1076 }
1077}
1078
1079void
1080RTCPInstance::enqueueReportBlock(RTPReceptionStats* stats) {
1081 fOutBuf->enqueueWord(stats->SSRC());
1082
1083 unsigned highestExtSeqNumReceived = stats->highestExtSeqNumReceived();
1084
1085 unsigned totNumExpected
1086 = highestExtSeqNumReceived - stats->baseExtSeqNumReceived();
1087 int totNumLost = totNumExpected - stats->totNumPacketsReceived();
1088 // 'Clamp' this loss number to a 24-bit signed value:
1089 if (totNumLost > 0x007FFFFF) {
1090 totNumLost = 0x007FFFFF;
1091 } else if (totNumLost < 0) {
1092 if (totNumLost < -0x00800000) totNumLost = 0x00800000; // unlikely, but...
1093 totNumLost &= 0x00FFFFFF;
1094 }
1095
1096 unsigned numExpectedSinceLastReset
1097 = highestExtSeqNumReceived - stats->lastResetExtSeqNumReceived();
1098 int numLostSinceLastReset
1099 = numExpectedSinceLastReset - stats->numPacketsReceivedSinceLastReset();
1100 unsigned char lossFraction;
1101 if (numExpectedSinceLastReset == 0 || numLostSinceLastReset < 0) {
1102 lossFraction = 0;
1103 } else {
1104 lossFraction = (unsigned char)
1105 ((numLostSinceLastReset << 8) / numExpectedSinceLastReset);
1106 }
1107
1108 fOutBuf->enqueueWord((lossFraction<<24) | totNumLost);
1109 fOutBuf->enqueueWord(highestExtSeqNumReceived);
1110
1111 fOutBuf->enqueueWord(stats->jitter());
1112
1113 unsigned NTPmsw = stats->lastReceivedSR_NTPmsw();
1114 unsigned NTPlsw = stats->lastReceivedSR_NTPlsw();
1115 unsigned LSR = ((NTPmsw&0xFFFF)<<16)|(NTPlsw>>16); // middle 32 bits
1116 fOutBuf->enqueueWord(LSR);
1117
1118 // Figure out how long has elapsed since the last SR rcvd from this src:
1119 struct timeval const& LSRtime = stats->lastReceivedSR_time(); // "last SR"
1120 struct timeval timeNow, timeSinceLSR;
1121 gettimeofday(&timeNow, NULL);
1122 if (timeNow.tv_usec < LSRtime.tv_usec) {
1123 timeNow.tv_usec += 1000000;
1124 timeNow.tv_sec -= 1;
1125 }
1126 timeSinceLSR.tv_sec = timeNow.tv_sec - LSRtime.tv_sec;
1127 timeSinceLSR.tv_usec = timeNow.tv_usec - LSRtime.tv_usec;
1128 // The enqueued time is in units of 1/65536 seconds.
1129 // (Note that 65536/1000000 == 1024/15625)
1130 unsigned DLSR;
1131 if (LSR == 0) {
1132 DLSR = 0;
1133 } else {
1134 DLSR = (timeSinceLSR.tv_sec<<16)
1135 | ( (((timeSinceLSR.tv_usec<<11)+15625)/31250) & 0xFFFF);
1136 }
1137 fOutBuf->enqueueWord(DLSR);
1138}
1139
1140void RTCPInstance::addSDES() {
1141 // For now we support only the CNAME item; later support more #####
1142
1143 // Begin by figuring out the size of the entire SDES report:
1144 unsigned numBytes = 4;
1145 // counts the SSRC, but not the header; it'll get subtracted out
1146 numBytes += fCNAME.totalSize(); // includes id and length
1147 numBytes += 1; // the special END item
1148
1149 unsigned num4ByteWords = (numBytes + 3)/4;
1150
1151 unsigned rtcpHdr = 0x81000000; // version 2, no padding, 1 SSRC chunk
1152 rtcpHdr |= (RTCP_PT_SDES<<16);
1153 rtcpHdr |= num4ByteWords;
1154 fOutBuf->enqueueWord(rtcpHdr);
1155
1156 if (fSource != NULL) {
1157 fOutBuf->enqueueWord(fSource->SSRC());
1158 } else if (fSink != NULL) {
1159 fOutBuf->enqueueWord(fSink->SSRC());
1160 }
1161
1162 // Add the CNAME:
1163 fOutBuf->enqueue(fCNAME.data(), fCNAME.totalSize());
1164
1165 // Add the 'END' item (i.e., a zero byte), plus any more needed to pad:
1166 unsigned numPaddingBytesNeeded = 4 - (fOutBuf->curPacketSize() % 4);
1167 unsigned char const zero = '\0';
1168 while (numPaddingBytesNeeded-- > 0) fOutBuf->enqueue(&zero, 1);
1169}
1170
1171void RTCPInstance::addBYE(char const* reason) {
1172 u_int32_t rtcpHdr = 0x81000000; // version 2, no padding, 1 SSRC
1173 rtcpHdr |= (RTCP_PT_BYE<<16);
1174 u_int16_t num32BitWords = 2; // by default, two 32-bit words total (i.e., with 1 SSRC)
1175 u_int8_t reasonLength8Bits = 0; // by default
1176 if (reason != NULL) {
1177 // We need to add more 32-bit words for the 'length+reason':
1178 unsigned const reasonLength = strlen(reason);
1179 reasonLength8Bits = reasonLength < 0xFF ? (u_int8_t)reasonLength : 0xFF;
1180 unsigned numExtraWords = ((1/*reason length field*/+reasonLength8Bits)+3)/4;
1181
1182 num32BitWords += numExtraWords;
1183 }
1184 rtcpHdr |= (num32BitWords-1); // length field
1185 fOutBuf->enqueueWord(rtcpHdr);
1186
1187 if (fSource != NULL) {
1188 fOutBuf->enqueueWord(fSource->SSRC());
1189 } else if (fSink != NULL) {
1190 fOutBuf->enqueueWord(fSink->SSRC());
1191 }
1192
1193 num32BitWords -= 2; // ASSERT: num32BitWords >= 0
1194 if (num32BitWords > 0) {
1195 // Add a length+'reason for leaving':
1196 // First word:
1197 u_int32_t lengthPlusFirst3ReasonBytes = reasonLength8Bits<<24;
1198 unsigned index = 0;
1199 if (reasonLength8Bits > index) lengthPlusFirst3ReasonBytes |= ((u_int8_t)reason[index++])<<16;
1200 if (reasonLength8Bits > index) lengthPlusFirst3ReasonBytes |= ((u_int8_t)reason[index++])<<8;
1201 if (reasonLength8Bits > index) lengthPlusFirst3ReasonBytes |= (u_int8_t)reason[index++];
1202 fOutBuf->enqueueWord(lengthPlusFirst3ReasonBytes);
1203
1204 // Any subsequent words:
1205 if (reasonLength8Bits > 3) {
1206 // ASSERT: num32BitWords > 1
1207 while (--num32BitWords > 0) {
1208 u_int32_t fourMoreReasonBytes = 0;
1209 if (reasonLength8Bits > index) fourMoreReasonBytes |= ((u_int8_t)reason[index++])<<24;
1210 if (reasonLength8Bits > index) fourMoreReasonBytes |= ((u_int8_t)reason[index++])<<16;
1211 if (reasonLength8Bits > index) fourMoreReasonBytes |= ((u_int8_t)reason[index++])<<8;
1212 if (reasonLength8Bits > index) fourMoreReasonBytes |= (u_int8_t)reason[index++];
1213 fOutBuf->enqueueWord(fourMoreReasonBytes);
1214 }
1215 }
1216 }
1217}
1218
1219void RTCPInstance::schedule(double nextTime) {
1220 fNextReportTime = nextTime;
1221
1222 double secondsToDelay = nextTime - dTimeNow();
1223 if (secondsToDelay < 0) secondsToDelay = 0;
1224#ifdef DEBUG
1225 fprintf(stderr, "schedule(%f->%f)\n", secondsToDelay, nextTime);
1226#endif
1227 int64_t usToGo = (int64_t)(secondsToDelay * 1000000);
1228 nextTask() = envir().taskScheduler().scheduleDelayedTask(usToGo,
1229 (TaskFunc*)RTCPInstance::onExpire, this);
1230}
1231
1232void RTCPInstance::reschedule(double nextTime) {
1233 envir().taskScheduler().unscheduleDelayedTask(nextTask());
1234 schedule(nextTime);
1235}
1236
1237void RTCPInstance::onExpire1() {
1238 nextTask() = NULL;
1239
1240 // Note: fTotSessionBW is kbits per second
1241 double rtcpBW = 0.05*fTotSessionBW*1024/8; // -> bytes per second
1242
1243 OnExpire(this, // event
1244 numMembers(), // members
1245 (fSink != NULL) ? 1 : 0, // senders
1246 rtcpBW, // rtcp_bw
1247 (fSink != NULL) ? 1 : 0, // we_sent
1248 &fAveRTCPSize, // ave_rtcp_size
1249 &fIsInitial, // initial
1250 dTimeNow(), // tc
1251 &fPrevReportTime, // tp
1252 &fPrevNumMembers // pmembers
1253 );
1254}
1255
1256////////// SDESItem //////////
1257
1258SDESItem::SDESItem(unsigned char tag, unsigned char const* value) {
1259 unsigned length = strlen((char const*)value);
1260 if (length > 0xFF) length = 0xFF; // maximum data length for a SDES item
1261
1262 fData[0] = tag;
1263 fData[1] = (unsigned char)length;
1264 memmove(&fData[2], value, length);
1265}
1266
1267unsigned SDESItem::totalSize() const {
1268 return 2 + (unsigned)fData[1];
1269}
1270
1271
1272////////// Implementation of routines imported by the "rtcp_from_spec" C code
1273
1274extern "C" void Schedule(double nextTime, event e) {
1275 RTCPInstance* instance = (RTCPInstance*)e;
1276 if (instance == NULL) return;
1277
1278 instance->schedule(nextTime);
1279}
1280
1281extern "C" void Reschedule(double nextTime, event e) {
1282 RTCPInstance* instance = (RTCPInstance*)e;
1283 if (instance == NULL) return;
1284
1285 instance->reschedule(nextTime);
1286}
1287
1288extern "C" void SendRTCPReport(event e) {
1289 RTCPInstance* instance = (RTCPInstance*)e;
1290 if (instance == NULL) return;
1291
1292 instance->sendReport();
1293}
1294
1295extern "C" void SendBYEPacket(event e) {
1296 RTCPInstance* instance = (RTCPInstance*)e;
1297 if (instance == NULL) return;
1298
1299 instance->sendBYE();
1300}
1301
1302extern "C" int TypeOfEvent(event e) {
1303 RTCPInstance* instance = (RTCPInstance*)e;
1304 if (instance == NULL) return EVENT_UNKNOWN;
1305
1306 return instance->typeOfEvent();
1307}
1308
1309extern "C" int SentPacketSize(event e) {
1310 RTCPInstance* instance = (RTCPInstance*)e;
1311 if (instance == NULL) return 0;
1312
1313 return instance->sentPacketSize();
1314}
1315
1316extern "C" int PacketType(packet p) {
1317 RTCPInstance* instance = (RTCPInstance*)p;
1318 if (instance == NULL) return PACKET_UNKNOWN_TYPE;
1319
1320 return instance->packetType();
1321}
1322
1323extern "C" int ReceivedPacketSize(packet p) {
1324 RTCPInstance* instance = (RTCPInstance*)p;
1325 if (instance == NULL) return 0;
1326
1327 return instance->receivedPacketSize();
1328}
1329
1330extern "C" int NewMember(packet p) {
1331 RTCPInstance* instance = (RTCPInstance*)p;
1332 if (instance == NULL) return 0;
1333
1334 return instance->checkNewSSRC();
1335}
1336
1337extern "C" int NewSender(packet /*p*/) {
1338 return 0; // we don't yet recognize senders other than ourselves #####
1339}
1340
1341extern "C" void AddMember(packet /*p*/) {
1342 // Do nothing; all of the real work was done when NewMember() was called
1343}
1344
1345extern "C" void AddSender(packet /*p*/) {
1346 // we don't yet recognize senders other than ourselves #####
1347}
1348
1349extern "C" void RemoveMember(packet p) {
1350 RTCPInstance* instance = (RTCPInstance*)p;
1351 if (instance == NULL) return;
1352
1353 instance->removeLastReceivedSSRC();
1354}
1355
1356extern "C" void RemoveSender(packet /*p*/) {
1357 // we don't yet recognize senders other than ourselves #####
1358}
1359
1360extern "C" double drand30() {
1361 unsigned tmp = our_random()&0x3FFFFFFF; // a random 30-bit integer
1362 return tmp/(double)(1024*1024*1024);
1363}
1364