Example #1
0
void RTSPRequest::ParseModeSubHeader(StrPtrLen* inModeSubHeader)
{
    static StrPtrLen sModeSubHeader("mode");
    static StrPtrLen sReceiveMode("receive");
    static StrPtrLen sRecordMode("record");
    StringParser theSubHeaderParser(inModeSubHeader);

    // Skip over to the first port
    StrPtrLen theFirstBit;
    theSubHeaderParser.GetThru(&theFirstBit, '=');
    theFirstBit.TrimWhitespace();
    
    // Make sure this is the client port subheader
    if (theFirstBit.EqualIgnoreCase(sModeSubHeader)) do
    {
        theSubHeaderParser.ConsumeWhitespace();

        StrPtrLen theMode;
		theSubHeaderParser.ConsumeWord(&theMode);
		
		if ( theMode.EqualIgnoreCase(sReceiveMode) || theMode.EqualIgnoreCase(sRecordMode) )
		{	fTransportMode = qtssRTPTransportModeRecord;
			break;
		}
        
    } while (false);
    
}
Example #2
0
void RTSPRequest::ParseAddrSubHeader(StrPtrLen* inSubHeader, StrPtrLen* inHeaderName, UInt32* outAddr)
{
    if (!inSubHeader || !inHeaderName || !outAddr)
        return;
        
    StringParser theSubHeaderParser(inSubHeader);

    // Skip over to the value
    StrPtrLen theFirstBit;
    theSubHeaderParser.GetThru(&theFirstBit, '=');
    theFirstBit.TrimWhitespace();

    // First make sure this is the proper subheader
    if (!theFirstBit.EqualIgnoreCase(*inHeaderName))
        return;
    
    //Find the IP address
    theSubHeaderParser.ConsumeUntilDigit();

    //Set the addr string param.
    StrPtrLen theAddr(theSubHeaderParser.GetCurrentPosition(), theSubHeaderParser.GetDataRemaining());
    
    //Convert the string to a UInt32 IP address
    char theTerminator = theAddr.Ptr[theAddr.Len];
    theAddr.Ptr[theAddr.Len] = '\0';
    
    *outAddr = SocketUtils::ConvertStringToAddr(theAddr.Ptr);
    
    theAddr.Ptr[theAddr.Len] = theTerminator;
    
}
Example #3
0
void  RTSPRequest::ParseRetransmitHeader()
{
    StringParser theRetransmitParser(fHeaderDictionary.GetValue(qtssXRetransmitHeader));
    StrPtrLen theProtName;
    Bool16 foundRetransmitProt = false;
            
    do
    {
        theRetransmitParser.ConsumeWhitespace();
        theRetransmitParser.ConsumeWord(&theProtName);
        theProtName.TrimTrailingWhitespace();
        foundRetransmitProt = theProtName.EqualIgnoreCase(RTSPProtocol::GetRetransmitProtocolName());
    }
    while ( (!foundRetransmitProt) &&
            (theRetransmitParser.GetThru(NULL, ',')) );

    if (!foundRetransmitProt)
        return;
    
    //
    // We are using Reliable RTP as the transport for this stream,
    // but if there was a previous transport header that indicated TCP,
    // do not set the transport to be reliable UDP
    if (fTransportType == qtssRTPTransportTypeUDP)
        fTransportType = qtssRTPTransportTypeReliableUDP;

    StrPtrLen theProtArg;
    while (theRetransmitParser.GetThru(&theProtArg, '='))   
    {
        //
        // Parse out params
        static const StrPtrLen kWindow("window");
         
        theProtArg.TrimWhitespace();
        if (theProtArg.EqualIgnoreCase(kWindow))
        {
            theRetransmitParser.ConsumeWhitespace();
            fWindowSize = theRetransmitParser.ConsumeInteger(NULL);
            
            // Save out the window size argument as a string so we
            // can easily put it into the response
            // (we never muck with this header)
            fWindowSizeStr.Ptr = theProtArg.Ptr;
            fWindowSizeStr.Len = theRetransmitParser.GetCurrentPosition() - theProtArg.Ptr;
        }
            
        theRetransmitParser.GetThru(NULL, ';'); //Skip past ';'
    }
}
Example #4
0
void RTSPRequest::ParseTimeToLiveSubHeader(StrPtrLen* inTimeToLiveSubHeader)
{
    static StrPtrLen sTimeToLiveSubHeader("ttl");

    StringParser theSubHeaderParser(inTimeToLiveSubHeader);

    // Skip over to the first part
    StrPtrLen theFirstBit;
    theSubHeaderParser.GetThru(&theFirstBit, '=');
    theFirstBit.TrimWhitespace();
    // Make sure this is the ttl subheader
    if (!theFirstBit.EqualIgnoreCase(sTimeToLiveSubHeader))
        return;
    
    // Parse out the time to live...
    theSubHeaderParser.ConsumeWhitespace();
    fTtl = (UInt16)theSubHeaderParser.ConsumeInteger(NULL);
}
Example #5
0
void  RTSPRequest::ParsePrebufferHeader()
{
    StringParser thePrebufferParser(fHeaderDictionary.GetValue(qtssXPreBufferHeader));

    StrPtrLen thePrebufferArg;
    while (thePrebufferParser.GetThru(&thePrebufferArg, '='))   
    {
        thePrebufferArg.TrimWhitespace();

        static const StrPtrLen kMaxTimeSubHeader("maxtime");
        if (thePrebufferArg.EqualIgnoreCase(kMaxTimeSubHeader))
        {        
            thePrebufferParser.ConsumeWhitespace();
            fPrebufferAmt = thePrebufferParser.ConsumeFloat();
        } 
            
        thePrebufferParser.GetThru(NULL, ';'); //Skip past ';'
    
    }
}
Example #6
0
void RTSPRequest::ParseClientPortSubHeader(StrPtrLen* inClientPortSubHeader)
{
    static StrPtrLen sClientPortSubHeader("client_port");
    static StrPtrLen sErrorMessage("Received invalid client_port field: ");
    StringParser theSubHeaderParser(inClientPortSubHeader);

    // Skip over to the first port
    StrPtrLen theFirstBit;
    theSubHeaderParser.GetThru(&theFirstBit, '=');
    theFirstBit.TrimWhitespace();
    
    // Make sure this is the client port subheader
    if (!theFirstBit.EqualIgnoreCase(sClientPortSubHeader))
        return;

    // Store the two client ports as integers
    theSubHeaderParser.ConsumeWhitespace();
    fClientPortA = (UInt16)theSubHeaderParser.ConsumeInteger(NULL);
    theSubHeaderParser.GetThru(NULL,'-');
    theSubHeaderParser.ConsumeWhitespace();
    fClientPortB = (UInt16)theSubHeaderParser.ConsumeInteger(NULL);
    if (fClientPortB != fClientPortA + 1) // an error in the port values
    {
        // The following to setup and log the error as a message level 2.
        StrPtrLen *userAgentPtr = fHeaderDictionary.GetValue(qtssUserAgentHeader);
        ResizeableStringFormatter errorPortMessage;
        errorPortMessage.Put(sErrorMessage);
        if (userAgentPtr != NULL)
            errorPortMessage.Put(*userAgentPtr);
        errorPortMessage.PutSpace();
        errorPortMessage.Put(*inClientPortSubHeader);
        errorPortMessage.PutTerminator(); 
        QTSSModuleUtils::LogError(qtssMessageVerbosity,qtssMsgNoMessage, 0, errorPortMessage.GetBufPtr(), NULL);
        
        
        //fix the rtcp port and hope it works.
        fClientPortB = fClientPortA + 1;
    }
}
Example #7
0
void RTSPRequest::ParseTransportHeader()
{
	static char* sRTPAVPTransportStr = "RTP/AVP";
	
    StringParser theTransParser(fHeaderDictionary.GetValue(qtssTransportHeader));
    
    //transport header from client: Transport: RTP/AVP;unicast;client_port=5000-5001\r\n
    //                              Transport: RTP/AVP;multicast;ttl=15;destination=229.41.244.93;client_port=5000-5002\r\n
    //                              Transport: RTP/AVP/TCP;unicast\r\n
    
    //
    // A client may send multiple transports to the server, comma separated.
	// In this case, the server should just pick one and use that. 
	
	while (theTransParser.GetDataRemaining() > 0)
	{	
	    (void)theTransParser.ConsumeWhitespace();
        (void)theTransParser.ConsumeUntil(&fFirstTransport, ',');
    
		if (fFirstTransport.NumEqualIgnoreCase(sRTPAVPTransportStr, ::strlen(sRTPAVPTransportStr)))
			break;

		if (theTransParser.PeekFast() == ',')
			theTransParser.Expect(',');
	}
	
    StringParser theFirstTransportParser(&fFirstTransport);
    
    StrPtrLen theTransportSubHeader;
    (void)theFirstTransportParser.GetThru(&theTransportSubHeader, ';');    

    while (theTransportSubHeader.Len > 0)
    {
       
        // Extract the relevent information from the relevent subheader.
        // So far we care about 3 sub-headers

        if (!this->ParseNetworkModeSubHeader(&theTransportSubHeader))
        {
            theTransportSubHeader.TrimWhitespace();

            switch (*theTransportSubHeader.Ptr)
            {
				case 'r':	// rtp/avp/??? Is this tcp or udp?
                case 'R':   // RTP/AVP/??? Is this TCP or UDP?
                {   
                    if ( theTransportSubHeader.EqualIgnoreCase("RTP/AVP/TCP") )
                        fTransportType = qtssRTPTransportTypeTCP;
                    break;
                }
                case 'c':   //client_port sub-header
                case 'C':   //client_port sub-header
                {
                    this->ParseClientPortSubHeader(&theTransportSubHeader);
                    break;
                }
                case 'd':   //destination sub-header
                case 'D':   //destination sub-header
                {
                    static StrPtrLen sDestinationSubHeader("destination");
                    
                    //Parse the header, extract the destination address
                    this->ParseAddrSubHeader(&theTransportSubHeader, &sDestinationSubHeader, &fDestinationAddr);
                    break;
                }
                case 's':   //source sub-header
                case 'S':   //source sub-header
                {
                    //Same as above code
                    static StrPtrLen sSourceSubHeader("source");
                    this->ParseAddrSubHeader(&theTransportSubHeader, &sSourceSubHeader, &fSourceAddr);
                    break;
                }
                case 't':   //time-to-live sub-header
                case 'T':   //time-to-live sub-header
                {
                    this->ParseTimeToLiveSubHeader(&theTransportSubHeader);
                    break;
                }
                case 'm':   //mode sub-header
                case 'M':   //mode sub-header
                {
                    this->ParseModeSubHeader(&theTransportSubHeader);
                    break;
                }
            }
        }
        
        // Move onto the next parameter
        (void)theFirstTransportParser.GetThru(&theTransportSubHeader, ';');
    }
}
Example #8
0
//throws eHTTPNoMoreData and eHTTPOutOfBuffer
QTSS_Error RTSPRequest::ParseHeaders(StringParser& parser)
{
    StrPtrLen theKeyWord;
    Bool16 isStreamOK;
    
    //Repeat until we get a \r\n\r\n, which signals the end of the headers
    
    while ((parser.PeekFast() != '\r') && (parser.PeekFast() != '\n')) 
    {
        //First get the header identifier
        
        isStreamOK = parser.GetThru(&theKeyWord, ':');
        if (!isStreamOK)
            return QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgNoColonAfterHeader, this->GetValue(qtssRTSPReqFullRequest));
                            
         theKeyWord.TrimWhitespace();
        
        //Look up the proper header enumeration based on the header string.
        //Use the enumeration to look up the dictionary ID of this header,
        //and set that dictionary attribute to be whatever is in the body of the header
        
        UInt32 theHeader = RTSPProtocol::GetRequestHeader(theKeyWord);
        StrPtrLen theHeaderVal;
		parser.ConsumeUntil(&theHeaderVal, StringParser::sEOLMask);
	
		StrPtrLen theEOL;
		if ((parser.PeekFast() == '\r') || (parser.PeekFast() == '\n'))
		{
			isStreamOK = true;
			parser.ConsumeEOL(&theEOL);
		}
		else
			isStreamOK = false;
			
		while((parser.PeekFast() == ' ') || (parser.PeekFast() == '\t'))
		{
			theHeaderVal.Len += theEOL.Len;
			StrPtrLen temp;
			parser.ConsumeUntil(&temp, StringParser::sEOLMask);
			theHeaderVal.Len += temp.Len;
			
			if ((parser.PeekFast() == '\r') || (parser.PeekFast() == '\n'))
			{
				isStreamOK = true;
				parser.ConsumeEOL(&theEOL);
			}
			else
				isStreamOK = false;			
		}

        // If this is an unknown header, ignore it. Otherwise, set the proper
        // dictionary attribute
        if (theHeader != qtssIllegalHeader)
        {
            Assert(theHeader < qtssNumHeaders);
            theHeaderVal.TrimWhitespace();
            fHeaderDictionary.SetVal(theHeader, &theHeaderVal);
        }
        if (!isStreamOK)
            return QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgNoEOLAfterHeader);
        
        //some headers require some special processing. If this code begins
        //to get out of control, we made need to come up with a function pointer table
        switch (theHeader)
        {
            case qtssSessionHeader:             ParseSessionHeader(); break;
            case qtssTransportHeader:           ParseTransportHeader(); break;
            case qtssRangeHeader:               ParseRangeHeader();     break;
            case qtssIfModifiedSinceHeader:     ParseIfModSinceHeader();break;
            case qtssXRetransmitHeader:         ParseRetransmitHeader();break;
            case qtssContentLengthHeader:       ParseContentLengthHeader();break;
            case qtssSpeedHeader:               ParseSpeedHeader();     break;
            case qtssXTransportOptionsHeader:   ParseTransportOptionsHeader();break;
            case qtssXPreBufferHeader:          ParsePrebufferHeader();break;
			case qtssXDynamicRateHeader:		ParseDynamicRateHeader(); break;
			case qtssXRandomDataSizeHeader:		ParseRandomDataSizeHeader(); break;
			case qtss3GPPAdaptationHeader:      fRequest3GPP.ParseAdpationHeader(&fHeaderDictionary); break;
			case qtss3GPPLinkCharHeader:        fRequest3GPP.ParseLinkCharHeader(&fHeaderDictionary); break;
			case qtssBandwidthHeader:           ParseBandwidthHeader(); break;
            default:    break;
        }
    }

    // Tell the session what the request body length is for this request
    // so that it can prevent people from reading past the end of the request.
    StrPtrLen* theContentLengthBody = fHeaderDictionary.GetValue(qtssContentLengthHeader);
    if (theContentLengthBody->Len > 0)
    {
        StringParser theHeaderParser(fHeaderDictionary.GetValue(qtssContentLengthHeader));
        theHeaderParser.ConsumeWhitespace();
        this->GetSession()->SetRequestBodyLength(theHeaderParser.ConsumeInteger(NULL));
    }
    
    isStreamOK = parser.ExpectEOL();
    Assert(isStreamOK);
    return QTSS_NoErr;
}