//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; }
int RtspRequest::ParseRtspPackage(char Buf[], int Size) //bool bReq { int ret = 0; StringArray_t saLine; StringPair_t spHeader; string Delim=CRLF; string sRequest(Buf, Size); U32 theHeader = 0; StringUtil::Trim(sRequest); StringUtil::Split(sRequest, Delim, saLine); //Request Line if(strncmp(saLine[0].c_str(), RTSPProtocol::GetVersionString(RTSPProtocol::k10Version).Ptr, RTSPProtocol::GetVersionString(RTSPProtocol::k10Version).Len) != 0) //bReq { m_bIsRequest = true; ret = ParseRequestLine(saLine[0]); if(ret < 0) { return -1; } } else { m_bIsRequest = false; ret = ParseStatusLine(saLine[0]); if(ret < 0) { return -1; } } //Parse Header for(int i=1; i<saLine.size(); i++) { StringUtil::Split(saLine[i], ':', spHeader); theHeader = RTSPProtocol::GetRequestHeader(StrPtrLen((char*)spHeader.first.c_str())); if(qtssIllegalHeader != theHeader) { StringUtil::Trim(spHeader.second); m_HeaderDict[theHeader] = spHeader.second; } //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 qtssCSeqHeader: ParseCSeqHeader(); break; case qtssTransportHeader: ParseTransportHeader(); break; case qtssRangeHeader: ParseRangeHeader(); break; case qtssContentLengthHeader: ParseContentLengthHeader();break; case qtssSpeedHeader: ParseSpeedHeader(); break; case qtssScaleHeader: ParseScaleHeader(); break; case qtssRequireHeader: ParseRequireHeader(); break; case ngodNoticeHeader: ParseNoticeHeader(); break; case ngodOnDemandSessionIdHeader: ParseOnDemandSessionIdHeader(); break; case ngodReasonHeader: ParseReasonHeader(); break; case ngodSessionGroupHeader: ParseSessionGroupHeader(); break; default: break; } } return 0; }