⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsppars.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

int
RTSPParser::parseAlertValue(const char* pValue, MIMEHeader* pHeader)
{
    MIMEInputStream input(pValue, strlen(pValue));
    MIMEScanner scanner(input);
    MIMEToken nextTok;
    MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue;

    // Parse Alert number
    nextTok = scanner.nextToken(";");
    if (nextTok.hasValue())
    {
	pHeaderValue->addParameter(nextTok.value(), "");
    }

    // Parse Alert text
    nextTok = scanner.nextToken("");
    if (nextTok.hasValue())
    {
	pHeaderValue->addParameter(nextTok.value(), "");
    }

    pHeader->addHeaderValue(pHeaderValue);

    return 0;
}

/*
 * Parse header values as list of comma separated values
 */
int 
RTSPParser::defaultParseHeaderValues(const char* pValue, MIMEHeader* pHeader)
{
    MIMEInputStream input(pValue, strlen(pValue));
    MIMEScanner scanner(input);
    
    MIMEToken nextTok = scanner.nextToken(",");
    while(nextTok.hasValue())
    {
	parseHeaderValue(nextTok.value(), pHeader);
	if((nextTok.lastChar() == MIMEToken::T_EOL) ||
	   (nextTok.lastChar() == MIMEToken::T_EOF))
	    return 0;
	nextTok = scanner.nextToken(",");
    }
    return 0;
}

int
RTSPParser::parseWWWAuthenticateHeaderValues(const char* pValue, 
					     MIMEHeader* pHeader)
{
/*
 * Not needed anymore, authentication model has changed
 * 
 */
    return 0;
}

int
RTSPParser::parseDigestAuthorizationHeaderValues(const char* pValue,
						 MIMEHeader* pHeader)
{
/*
 * Not needed anymore, authentication model has changed
 * 
 */
    return 0;
}

/*
 * construct a MIMEHeader and add header values to it
 * format: 'HeaderName: option, option=value;option=value, option'
 */
MIMEHeader* 
RTSPParser::parseHeader(CHXString& str)
{
    MIMEHeader* pHeader = 0;
    MIMEInputStream input(str);
    MIMEScanner scanner(input);
    MIMEToken nextTok = scanner.nextToken(":");

    if(nextTok.hasValue())
    {
	pHeader = new MIMEHeader(nextTok.value());
	nextTok = scanner.nextToken("\n");

	if(strcasecmp(pHeader->name(), "Range") == 0)
	{
	    parseRangeValue(nextTok.value(), pHeader);
	}
	else if
	(
	    (strcasecmp(pHeader->name(), "WWW-Authenticate") == 0)
	    ||
	    (strcasecmp(pHeader->name(), "Authenticate") == 0)
	    ||
	    (strcasecmp(pHeader->name(), "Authorization") == 0)
	    ||
	    // XXX HP get the absolute redirect URL which could 
	    // contain ',' and would be treated as field separater
	    // in defaultParseHeaderValues()
	    (strcasecmp(pHeader->name(), "Location") == 0)
            ||
            (strcasecmp(pHeader->name(), "Content-base") == 0)
	)
	{
	    MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue;
	    if(pHeaderValue)
	    {
		pHeaderValue->addParameter(nextTok.value());
		pHeader->addHeaderValue(pHeaderValue);
	    }
	}
	else if((strcasecmp(pHeader->name(), "PEP-Info") == 0) ||
	        (strcasecmp(pHeader->name(), "C-PEP-Info") == 0))
	{
	    parsePEPInfoHeaderValues(nextTok.value(), pHeader);
	}
        else if(strcasecmp(pHeader->name(), "RTP-Info") == 0)
        {
            parseRTPInfoHeaderValues(nextTok.value(), pHeader);
        }
	else if(strcasecmp(pHeader->name(), "BackChannel") == 0)
	{
	    parseBackChannelValue(nextTok.value(), pHeader);
	}
	else if(strcasecmp(pHeader->name(), "Alert") == 0)
	{
	    parseAlertValue(nextTok.value(), pHeader);
	}
	else
	{
	    defaultParseHeaderValues(nextTok.value(), pHeader);
	}
    }
    return pHeader;
}

/*
 * Parse request line in format 'METHOD URL VERSION SEQ_NO'
 */
RTSPRequestMessage*
RTSPParser::parseRequestLine(CHXString& str)
{
    int majorVersion, minorVersion;
    RTSPRequestMessage* pReqMsg = 0;
    MIMEInputStream input(str);
    MIMEScanner scanner(input);

    // build message
    MIMEToken nextTok = scanner.nextToken();
    const char* pMsgName = nextTok.value();

    if(strcasecmp(pMsgName, "SETUP") == 0)
    {
	pReqMsg = new RTSPSetupMessage;
    }
    else if(strcasecmp(pMsgName, "REDIRECT") == 0)
    {
	pReqMsg = new RTSPRedirectMessage;
    }
    else if(strcasecmp(pMsgName, "PLAY") == 0)
    {
	pReqMsg = new RTSPPlayMessage;
    }
    else if(strcasecmp(pMsgName, "PAUSE") == 0)
    {
	pReqMsg = new RTSPPauseMessage;
    }
    else if(strcasecmp(pMsgName, "SET_PARAMETER") == 0)
    {
	pReqMsg = new RTSPSetParamMessage;
    }
    else if(strcasecmp(pMsgName, "GET_PARAMETER") == 0)
    {
	pReqMsg = new RTSPGetParamMessage;
    }
    else if(strcasecmp(pMsgName, "TEARDOWN") == 0)
    {
	pReqMsg = new RTSPTeardownMessage;
    }
    else if(strcasecmp(pMsgName, "DESCRIBE") == 0)
    {
	pReqMsg = new RTSPDescribeMessage;
    }
    else if(strcasecmp(pMsgName, "OPTIONS") == 0)
    {
	pReqMsg = new RTSPOptionsMessage;
    }
    else if(strcasecmp(pMsgName, "RECORD") == 0)
    {
	pReqMsg = new RTSPRecordMessage;
    }
    else if(strcasecmp(pMsgName, "ANNOUNCE") == 0)
    {
	pReqMsg = new RTSPAnnounceMessage;
    }
    else
    {
	pReqMsg = new RTSPUnknownMessage;
    }

    // get URL
    nextTok = scanner.nextToken(" ");
    pReqMsg->setURL(nextTok.value());

    // get version info
    nextTok = scanner.nextToken();
    if(parseProtocolVersion(nextTok.value(), majorVersion, minorVersion))
    {
	pReqMsg->setVersion(majorVersion, minorVersion);
    }
    else
    {
	pReqMsg->setVersion(0,0);	// indicate bad version
    }
    
    return pReqMsg;
}

/*
 * Parse response line in format 'VERSION ERR_CODE SEQ_NO ERR_MSG'
 */
RTSPResponseMessage*
RTSPParser::parseResponseLine(CHXString& str)
{
    int majorVersion, minorVersion;
    RTSPResponseMessage* pRespMsg = 0;

    MIMEInputStream input(str);
    MIMEScanner scanner(input);

    MIMEToken nextTok = scanner.nextToken();

    pRespMsg = new RTSPResponseMessage;

    if(parseProtocolVersion(nextTok.value(), 
	majorVersion, minorVersion))
    {
	pRespMsg->setVersion(majorVersion, minorVersion);
    }
    else
    {
	pRespMsg->setVersion(0,0);	// indicate bad version
    }

    // get error code
    nextTok = scanner.nextToken();
    pRespMsg->setErrorCode(nextTok.value());

    // get error message
    nextTok = scanner.nextToken("\n");
    pRespMsg->setErrorMsg(nextTok.value());

    return pRespMsg;
}

/*
 * Parse response message
 */
RTSPMessage* 
RTSPParser::parseResponse()
{
    RTSPResponseMessage* pRespMsg = 0;
    
    LISTPOSITION pos = m_msglines.GetHeadPosition();
    CHXString* pStr = (CHXString*)m_msglines.GetNext(pos);
    pRespMsg = parseResponseLine(*pStr);
    if(!pRespMsg)
	return 0;
    while(pos)
    {
	pStr = (CHXString*)m_msglines.GetNext(pos);
	MIMEHeader* pHeader = parseHeader(*pStr);
	if(pHeader)
	    pRespMsg->addHeader(pHeader);
    }
    // get sequence number
    UINT32 seqNo = 0;
    pRespMsg->getHeaderValue("CSeq", seqNo);
    pRespMsg->setSeqNo(seqNo);
    return pRespMsg;
}

/*
 * Parse request message
 */
RTSPMessage* 
RTSPParser::parseRequest()
{
    RTSPRequestMessage* pReqMsg = 0;
    
    LISTPOSITION pos = m_msglines.GetHeadPosition();
    CHXString* pStr = (CHXString*)m_msglines.GetNext(pos);
    pReqMsg = parseRequestLine(*pStr);
    if(!pReqMsg)
	return 0;
    while(pos)
    {
	pStr = (CHXString*)m_msglines.GetNext(pos);
	MIMEHeader* pHeader = parseHeader(*pStr);
	if(pHeader)
	    pReqMsg->addHeader(pHeader);
    }
    // get sequence number
    UINT32 seqNo = 0;
    pReqMsg->getHeaderValue("CSeq", seqNo);
    pReqMsg->setSeqNo(seqNo);
    return pReqMsg;
}

/*
 * Add each line in message to list m_msglines.
 * Look for two carriage returns to delimit
 * message header.
 */
UINT32 
RTSPParser::scanMessageHeader(const char* pMsg, UINT32 nMsgLen)
{
    // first, get rid of any leading whitespace and <CR><LF> chars

    const char* pCh = pMsg;
    while(*pCh == '\n' || *pCh == '\r' || *pCh == ' ' || *pCh == '\t')
    {
	pCh++;
    }
    UINT32 offset = pCh - pMsg;
    if(offset > nMsgLen)
    {
	return 0;
    }

    MIMEInputStream input(pCh, nMsgLen - offset);
    MIMEScanner scanner(input);

    MIMEToken tok;
    int gotEOL = 0;
    UINT32 scanOffset = 0;
    do
    {
	tok = scanner.nextToken("\n");
	if(tok.lastChar() == MIMEToken::T_EOL)
	{
	    if(gotEOL && !tok.hasValue())
	    {
		scanOffset = scanner.offset();
		break;
	    }
	    else
	    {
		gotEOL = 1;
	    }
	}
	else
	{
	    gotEOL = 0;
	}
	m_msglines.AddTail((void*)(new CHXString((const char*)tok.value())));
    } while(tok.lastChar() != MIMEToken::T_EOF);

    if(scanOffset == 0)
    {
	return 0;
    }
    else
    {
	return scanOffset + offset;
    }
}

/*
 * Parse message pointed to by pMsg with length nMsgLen.
 * If not a complete message, return 0, otherwise return
 * RTSPMessage pointer.
 */
RTSPMessage* 
RTSPParser::parse(const char* pMsg, UINT32& nMsgLen)
{
    RTSPMessage* pRTSPMsg = 0;
    clearMessageLines();
    INT32 msgOffset = scanMessageHeader(pMsg, nMsgLen);
    if(msgOffset > 0)
    {
	if(m_msglines.GetCount() == 0)
	{
	    nMsgLen = 0;
	    return 0;
	}
	CHXString* str = (CHXString*)m_msglines.GetHead();
	if(strncasecmp((*str), "RTSP/", 5) == 0)
	{
	    pRTSPMsg = parseResponse();
	}
	else 
	{
	    pRTSPMsg = parseRequest();
	}

	if(pRTSPMsg)
	{
	    UINT32 contentLength = 0;
	    if(pRTSPMsg->getHeaderValue("Content-length", contentLength))
	    {
		if((UINT32)msgOffset + contentLength <= (UINT32)nMsgLen)
		{
		    CHXString content(&pMsg[msgOffset], 
		    	HX_SAFEUINT(contentLength));
		    pRTSPMsg->setContent(content);
		    nMsgLen = msgOffset + contentLength;
		}
		else	// content-length not satisfied
		{
		    // XXXBAB - update nMsglen as number of bytes needed 
		    // to complete message
		    delete pRTSPMsg;
		    pRTSPMsg = 0;
		    nMsgLen = 0;
		}
	    }
	    else
	    {
		nMsgLen = msgOffset;
	    }
	}
    }
    else
    {
	nMsgLen = 0;
    }
    return pRTSPMsg;
}

/*
 * Delete contents of m_msglines
 */
void 
RTSPParser::clearMessageLines()
{
    LISTPOSITION pos = m_msglines.GetHeadPosition();
    while(pos)
    {
	CHXString* str = (CHXString*)m_msglines.GetNext(pos);
	delete str;
    }
    m_msglines.RemoveAll();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -