Beispiel #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);
    
}
Beispiel #2
0
void HTTPRequest::SetKeepAlive(StrPtrLen *keepAliveValue)
{
    if ( sCloseString.EqualIgnoreCase(keepAliveValue->Ptr, keepAliveValue->Len) )
            fRequestKeepAlive = sFalse;
    else
        {
            Assert( sKeepAliveString.EqualIgnoreCase(keepAliveValue->Ptr, keepAliveValue->Len) );
            fRequestKeepAlive = sTrue;
        }
}
Beispiel #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 ';'
    }
}
Beispiel #4
0
QTSS_RTSPHeader RTSPProtocol::GetRequestHeader(const StrPtrLen &inHeaderStr)
{
    if (inHeaderStr.Len == 0)
        return qtssIllegalHeader;
    
    QTSS_RTSPHeader theHeader = qtssIllegalHeader;
    
    //chances are this is one of our selected "VIP" headers. so check for this.
    switch(*inHeaderStr.Ptr)
    {
        case 'C':   case 'c':   theHeader = qtssCSeqHeader;         break;
        case 'S':   case 's':   theHeader = qtssSessionHeader;      break;
        case 'U':   case 'u':   theHeader = qtssUserAgentHeader;    break;
        case 'A':   case 'a':   theHeader = qtssAcceptHeader;       break;
        case 'T':   case 't':   theHeader = qtssTransportHeader;    break;
        case 'R':   case 'r':   theHeader = qtssRangeHeader;        break;
        case 'X':   case 'x':   theHeader = qtssExtensionHeaders;   break;
    }
    
    //
    // Check to see whether this is one of our extension headers. These
    // are very likely to appear in requests.
    if (theHeader == qtssExtensionHeaders)
    {
        for (SInt32 y = qtssExtensionHeaders; y < qtssNumHeaders; y++)
        {
            if (inHeaderStr.EqualIgnoreCase(sHeaders[y].Ptr, sHeaders[y].Len))
                return y;
        }
    }
    
    //
    // It's not one of our extension headers, check to see if this is one of
    // our normal VIP headers
    if ((theHeader != qtssIllegalHeader) &&
        (inHeaderStr.EqualIgnoreCase(sHeaders[theHeader].Ptr, sHeaders[theHeader].Len)))
        return theHeader;

    //
    //If this isn't one of our VIP headers, go through the remaining request headers, trying
    //to find the right one.
    for (SInt32 x = qtssNumVIPHeaders; x < qtssNumHeaders; x++)
    {
        if (inHeaderStr.EqualIgnoreCase(sHeaders[x].Ptr, sHeaders[x].Len))
            return x;
    }
    return qtssIllegalHeader;
}
Beispiel #5
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;
    
}
Beispiel #6
0
QTSS_RTSPMethod
RTSPProtocol::GetMethod(const StrPtrLen &inMethodStr)
{
    //chances are this is one of our selected "VIP" methods. so check for this.
    QTSS_RTSPMethod theMethod = qtssIllegalMethod;
    
    switch(*inMethodStr.Ptr)
    {
        case 'S':   case 's':   theMethod = qtssSetupMethod;    break;
        case 'D':   case 'd':   theMethod = qtssDescribeMethod; break;
        case 'T':   case 't':   theMethod = qtssTeardownMethod; break;
        case 'O':   case 'o':   theMethod = qtssOptionsMethod;  break;
        case 'A':   case 'a':   theMethod = qtssAnnounceMethod; break;
    }

    if ((theMethod != qtssIllegalMethod) &&
        (inMethodStr.EqualIgnoreCase(sMethods[theMethod].Ptr, sMethods[theMethod].Len)))
        return theMethod;

    for (SInt32 x = qtssNumVIPMethods; x < qtssIllegalMethod; x++)
        if (inMethodStr.EqualIgnoreCase(sMethods[x].Ptr, sMethods[x].Len))
            return x;
    return qtssIllegalMethod;
}
Beispiel #7
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);
}
Beispiel #8
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 ';'
    
    }
}
Beispiel #9
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;
    }
}
Beispiel #10
0
QTSS_Error QTSSDataConverter::StringToValue(    char* inValueAsString,
        QTSS_AttrDataType inType,
        void* ioBuffer,
        UInt32* ioBufSize)
{
    UInt32 theBufSize = 0;
    char* theFormat = NULL;

    if ( inValueAsString == NULL || ioBufSize == NULL)
        return QTSS_BadArgument;

    if ( inType == qtssAttrDataTypeCharArray )
    {
        //
        // If this data type is a string, copy the string into
        // the destination buffer
        UInt32 theLen = ::strlen(inValueAsString);

        //
        // First check to see if the destination is big enough
        if ((ioBuffer == NULL) || (*ioBufSize < theLen))
        {
            *ioBufSize = theLen;
            return QTSS_NotEnoughSpace;
        }

        //
        // Do the string copy. Use memcpy for speed.
        ::memcpy(ioBuffer, inValueAsString, theLen);
        *ioBufSize = theLen;
        return QTSS_NoErr;
    }

    if (inType == qtssAttrDataTypeBool16)
    {
        //
        // The text "enabled" means true, anything else means false
        if (*ioBufSize < sizeof(Bool16))
        {
            *ioBufSize = sizeof(Bool16);
            return QTSS_NotEnoughSpace;
        }

        Bool16* it = (Bool16*)ioBuffer;
        StrPtrLen theValuePtr(inValueAsString);
        if (kEnabledStr.EqualIgnoreCase(inValueAsString, ::strlen(inValueAsString)))
            *it = true;
        else
            *it = false;

        *ioBufSize = sizeof(Bool16);
        return QTSS_NoErr;
    }

    //
    // If this is another type, format the string into that type
    switch ( inType )
    {
    case qtssAttrDataTypeUInt16:
    {
        theBufSize = sizeof(UInt16);
        theFormat = "%hu";
    }
    break;

    case qtssAttrDataTypeSInt16:
    {
        theBufSize = sizeof(SInt16);
        theFormat = "%hd";
    }
    break;

    case qtssAttrDataTypeSInt32:
    {
        theBufSize = sizeof(SInt32);
        theFormat = "%d";
    }
    break;

    case qtssAttrDataTypeUInt32:
    {
        theBufSize = sizeof(UInt32);
        theFormat = "%u";
    }
    break;

    case qtssAttrDataTypeSInt64:
    {
        theBufSize = sizeof(SInt64);
        theFormat = "%" _64BITARG_ "d";
    }
    break;

    case qtssAttrDataTypeUInt64:
    {
        theBufSize = sizeof(UInt64);
        theFormat = "%" _64BITARG_ "u";
    }
    break;

    case qtssAttrDataTypeFloat32:
    {
        theBufSize = sizeof(Float32);
        theFormat = "%f";
    }
    break;

    case qtssAttrDataTypeFloat64:
    {
        theBufSize = sizeof(Float64);
        theFormat = "%f";
    }
    break;

    case qtssAttrDataTypeTimeVal:
    {
        theBufSize = sizeof(SInt64);
        theFormat = "%" _64BITARG_ "d";
    }
    break;

    default:
        return ConvertCHexStringToBytes(inValueAsString,ioBuffer,ioBufSize);
    }

    if (( ioBuffer == NULL) || (*ioBufSize < theBufSize ))
    {
        *ioBufSize = theBufSize;
        return QTSS_NotEnoughSpace;
    }
    *ioBufSize = theBufSize;
    ::sscanf(inValueAsString, theFormat, ioBuffer);

    return QTSS_NoErr;
}
Bool16 IsHomeDirURL(StrPtrLen& theUrl)
{
    StrPtrLen token = theUrl;
    token.Len = 2;
    return token.EqualIgnoreCase(StrPtrLen("/~"));
}
// This determines if a URL in an HTTP request is actually
// a server admin request.
Bool16 IsAdminURL(StrPtrLen& theUrl)
{
    StrPtrLen token = theUrl;
    token.Len = 15;
    return token.EqualIgnoreCase(StrPtrLen("/modules/admin/"));
}
// This determines if an incoming request is an HTTP GET
// request.
Bool16 IsHTTPGet(StrPtrLen& theRequest)
{
    StrPtrLen token = theRequest;
    token.Len = 3;
    return token.EqualIgnoreCase(StrPtrLen("GET"));
}
Beispiel #14
0
UInt32 ReplaceSessionAndTransportHeaders(StrPtrLen* inResponse, iovec* outNewResponse, StrPtrLen* inNewSessionID,
                                                        StrPtrLen* inNewTransportHeader, UInt32* outNewResponseLen)
{
    static StrPtrLen sTransportHeader("Transport");
    static StrPtrLen sSessionHeader("Session");

    StringParser reqParser(inResponse);
    StrPtrLen theHeaderName;

    UInt32 curVecIndex = 0;
    outNewResponse[0].iov_base = inResponse->Ptr;
    *outNewResponseLen = 0;
    
    while (reqParser.GetDataRemaining() > 0)
    {
        reqParser.ConsumeWord(&theHeaderName);

        if (theHeaderName.EqualIgnoreCase(sTransportHeader.Ptr, sTransportHeader.Len))
        {
            //
            // Mark off the length of the last section of the header
			outNewResponse[curVecIndex].iov_len = (UInt32) ((PointerSizedUInt) theHeaderName.Ptr) - ((PointerSizedUInt) outNewResponse[curVecIndex].iov_base );
            *outNewResponseLen += outNewResponse[curVecIndex].iov_len;
            
            //
            // Insert the new Transport header
            outNewResponse[curVecIndex+1].iov_base = inNewTransportHeader->Ptr;
            outNewResponse[curVecIndex+1].iov_len = inNewTransportHeader->Len;
            *outNewResponseLen += inNewTransportHeader->Len;
            
            //
            // Move onto the next iovec
            curVecIndex+=2;
            
            //
            // Mark the start of the next section
            reqParser.GetThruEOL(NULL);
            outNewResponse[curVecIndex].iov_base = reqParser.GetCurrentPosition();
        }
        else if (theHeaderName.EqualIgnoreCase(sSessionHeader.Ptr, sSessionHeader.Len))
        {
            reqParser.ConsumeLength(NULL, 2); //skip over ": "
            
            //
            // Mark off the length of the last section of the header
            outNewResponse[curVecIndex].iov_len = (UInt32) ((PointerSizedUInt) reqParser.GetCurrentPosition()) - ((PointerSizedUInt) outNewResponse[curVecIndex].iov_base);
            *outNewResponseLen += outNewResponse[curVecIndex].iov_len;
            
            //
            // Insert new session ID
            outNewResponse[curVecIndex+1].iov_base = inNewSessionID->Ptr;
            outNewResponse[curVecIndex+1].iov_len = inNewSessionID->Len;
            *outNewResponseLen += inNewSessionID->Len;
            
            //
            // Move onto the next empty vec
            curVecIndex+=2;
            
            //
            // Move past the session ID. Be careful, there may be a ';' that we need to look for
            
            StrPtrLen theSessionID;
            reqParser.GetThruEOL(&theSessionID);
            
            outNewResponse[curVecIndex].iov_base = &theSessionID.Ptr[theSessionID.Len];
    
            while (theSessionID.Ptr < outNewResponse[curVecIndex].iov_base)
            {
                if (*theSessionID.Ptr == ';')
                {
                    outNewResponse[curVecIndex].iov_base = theSessionID.Ptr;
                    break;
                }
                theSessionID.Ptr++;
            }       
        }
        else
            reqParser.GetThruEOL(NULL);
    }
    
    //
    // Finish off the vec by marking the len of the last section
    outNewResponse[curVecIndex].iov_len = (UInt32) ((PointerSizedUInt) reqParser.GetCurrentPosition()) -  ((PointerSizedUInt) outNewResponse[curVecIndex].iov_base );

    //
    // And finish off the total length
    *outNewResponseLen += outNewResponse[curVecIndex].iov_len;

    //
    // Return the number of vecs written
    return curVecIndex+1;
}
Beispiel #15
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, ';');
    }
}