/* * * @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: RelaySDPSourceInfo.cpp Contains: Implementation of object defined in .h file */ #include "RelaySDPSourceInfo.h" #include "SDPSourceInfo.h" #include "MyAssert.h" #include "StringParser.h" #include "OSMemory.h" #ifndef __Win32__ #include #endif RelaySDPSourceInfo::~RelaySDPSourceInfo() { // Not necessary anymore as the destructor of the base class will take care // of deleting all allocated memory for fOutputArray and fStreamArray /* if (fOutputArray != NULL) { for (UInt32 x = 0; x < fNumOutputs; x++) { delete [] fOutputArray[x].fPortArray; fOutputArray[x].fNumPorts = 0; } char* theOutputArray = (char*)fOutputArray; delete [] theOutputArray; } if (fStreamArray != NULL) { char* theStreamArray = (char*)fStreamArray; delete [] theStreamArray; } */ } void RelaySDPSourceInfo::Parse(StrPtrLen* inSDPData) { // These are the lines of the SDP file that we are interested in static StrPtrLen sRelayAddr("a=x-qt-relay-addr"); static StrPtrLen sRelayPort("a=x-qt-relay-port"); Assert(fOutputArray == NULL); Assert(fStreamArray == NULL); StrPtrLen sdpLine; StrPtrLen outputAddrs; StringParser trackCounter(inSDPData); UInt32 theDestIPAddr = 0; UInt16 theDestTtl = 0; // // FIRST WALK THROUGH SDP // The first walk is to count up the number of StreamInfo & OutputInfo // objects that we will need. while (true) { // grab a line trackCounter.ConsumeUntil(&sdpLine, StringParser::sEOLMask); if (sdpLine.NumEqualIgnoreCase(sRelayAddr.Ptr, sRelayAddr.Len)) { // there is a x-qt-relay-addr line, look for all IP addrs StringParser relayAddrParser(&sdpLine); relayAddrParser.ConsumeUntil(NULL, StringParser::sDigitMask); // The first IP addr on this line is the destination IP addr of the // source broadcast. theDestIPAddr = SDPSourceInfo::GetIPAddr(&relayAddrParser, ' '); relayAddrParser.ConsumeWhitespace(); // Store this position so we can later go back to it outputAddrs.Ptr = relayAddrParser.GetCurrentPosition(); outputAddrs.Len = relayAddrParser.GetDataRemaining(); StrPtrLen theTtl; while (relayAddrParser.GetDataRemaining() > 0) { relayAddrParser.ConsumeUntil(&theTtl, ' '); relayAddrParser.ConsumeWhitespace(); fNumOutputs++; } fNumOutputs--;// Don't count the ttl as an output! StringParser ttlParser(&theTtl); theDestTtl = (UInt16) ttlParser.ConsumeInteger(NULL); } // Each x=qt-relay-port line corresponds to one source stream. else if (sdpLine.NumEqualIgnoreCase(sRelayPort.Ptr, sRelayPort.Len)) fNumStreams++; //stop when we reach an empty line. if (!trackCounter.ExpectEOL()) break; } // No relay info in this file! if ((fNumStreams == 0) || (fNumOutputs == 0)) return; // x-qt-relay-port lines should always be in pairs (RTP & RTCP) if ((fNumStreams & 1) != 0) return; fNumStreams /= 2; // // CONSTRUCT fStreamInfo AND fOutputInfo ARRAYS fStreamArray = NEW StreamInfo[fNumStreams]; fOutputArray = NEW OutputInfo[fNumOutputs]; // // FILL IN ARRAYS // Filling in the output addresses is easy because the outputAddrs // StrPtrLen points right at the data we want StringParser theOutputAddrParser(&outputAddrs); for (UInt32 x = 0; x < fNumOutputs; x++) { fOutputArray[x].fDestAddr = SDPSourceInfo::GetIPAddr(&theOutputAddrParser, ' '); fOutputArray[x].fLocalAddr = INADDR_ANY; fOutputArray[x].fTimeToLive = theDestTtl; fOutputArray[x].fPortArray = NEW UInt16[fNumStreams];//Each output has one port per stream fOutputArray[x].fNumPorts = fNumStreams; ::memset(fOutputArray[x].fPortArray, 0, fNumStreams * sizeof(UInt16)); fOutputArray[x].fAlreadySetup = false; theOutputAddrParser.ConsumeWhitespace(); Assert(fOutputArray[x].fDestAddr > 0); } StringParser sdpParser(inSDPData); // Now go through and find all the port information on all the x-qt-relay-port lines for (UInt32 theStreamIndex = 0; theStreamIndex < fNumStreams; ) { sdpParser.ConsumeUntil(&sdpLine, StringParser::sEOLMask); // parse through all the x-qt-relay-port lines if (sdpLine.NumEqualIgnoreCase(sRelayPort.Ptr, sRelayPort.Len)) { // Begin parsing... find the first port on the line StringParser relayAddrParser(&sdpLine); relayAddrParser.ConsumeUntil(NULL, StringParser::sDigitMask); // The first port is the source port for this stream fStreamArray[theStreamIndex].fPort = (UInt16) relayAddrParser.ConsumeInteger(NULL); if (fStreamArray[theStreamIndex].fPort & 1) continue; //we only care about RTP ports // Fill in all the fields we can for this stream fStreamArray[theStreamIndex].fDestIPAddr = theDestIPAddr; fStreamArray[theStreamIndex].fTimeToLive = theDestTtl; fStreamArray[theStreamIndex].fTrackID = theStreamIndex + 1; // Now fill in all the output ports for this stream for (UInt32 x = 0; x < fNumOutputs; x++) { relayAddrParser.ConsumeWhitespace(); fOutputArray[x].fPortArray[theStreamIndex] = (UInt16) relayAddrParser.ConsumeInteger(NULL); } theStreamIndex++; } //stop when we reach an empty line. if (!sdpParser.ExpectEOL()) break; } }