328 lines
9.8 KiB
C++
328 lines
9.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: RTSPRequest3GPP.cpp
|
||
|
|
||
|
Contains: Implementation of RTSPRequest3GPP class.
|
||
|
|
||
|
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "RTSPRequest3GPP.h"
|
||
|
#include "RTSPProtocol.h"
|
||
|
#include "QTSServerInterface.h"
|
||
|
|
||
|
#include "RTSPSession.h"
|
||
|
#include "RTSPSessionInterface.h"
|
||
|
#include "StringParser.h"
|
||
|
#include "StringTranslator.h"
|
||
|
#include "OS.h"
|
||
|
#include "OSMemory.h"
|
||
|
#include "QTSS.h"
|
||
|
#include "QTSSModuleUtils.h"
|
||
|
#include "base64.h"
|
||
|
#include "OSArrayObjectDeleter.h"
|
||
|
#include "DateTranslator.h"
|
||
|
#include "SocketUtils.h"
|
||
|
|
||
|
|
||
|
void RateAdapationStreamDataFields::SetData(StrPtrLen *streamDataStr)
|
||
|
{
|
||
|
|
||
|
static StrPtrLen sSize("size");
|
||
|
static StrPtrLen sTargetTime("target-time");
|
||
|
static StrPtrLen sURL("url");
|
||
|
|
||
|
StringParser theStreamDataParser(streamDataStr);
|
||
|
|
||
|
StrPtrLen url;
|
||
|
theStreamDataParser.GetThru(&url, '=');//consume "url="
|
||
|
url.TrimWhitespace(); // fix if it is " url =" instead of "url="
|
||
|
|
||
|
if (false == url.NumEqualIgnoreCase(sURL.Ptr, sURL.Len))
|
||
|
return; //failed to find url=
|
||
|
|
||
|
|
||
|
theStreamDataParser.GetThru(&url, ';');//consume "url=/asdlfjasdf/id=12;"
|
||
|
|
||
|
{ //get the stream id url component
|
||
|
|
||
|
StringParser theURLParser(&url);
|
||
|
while (theURLParser.GetThru(&url, '/')); //trim to the last path segment
|
||
|
}
|
||
|
|
||
|
{ // get the id value
|
||
|
StringParser theIDParser(&url);
|
||
|
if (false == theIDParser.GetThru(&url, '='))//consume "id=12;"
|
||
|
return; //failed to find '='
|
||
|
|
||
|
theIDParser.ConsumeWhitespace();
|
||
|
fTrackID = theIDParser.ConsumeInteger();
|
||
|
}
|
||
|
|
||
|
|
||
|
StrPtrLen theDataStr;
|
||
|
while ( theStreamDataParser.GetThru(&theDataStr,'=') ) //get the field name
|
||
|
{
|
||
|
theDataStr.TrimWhitespace();
|
||
|
if (theDataStr.NumEqualIgnoreCase(sSize.Ptr, sSize.Len)) // size=
|
||
|
{
|
||
|
theStreamDataParser.ConsumeWhitespace();
|
||
|
fBufferSizeBytes = theStreamDataParser.ConsumeInteger();
|
||
|
}
|
||
|
|
||
|
if (theDataStr.NumEqualIgnoreCase(sTargetTime.Ptr, sTargetTime.Len)) // target-time =
|
||
|
{
|
||
|
theStreamDataParser.ConsumeWhitespace();
|
||
|
fTargetTimeMilli = theStreamDataParser.ConsumeInteger();
|
||
|
}
|
||
|
theStreamDataParser.GetThru(&theDataStr,';'); //skip to next field
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
void RateAdapationStreamDataFields::CopyData(RateAdapationStreamDataFields* source)
|
||
|
{
|
||
|
if (NULL == source)
|
||
|
return;
|
||
|
|
||
|
fTrackID = source->GetSDPStreamID();
|
||
|
fBufferSizeBytes = source->GetBufferSizeBytes();
|
||
|
fTargetTimeMilli = source->GetTargetTimeMilliSec();
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//-----------
|
||
|
void LinkCharDataFields::ParseData( StrPtrLen &theDataStr, StringParser &theLinkCharDataParser)
|
||
|
{
|
||
|
static StrPtrLen sGBW("GBW");
|
||
|
static StrPtrLen sMBW("MBW");
|
||
|
static StrPtrLen sMTD("MTD");
|
||
|
|
||
|
if (theDataStr.NumEqualIgnoreCase(sGBW.Ptr, sGBW.Len)) // GBW=
|
||
|
{
|
||
|
theLinkCharDataParser.ConsumeWhitespace();
|
||
|
fGuaranteedKBitsPerSec = theLinkCharDataParser.ConsumeInteger();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (theDataStr.NumEqualIgnoreCase(sMBW.Ptr, sMBW.Len)) //MBW=
|
||
|
{
|
||
|
theLinkCharDataParser.ConsumeWhitespace();
|
||
|
fMaximumKBitsPerSec = theLinkCharDataParser.ConsumeInteger();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (theDataStr.NumEqualIgnoreCase(sMTD.Ptr, sMTD.Len)) //MBW=
|
||
|
{
|
||
|
theLinkCharDataParser.ConsumeWhitespace();
|
||
|
fMaximumTransferDelayMilliSec = theLinkCharDataParser.ConsumeInteger();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void LinkCharDataFields::SetData(StrPtrLen *streamDataStr)
|
||
|
{
|
||
|
|
||
|
static StrPtrLen sURL("url");
|
||
|
|
||
|
StringParser theLinkCharDataParser(streamDataStr);
|
||
|
|
||
|
StrPtrLen url;
|
||
|
theLinkCharDataParser.GetThru(&url, '=');//consume "url="
|
||
|
url.TrimWhitespace(); // fix if it is " url =" instead of "url="
|
||
|
|
||
|
if (false == url.NumEqualIgnoreCase(sURL.Ptr, sURL.Len))
|
||
|
return; //failed to find url=
|
||
|
|
||
|
theLinkCharDataParser.ConsumeUntil(&url, ';');//consume "url=/asdlfjasdf;"
|
||
|
if (!theLinkCharDataParser.Expect(';'))
|
||
|
return; // no parameters
|
||
|
|
||
|
url.TrimWhitespace();
|
||
|
fURL.Set(url.GetAsCString());
|
||
|
|
||
|
StrPtrLen theDataStr;
|
||
|
while ( theLinkCharDataParser.GetThru(&theDataStr,'=') ) //get the field name
|
||
|
{
|
||
|
theDataStr.TrimWhitespace();
|
||
|
this->ParseData(theDataStr,theLinkCharDataParser);
|
||
|
|
||
|
theLinkCharDataParser.GetThru(&theDataStr,';'); //skip to next field
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
void LinkCharDataFields::CopyData(LinkCharDataFields* source)
|
||
|
{
|
||
|
if (NULL == source)
|
||
|
return;
|
||
|
|
||
|
fURL.Set(source->GetURL()->GetAsCString());
|
||
|
fGuaranteedKBitsPerSec = source->GetGKbits();
|
||
|
fMaximumKBitsPerSec = source->GetMaxKBits();
|
||
|
fMaximumTransferDelayMilliSec = source->GetMaxDelayMilliSecs();
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//--------
|
||
|
QTSSAttrInfoDict::AttrInfo RTSPRequest3GPP::sAttributes[] =
|
||
|
{ /*fields: fAttrName, fFuncPtr, fAttrDataType, fAttrPermission */
|
||
|
/* 0 */ { "qtss3GPPRequestEnabled", NULL, qtssAttrDataTypeBool16, qtssAttrModeRead | qtssAttrModeWrite | qtssAttrModePreempSafe },
|
||
|
/* 1 */ { "qtss3GPPRequestRateAdaptationStreamData", NULL, qtssAttrDataTypeCharArray, qtssAttrModeRead | qtssAttrModePreempSafe }
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
void RTSPRequest3GPP::Initialize()
|
||
|
{
|
||
|
for (UInt32 x = 0; x < qtss3GPPRequestNumParams; x++)
|
||
|
QTSSDictionaryMap::GetMap(QTSSDictionaryMap::k3GPPRequestDictIndex)->
|
||
|
SetAttribute(x, sAttributes[x].fAttrName, sAttributes[x].fFuncPtr,
|
||
|
sAttributes[x].fAttrDataType, sAttributes[x].fAttrPermission);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
RTSPRequest3GPP::RTSPRequest3GPP(Bool16 enabled)
|
||
|
: QTSSDictionary(QTSSDictionaryMap::GetMap(QTSSDictionaryMap::k3GPPRequestDictIndex)),
|
||
|
fEnabled (enabled),fIs3GPP(false), fHasRateAdaptation(false), fHasLinkChar(false)
|
||
|
{
|
||
|
this->SetVal(qtss3GPPRequestEnabled, &fEnabled, sizeof(fEnabled));
|
||
|
|
||
|
}
|
||
|
|
||
|
QTSS_Error RTSPRequest3GPP::ParseAdpationHeader(QTSSDictionary* headerDictionaryPtr)
|
||
|
{
|
||
|
|
||
|
if (NULL == headerDictionaryPtr)
|
||
|
{ Assert(0);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!fEnabled)
|
||
|
return QTSS_NoErr;
|
||
|
|
||
|
StringParser theRateAdaptHeaderParser(headerDictionaryPtr->GetValue(qtss3GPPAdaptationHeader));
|
||
|
|
||
|
if (theRateAdaptHeaderParser.GetDataRemaining() == 0)
|
||
|
return -1;
|
||
|
|
||
|
fIs3GPP = true;
|
||
|
fHasRateAdaptation = true;
|
||
|
|
||
|
StrPtrLen theStreamData;
|
||
|
UInt32 numValueIndex = 0;
|
||
|
while (theRateAdaptHeaderParser.GetDataRemaining() != 0)
|
||
|
{
|
||
|
theRateAdaptHeaderParser.GetThru(&theStreamData, ',');
|
||
|
theStreamData.TrimWhitespace();
|
||
|
(void) this->SetValuePtr(qtss3GPPRequestRateAdaptationStreamData,theStreamData.Ptr, theStreamData.Len, QTSSDictionary::kDontObeyReadOnly);
|
||
|
numValueIndex++;
|
||
|
}
|
||
|
|
||
|
//this->ParseAdpationHeaderTest();
|
||
|
|
||
|
return QTSS_NoErr;
|
||
|
}
|
||
|
|
||
|
void RTSPRequest3GPP::ParseAdpationHeaderTest()
|
||
|
{
|
||
|
StrPtrLen dataStr;
|
||
|
UInt32 numValues = this->GetNumValues(qtss3GPPRequestRateAdaptationStreamData);
|
||
|
qtss_printf("RTSPRequest3GPP::ParseAdpationHeaderTest numValues =%lu\n", numValues);
|
||
|
|
||
|
for (;numValues > 0; numValues --)
|
||
|
{
|
||
|
|
||
|
if(0 != this->GetValuePtr(qtss3GPPRequestRateAdaptationStreamData, numValues - 1, (void**) &dataStr.Ptr, &dataStr.Len, true))
|
||
|
qtss_printf("RTSPRequest3GPP::ParseAdpationHeaderTest err GetValuePtr(qtss3GPPRequestRateAdaptationStreamData\n");
|
||
|
|
||
|
dataStr.PrintStr("RTSPRequest3GPP::ParseAdpationHeaderTest qtss3GPPRequestRateAdaptationStreamData=[","]\n");
|
||
|
RateAdapationStreamDataFields fieldsParser;
|
||
|
fieldsParser.SetData(&dataStr);
|
||
|
fieldsParser.PrintData(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
QTSS_Error RTSPRequest3GPP::ParseLinkCharHeader(QTSSDictionary* headerDictionaryPtr)
|
||
|
{
|
||
|
|
||
|
if (NULL == headerDictionaryPtr)
|
||
|
{ Assert(0);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
StrPtrLen* theLinkCharStr = headerDictionaryPtr->GetValue(qtss3GPPLinkCharHeader);
|
||
|
if (theLinkCharStr == NULL)
|
||
|
return -1;
|
||
|
|
||
|
if (theLinkCharStr->Len == 0)
|
||
|
return -1;
|
||
|
|
||
|
fIs3GPP = true;
|
||
|
fHasLinkChar = true;
|
||
|
|
||
|
//this->ParseLinkCharHeaderTest(headerDictionaryPtr);
|
||
|
|
||
|
return QTSS_NoErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
void RTSPRequest3GPP::ParseLinkCharHeaderTest(QTSSDictionary* headerDictionaryPtr)
|
||
|
{
|
||
|
StrPtrLen dataStr;
|
||
|
UInt32 numValues = headerDictionaryPtr->GetNumValues(qtss3GPPLinkCharHeader);
|
||
|
qtss_printf("RTSPRequest3GPP::ParseLinkCharHeaderTest qtss3GPPLinkCharHeader numValues =%lu\n", numValues); //should be 1
|
||
|
|
||
|
for (;numValues > 0; numValues --)
|
||
|
{
|
||
|
|
||
|
if(0 != headerDictionaryPtr->GetValuePtr(qtss3GPPLinkCharHeader, numValues - 1, (void**) &dataStr.Ptr, &dataStr.Len, true))
|
||
|
qtss_printf("RTSPRequest3GPP::ParseLinkCharHeaderTest err GetValuePtr(qtss3GPPLinkCharHeader\n");
|
||
|
|
||
|
dataStr.PrintStr("RTSPRequest3GPP::ParseLinkCharHeaderTest qtss3GPPLinkCharHeader=[","]\n");
|
||
|
LinkCharDataFields fieldsParser;
|
||
|
fieldsParser.SetData(&dataStr);
|
||
|
fieldsParser.PrintData(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|