Darwin-Streaming-Server/RTCPUtilitiesLib/RTCPAckPacketFmt.h
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

158 lines
5.8 KiB
C++

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: RTCPAckPacketFmt.h
Some useful things for Generating Ack Packets
*/
#ifndef _RTCPACKPACKETFMT_H_
#define _RTCPACKPACKETFMT_H_
#include <stdlib.h>
#include <arpa/inet.h>
#include "StrPtrLen.h"
#include "OSHeaders.h"
#include "MyAssert.h"
class RTCPAckPacketFmt
{
enum {
RTP_VERSION = 2,
RTCP_SR = 200,
RTCP_RR = 201,
RTCP_SDES = 202,
RTCP_BYE = 203,
RTCP_APP = 204
};
struct RTCPAckHeader {
#if 0
//ackheader
unsigned int version:2; /* protocol version */
unsigned int p:1; /* padding flag */
unsigned int subtype:5; /* the subtype of ack */
unsigned int pt:8; /* RTCP packet type */
#endif
UInt16 ackheader;
UInt16 length; /* pkt len in words, w/o this word */
UInt32 SSRC; /* sender generating this packet */
UInt32 name; /* four ASCII chars */
UInt32 SSRC1; /* SSRC of the stream */
UInt16 reserved;
UInt16 seqNum;
};
public:
RTCPAckPacketFmt() : fBitMaskSize(0) {}
RTCPAckPacketFmt(StrPtrLen &newBuffer) : fBitMaskSize(0) { SetBuffer(newBuffer); }
RTCPAckPacketFmt(char *newBuffer, UInt32 bufLen) : fBitMaskSize(0) { SetBuffer(newBuffer, bufLen); }
//Setting the buffer resets the packet
void SetBuffer(StrPtrLen &newBuffer) { return this->SetBuffer(newBuffer.Ptr, newBuffer.Len); }
void SetBuffer(char *newBuffer, UInt32 bufLen)
{
Assert(sizeof(RTCPAckHeader) == 20);
Assert(bufLen >= sizeof(RTCPAckHeader));
fBitMaskSize = 0;
fBuf.Set(newBuffer, bufLen);
//fill in the header
RTCPAckHeader &header = *reinterpret_cast<RTCPAckHeader *>(fBuf.Ptr);
::memset(&header, 0, sizeof(header));
header.ackheader = htons(0x80CC); //(RTP_VERSION << 14) + RTCP_APP;
header.length = htons(GetPacketLen() / 4 - 1);
header.name = htonl(FOUR_CHARS_TO_INT('q', 't', 'a', 'k'));
}
void SetSSRC(UInt32 SSRC)
{
RTCPAckHeader &header = *reinterpret_cast<RTCPAckHeader *>(fBuf.Ptr);
header.SSRC = htonl(SSRC);
}
//Can handle duplicates
void SetAcks(SVector<UInt32> AckList, UInt32 serverSSRC)
{
Assert(!AckList.empty());
::qsort(AckList.begin(), AckList.size(), sizeof(UInt32), UInt32Compare);
RTCPAckHeader &header = *reinterpret_cast<RTCPAckHeader *>(fBuf.Ptr);
header.SSRC1 = htonl(serverSSRC);
header.seqNum = htons(static_cast<UInt16>(AckList.front()));
fBitMaskSize = 0;
if (AckList.front() == AckList.back()) //no mask is needed
return;
//figure out how big the mask is supposed to be
UInt32 slotsInMaskNeeded = AckList.back() - AckList.front();
fBitMaskSize = slotsInMaskNeeded % 32 == 0 ? (slotsInMaskNeeded / 32) * 4 : (slotsInMaskNeeded / 32 + 1) * 4;
header.length = htons(GetPacketLen() / 4 - 1);
Assert(fBuf.Len >= GetPacketLen());
UInt32 *mask = reinterpret_cast<UInt32 *>(fBuf.Ptr + sizeof(RTCPAckHeader));
::memset(mask, 0, fBitMaskSize);
//calculate where the bit to set is supposed to be and sets the bits
for(UInt32 i = 1; i < AckList.size(); ++i)
{
if (AckList.front() == AckList[i])
continue;
UInt32 diff = AckList[i] - (AckList.front() + 1);
UInt32 maskIndex = diff / 32;
UInt32 shiftSize = diff % 32;
mask[maskIndex] |= 0x80000000 >> shiftSize;
Assert(maskIndex * 4 < fBitMaskSize);
}
//restore big-endianess of the mask
for(UInt32 i = 0; i < fBitMaskSize / 4; ++i)
mask[i] = htonl(mask[i]);
}
//The length of packet written out
UInt32 GetPacketLen() { return sizeof(RTCPAckHeader) + fBitMaskSize; }
StrPtrLen GetBufferRemaining() { return StrPtrLen(fBuf.Ptr + GetPacketLen(), fBuf.Len - GetPacketLen()); }
StrPtrLen GetPacket() { return StrPtrLen(fBuf.Ptr, GetPacketLen()); }
private:
static int UInt32Compare(const void *left, const void *right)
{
UInt32 l = *reinterpret_cast<const UInt32 *>(left);
UInt32 r = *reinterpret_cast<const UInt32 *>(right);
return l < r ? -1 : l > r ? 1 : 0;
}
StrPtrLen fBuf;
UInt32 fBitMaskSize; // in bytes, not words
};
#endif //_RTCPACKPACKETFMT_H_