[hxprotocol] CR: handle ',' in URL of RTP-Info
Henry Ping ping at real.comHere is my 2nd attempt to address this issue, it's tricky given both ';'
and ',' can exist in URL and they are also valid attribute's and entry's
separators.
I'd like to check this in before 12pm tonight if no objection, so the fix
will be in tonight's daily build.
-->Henry
At 12:48 PM 7/28/2003 -0700, Tom Marshall wrote:
>On Mon, Jul 28, 2003 at 11:49:31AM -0700, Henry Ping wrote:
> > In RTP-Info header from PLAY response, ',' is allowed in URL such as the
> > port separator for cloaking("?cloakport=7070, 80, 554") but the client
> > currently only treats ',' as the field separator of control streams.
>
>This is a problem in the RTSP spec and fixing the issue is bound to be
>tricky.
>
>What happens if an url contains a semicolon? This is common in HTTP urls,
>especially for Java based servlets that maintain session state. A quick
>tcpdump shows that the Mozilla web browser sends semicolons unescaped but
>RealPlayer (8.0 for Linux) does not. I don't have another RTSP client handy
>to test with, but I think a better parser could protect us from future
>reincarnations of this same bug with third party clients. Something that
>looks for an initial "url=" after the semicolon to recognize the start of a
>new stream-url would probably be more robust.
>
>Client-side behavior parameters (cloakport, start, end, etc.) would probably
>be better encoded differently. The query should be reserved for dynamic
>content on the server. Using queries to signal client-side behavior has
>other undesirable consequences, such as caching issues. One alternative
>could be using an url fragment. Fragments are handled at the client and not
>transmitted on the wire.
>
>Coincidentally, I just had a discussion regarding encoding temporal
>parameters in URIs at the last IETF meeting. Temporal parameters differ
>from HTTP fragments because they indicate a range to be used for the PLAY
>request in RTSP so that only part of the document is not retrieved, but the
>HTTP client retrieves the entire document. There may be enough interest in
>this issue to begin discussion in the IETF for updating the URI spec to
>include an official syntax for encoding temporal parameters in fragments.
>
>--
>Logic is a systematic method of coming to the wrong conclusion with
>confidence.
-------------- next part --------------
? Umakefil.upp
? Makefile
? protocol_rtsp.dsp
? protocol_rtsp.dsw
? dbg32
? a
? logfile.txt
Index: rtsppars.cpp
===================================================================
RCS file: /cvs/protocol/rtsp/rtsppars.cpp,v
retrieving revision 1.1.1.1.10.1
diff -u -w -4 -r1.1.1.1.10.1 rtsppars.cpp
--- rtsppars.cpp 13 Jun 2003 00:21:45 -0000 1.1.1.1.10.1
+++ rtsppars.cpp 28 Jul 2003 23:52:33 -0000
@@ -246,8 +246,148 @@
return 0;
}
int
+RTSPParser::parseRTPInfoHeaderValues(const char* pValue, MIMEHeader* pHeader)
+{
+ // Per RFC2326 "12.33 RTP-Info"
+ // We can't use token search on ',' & ';' since both can also be part of
+ // the URL value. We will:
+ // 1. find stream URL entry based on "url="
+ // 2. read "url", "seq" and "rtptime" within the stream URL entry
+ if (!pValue || 0 == strlen(pValue))
+ {
+ return 0;
+ }
+
+ char* pCurrentEntry = NULL;
+ char* pNextEntry = NULL;
+ CHXString value = pValue;
+ CHXString entry;
+
+ pCurrentEntry = strstr(pValue, "url=");
+
+ while (pNextEntry = strstr(pCurrentEntry+4, "url="))
+ {
+ // retreive stream URL entry
+ entry = value.Mid(pCurrentEntry - pValue, pNextEntry - pCurrentEntry);
+
+ // retrieve "url", "seq" and "rtptime"
+ SetRTPInfoEntry(entry, pHeader);
+
+ pCurrentEntry = pNextEntry;
+ }
+
+ entry = value.Mid(pCurrentEntry - pValue);
+ SetRTPInfoEntry(entry, pHeader);
+
+ return 0;
+}
+
+int
+RTSPParser::ReadRTPInfoEntry(CHXString in,
+ INT32 i,
+ INT32 length,
+ CHXString& out)
+{
+ UINT32 ulLength = 0;
+ CHXString temp;
+
+ if (length > 0)
+ {
+ temp = in.Mid(i, length);
+ }
+ else
+ {
+ temp = in.Mid(i);
+ }
+
+ temp.TrimLeft();
+ temp.TrimRight();
+
+ ulLength = temp.GetLength();
+ // remove trailing ',' or ';' in case there is any
+ if (temp[ulLength-1] == ',' || temp[ulLength-1] == ';')
+ {
+ out = temp.Mid(0, ulLength-1);
+ out.TrimRight();
+ }
+ else
+ {
+ out = temp;
+ }
+
+ return 0;
+}
+
+int
+RTSPParser::SetRTPInfoEntry(CHXString in, MIMEHeader* pHeader)
+{
+ INT32 lURL, lSeq, lRTPTime;
+ CHXString URLValue, SeqValue, RTPTimeValue;
+ MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue;
+
+ lURL = in.Find("url=");
+ lSeq = in.Find("seq=");
+ lRTPTime = in.Find("rtptime=");
+
+ // both seq and rtptime are present
+ if (lSeq > 0 && lRTPTime > 0)
+ {
+ // url;seq;rtptime
+ if (lRTPTime > lSeq)
+ {
+ ReadRTPInfoEntry(in, lURL+4, lSeq-lURL-5, URLValue);
+ ReadRTPInfoEntry(in, lSeq+4, lRTPTime-lSeq-5, SeqValue);
+ ReadRTPInfoEntry(in, lRTPTime+8, -1, RTPTimeValue);
+ }
+ // url;rtptime;seq
+ else
+ {
+ ReadRTPInfoEntry(in, lURL+4, lRTPTime-lURL-5, URLValue);
+ ReadRTPInfoEntry(in, lRTPTime+8, lSeq-lRTPTime-9, RTPTimeValue);
+ ReadRTPInfoEntry(in, lSeq+4, -1, SeqValue);
+ }
+ }
+ // url;seq
+ else if (lSeq > 0)
+ {
+ ReadRTPInfoEntry(in, lURL+4, lSeq-lURL-5, URLValue);
+ ReadRTPInfoEntry(in, lSeq+4, -1, SeqValue);
+ }
+ // url;rtptime
+ else if (lRTPTime > 0)
+ {
+ ReadRTPInfoEntry(in, lURL+4, lRTPTime-lURL-5, URLValue);
+ ReadRTPInfoEntry(in, lRTPTime+8, -1, RTPTimeValue);
+ }
+ // invalid case, either seq or rtptime has to be present
+ else
+ {
+ HX_ASSERT(FALSE);
+ }
+
+ if (!URLValue.IsEmpty())
+ {
+ pHeaderValue->addParameter("url", URLValue);
+ }
+
+ if (!SeqValue.IsEmpty())
+ {
+ pHeaderValue->addParameter("seq", SeqValue);
+ }
+
+ if (!RTPTimeValue.IsEmpty())
+ {
+ pHeaderValue->addParameter("rtptime", RTPTimeValue);
+ }
+
+ pHeader->addHeaderValue(pHeaderValue);
+
+ return 0;
+}
+
+int
RTSPParser::parseBackChannelValue(const char* pValue, MIMEHeader* pHeader)
{
MIMEInputStream input(pValue, strlen(pValue));
MIMEScanner scanner(input);
@@ -375,8 +515,12 @@
(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);
}
Index: pub/rtsppars.h
===================================================================
RCS file: /cvs/protocol/rtsp/pub/rtsppars.h,v
retrieving revision 1.1.1.1
diff -u -w -4 -r1.1.1.1 rtsppars.h
--- pub/rtsppars.h 18 Oct 2002 01:57:52 -0000 1.1.1.1
+++ pub/rtsppars.h 28 Jul 2003 23:52:33 -0000
@@ -68,8 +68,11 @@
MIMEHeader* pHeader);
int parseDigestAuthorizationHeaderValues(const char* pValue,
MIMEHeader* pHeader);
int parsePEPInfoHeaderValues(const char* pValue, MIMEHeader* pHeader);
+ int parseRTPInfoHeaderValues(const char* pValue, MIMEHeader* pHeader);
+ int ReadRTPInfoEntry(CHXString in, INT32 i, INT32 length, CHXString& out);
+ int SetRTPInfoEntry(CHXString in, MIMEHeader* pHeader);
int parseBackChannelValue(const char* pValue, MIMEHeader* pHeader);
int parseAlertValue(const char* pValue, MIMEHeader* pHeader);
int defaultParseHeaderValues(const char* pValue, MIMEHeader* pHeader);
int parseProtocolVersion(const CHXString& prot, int& major, int& minor);
-------------- next part --------------
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe at protocol.helixcommunity.org
For additional commands, e-mail: dev-help at protocol.helixcommunity.org