• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 
19 #include "rtsp_par_com.h"
20 #include "oscl_string_utils.h"
21 #include "rtsp_range_utils.h"
22 
23 OSCL_EXPORT_REF void
reset()24 RTSPIncomingMessage::reset()
25 {
26     RTSPGenericMessage::reset();
27 
28 #ifdef RTSP_PLAYLIST_SUPPORT
29     playlistRangeField.setPtrLen("", 0);
30     playlistRangeFieldIsSet = false;
31     // need to figure out how to store all the error fields.. we may not actually need to
32     playlistErrorFieldIsSet = false;
33     playlistErrorFieldCount = 0;
34     for (int ii = 0; ii < RTSP_MAX_NUMBER_OF_PLAYLIST_ERROR_ENTRIES; ++ii)
35     {
36         playlistErrorField[ii].setPtrLen("", 0);
37     }
38 
39     supportedFieldIsSet = false;
40     numOfSupportedEntries = 0;
41     for (int jj = 0; jj < RTSP_MAX_NUMBER_OF_SUPPORTED_ENTRIES; ++jj)
42     {
43         supportedField[jj].setPtrLen("", 0);
44     }
45 
46     playlistRangeUrl.setPtrLen("", 0);
47     playlistRangeClipIndex = 0;
48     playlistRangeClipOffset = 0;
49     playlistRangeNptTime = 0;
50 #endif
51 
52     amMalformed = RTSPOk;
53     rtspVersionString = "";
54 }
55 
56 void
parseFirstFields()57 RTSPIncomingMessage::parseFirstFields()
58 {
59 
60     char * endOfString;
61 
62     // The first thing to do is to parse the status line;
63     // the rest of the parsing (regular fields) can be parsed out by
64     // parseNextPortion() method, since it has to know how to do that anyway.
65     // We also have to find out if Content-length is there, etc.
66 
67     // so, let's set up the pointers first
68     //
69     secondaryBufferSpace = secondaryBuffer;
70     if (CHAR_CR == *secondaryBufferSpace)
71     {
72         ++secondaryBufferSpace;
73     }
74     if (CHAR_LF == *secondaryBufferSpace)
75     {
76         ++secondaryBufferSpace;
77     }
78 
79 #ifdef SIMPLE_HTTP_SUPPORT
80     if (secondaryBufferSizeUsed >= 4)
81     {// Real http cloaking. H\02\00\00
82         if (('H' != secondaryBufferSpace[0])
83                 || ('T' != secondaryBufferSpace[1])
84                 || ('T' != secondaryBufferSpace[2])
85                 || ('P' != secondaryBufferSpace[3])
86            )
87         {
88             if ('H' == secondaryBufferSpace[0])
89             {//HTTP_RESPONSE
90                 uint32 nOptionLen = secondaryBufferSpace[1];
91                 secondaryBufferSpace += (2 + nOptionLen);
92             }
93             /* TBD
94             else if('r' == secondaryBufferSpace[0])
95             {//HTTP_RV_RESPONSE
96             }
97             */
98         }
99     }
100 #endif
101 
102     numPtrFields = 0;
103 
104     char * wordPtr[3] = { NULL, NULL, NULL };
105     char * endOfLine;
106     int   wordCount;
107     bool  wordCountTrigger;
108 
109     for (endOfLine = secondaryBufferSpace, wordCount = 0, wordCountTrigger = true;
110             (endOfLine < secondaryBufferSpace + secondaryBufferSizeUsed)
111             && (CHAR_CR != *endOfLine)
112             && (CHAR_LF != *endOfLine);
113             ++endOfLine
114         )
115     {
116         switch (wordCountTrigger)
117         {
118             case true:  // if non-space, then it's a beginning of a new word
119             {
120                 if ((*endOfLine >= 0x09 && *endOfLine <= 0x0D) || *endOfLine == 0x20)
121                 { // spaces
122                 }
123                 else
124                 { // word
125                     if (3 > wordCount)
126                     {
127                         wordPtr[wordCount] = endOfLine;
128                     }
129                     ++wordCount;
130 
131                     // uncock the trigger
132                     wordCountTrigger = false;
133                 }
134 
135                 break;
136             }
137 
138             case false: // if space, then cock the trigger
139             {
140                 if ((*endOfLine >= 0x09 && *endOfLine <= 0x0D) || *endOfLine == 0x20)
141                 { // yeah, space
142                     wordCountTrigger = true;
143                 }
144                 else
145                 { // still a word
146                 }
147                 break;
148             }
149 
150             default:
151                 // ERROR: internal inconsistency, a switch on a boolean should not hit
152                 // this point
153                 ;;
154         }
155     }
156 
157     if (3 > wordCount)
158     { // only two words in the status line - error
159 
160         amMalformed = RTSPErrorSyntax;
161         return;
162     }
163 
164     if (CHAR_CR == *endOfLine)
165     {
166         *(endOfLine++) = CHAR_NULL;
167         if (CHAR_LF == *endOfLine)
168         {
169             *(endOfLine++) = CHAR_NULL;
170         }
171     }
172     else if (CHAR_LF == *endOfLine)
173     {
174         *(endOfLine++) = CHAR_NULL;
175     }
176     else
177     {
178         // ran to the end of input, didn't find a single newline....
179         // most probably the message was too big to handle, but parser still
180         // created a message hoping that at least something can be found...
181         //
182 
183         amMalformed = RTSPErrorSyntax;
184 
185         return;
186     }
187 
188 
189 
190     // figure out the format of the message - request or response?
191     //
192     // make out the first word... don't forget about '$'
193     //
194 
195 ////  endOfString = secondaryBufferSpace;
196 ////  while( ! isspace(*endOfString) )
197 ////    ++endOfString;
198 
199     endOfString = wordPtr[1];
200     while (--endOfString >= secondaryBufferSpace
201             && ((*endOfString >= 0x09 && *endOfString <= 0x0D) || *endOfString == 0x20)
202           )
203     {
204         *endOfString = CHAR_NULL;
205     }
206 
207 ////  *endOfString = CHAR_NULL;
208 ////  StrCSumPtrLen firstWordPLSS = secondaryBufferSpace;
209     StrCSumPtrLen firstWordPLSS = wordPtr[0];
210 
211     if (('R' == *(wordPtr[0]))
212             && ('T' == *(wordPtr[0] + 1))
213             && ('S' == *(wordPtr[0] + 2))
214             && ('P' == *(wordPtr[0] + 3))
215             && ('/' == *(wordPtr[0] + 4))
216        )
217     {
218         // it has to be a response
219         //
220         msgType = RTSPResponseMsg;
221         rtspVersionString = firstWordPLSS;
222 
223         // if there is a mismatch, let the Engine know about it and stop parsing
224         if (rtspVersionString != RTSPVersionString)
225         {
226             amMalformed = RTSPErrorVersion;
227             return;
228         }
229 
230         // get the code
231 ////      secondaryBufferSpace = endOfString+1;
232 ////     while( isspace(*secondaryBufferSpace) )
233 ////      {
234 ////          ++secondaryBufferSpace;
235 ////        }
236 
237 ////      statusCode = atoi( secondaryBufferSpace );
238         uint32 atoi_tmp;
239         PV_atoi(wordPtr[1], 'd', atoi_tmp);
240         statusCode = (RTSPStatusCode)atoi_tmp;
241 
242         // get the reason string
243 
244 ////      while( ! isspace( *secondaryBufferSpace ) )
245 ////        {
246 ////          ++secondaryBufferSpace;
247 ////        }
248 
249 ////      while( isspace( *secondaryBufferSpace ) )
250 ////        {
251 ////          ++secondaryBufferSpace;
252 ////        }
253 
254 ////      endOfString = secondaryBufferSpace;
255 ////      while(            (CHAR_CR != *endOfString)
256 ////                                &&  (CHAR_LF != *endOfString)
257 ////                                )
258 ////        {
259 ////          ++endOfString;
260 ////        }
261 
262 ////      *endOfString = CHAR_NULL;
263 ////      reasonString = secondaryBufferSpace;
264         reasonString = wordPtr[2];
265 
266         // now, resync to the next line
267 ////      secondaryBufferSpace = endOfString+1;
268 ////      if( CHAR_LF == *secondaryBufferSpace )
269 ////        {
270 ////          ++secondaryBufferSpace;
271 ////        }
272 
273         secondaryBufferSpace = endOfLine;
274     }
275 #ifdef SIMPLE_HTTP_SUPPORT
276     else if (('H' == *(wordPtr[0]))
277              && ('T' == *(wordPtr[0] + 1))
278              && ('T' == *(wordPtr[0] + 2))
279              && ('P' == *(wordPtr[0] + 3))
280              && ('/' == *(wordPtr[0] + 4))
281             )
282     {
283         msgType = RTSPResponseMsg;
284         rtspVersionString = firstWordPLSS;
285 
286         // if there is a mismatch, let the Engine know about it and stop parsing
287         if ((rtspVersionString != HTTPVersion_1_0_String)
288                 && (rtspVersionString != HTTPVersion_1_1_String))
289         {
290             amMalformed = RTSPErrorVersion;
291             return;
292         }
293         uint32 atoi_tmp;
294         PV_atoi(wordPtr[1], 'd', atoi_tmp);
295         statusCode = (RTSPStatusCode)atoi_tmp;
296         reasonString = wordPtr[2];
297         secondaryBufferSpace = endOfLine;
298     }
299 #endif
300     else
301     {   // okay, it could be a request
302 
303         // but for requests there must be exactly three words on the
304         // status line
305         if (3 != wordCount)
306         {
307             amMalformed = RTSPErrorSyntax;
308             return;
309         }
310 
311         msgType = RTSPRequestMsg;
312 
313         methodString = firstWordPLSS;
314 
315         if (firstWordPLSS == RtspRequestMethodStringDescribe)
316         {
317             method = METHOD_DESCRIBE;
318         }
319         else if (firstWordPLSS == RtspRequestMethodStringGetParameter)
320         {
321             method = METHOD_GET_PARAMETER;
322         }
323         else if (firstWordPLSS == RtspRequestMethodStringOptions)
324         {
325             method = METHOD_OPTIONS;
326         }
327         else if (firstWordPLSS == RtspRequestMethodStringPause)
328         {
329             method = METHOD_PAUSE;
330         }
331         else if (firstWordPLSS == RtspRequestMethodStringPlay)
332         {
333             method = METHOD_PLAY;
334         }
335         else if (firstWordPLSS == RtspRequestMethodStringSetup)
336         {
337             method = METHOD_SETUP;
338         }
339         else if (firstWordPLSS == RtspRequestMethodStringRecord)
340         {
341             method = METHOD_RECORD;
342         }
343         else if (firstWordPLSS == RtspRequestMethodStringTeardown)
344         {
345             method = METHOD_TEARDOWN;
346         }
347         else if (firstWordPLSS == RtspRequestMethodStringEndOfStream)
348         {
349             method = METHOD_END_OF_STREAM;
350         }
351         /* TBD: add Announce, SetParameter and Redirect later
352         else if( firstWordPLSS == RtspRequestMethodStringAnnounce )
353           {
354             method = METHOD_ANNOUNCE;
355           }
356         */
357         else if (firstWordPLSS == RtspRequestMethodStringSetParameter)
358         {
359             method = METHOD_SET_PARAMETER;
360         }
361 
362         else if (firstWordPLSS == RtspRequestMethodStringRedirect)  //SS
363         {
364             method = METHOD_REDIRECT; ////SS
365         }
366         // now, we could put binary data here, but it's not exactly the same
367         // thing; since it requires special care, let's not confuse things by
368         // putting generic-looking stuff here
369         else
370         {
371             method = METHOD_UNRECOGNIZED;
372         }
373 
374         // get the URI
375 
376 ////      secondaryBufferSpace = endOfString +1;
377 ////      while( isspace( *secondaryBufferSpace ) )
378 ////        {
379 ////          ++secondaryBufferSpace;
380 ////        }
381 
382 ////      endOfString = secondaryBufferSpace;
383 ////      while( ! isspace( *endOfString ) )
384 ////        {
385 ////          ++endOfString;
386 ////        }
387 ////      *endOfString = CHAR_NULL;
388 
389 ////      originalURI = secondaryBufferSpace;
390         endOfString = wordPtr[2];
391         while ((--endOfString) >= wordPtr[1]
392                 && ((*endOfString >= 0x09 && *endOfString <= 0x0D) || *endOfString == 0x20)
393               )
394         {
395             *endOfString = CHAR_NULL;
396         }
397         originalURI = wordPtr[1];
398 
399         // get the RTSP version
400 ////      secondaryBufferSpace = endOfString +1;
401 ////      while( isspace( *secondaryBufferSpace ) )
402 ////        {
403 ////          ++secondaryBufferSpace;
404 ////        }
405 ////      endOfString = secondaryBufferSpace;
406 ////      while( !isspace(*endOfString) )
407 ////        {
408 ////          ++endOfString;
409 ////        }
410 
411 ////      *endOfString = CHAR_NULL;
412 ////      rtspVersionString = secondaryBufferSpace;
413         endOfString = endOfLine;
414         while (--endOfString >= wordPtr[2]
415                 && (((*endOfString >= 0x09 && *endOfString <= 0x0D) || *endOfString == 0x20)
416                     ||  CHAR_NULL == *endOfString
417                    )
418               )
419         {
420             *endOfString = CHAR_NULL;
421         }
422         rtspVersionString = wordPtr[2];
423 
424         // if there is a mismatch, let the Engine know about it and stop parsing
425         if (rtspVersionString != RTSPVersionString)
426         {
427             amMalformed = RTSPErrorVersion;
428             return;
429         }
430 
431         // now, resync to the next line
432 ////      secondaryBufferSpace = endOfString + 1;
433 ////      if( CHAR_LF == *secondaryBufferSpace )
434 ////        {
435 ////          ++secondaryBufferSpace;
436 ////        }
437         secondaryBufferSpace = endOfLine;
438 
439         // extra URI validation
440         {
441             if (1 == originalURI.length())
442             { // Is it a star
443                 if (CHAR_STAR != originalURI.c_str()[0])
444                 {
445                     amMalformed = RTSPErrorSyntax;
446                     return;
447                 }
448             }
449             else
450             { // it's a normal URI
451 
452                 // let's validate the scheme
453                 char colonStr[2];
454                 colonStr[0] = CHAR_COLON;
455                 colonStr[1] = NULL_TERM_CHAR;
456                 const char * colonPtr = oscl_strstr(originalURI.c_str(), colonStr);
457                 if (NULL == colonPtr)
458                 {
459                     // no colon
460                     amMalformed = RTSPErrorSyntax;
461                     return;
462                 }
463 
464                 // now, the first character of the scheme is a character
465                 const char * ptr = originalURI.c_str();
466                 if (!((*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z')))
467 
468                 {
469                     // the URI doesn't start with a character
470                     amMalformed = RTSPErrorSyntax;
471                     return;
472                 }
473 
474                 // the rest of the characters must be either characters, or
475                 // plus/minus, or dots...
476                 for (++ptr; ptr < colonPtr; ++ptr)
477                 {
478                     if (!(((*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z'))
479                             || (*ptr >= '0' || *ptr <= '9')
480                             ||  CHAR_PLUS == *ptr
481                             ||  CHAR_MINUS == *ptr
482                             ||  CHAR_DOT == *ptr
483                          ))
484                     {
485                         amMalformed = RTSPErrorSyntax;
486                         return;
487                     }
488                 }
489             }
490         }
491 
492         // finish off the URI processing
493 
494         {
495             // look for the base
496             uint32  ii;
497             int32   ee;
498             uint32 length = originalURI.length();
499 
500             for (ii = 0; ii < length; ++ii)
501             {
502                 if (CHAR_SLASH == originalURI.c_str()[ii])
503                 {
504                     if (CHAR_SLASH != originalURI.c_str()[++ii])
505                     {
506                         break;
507                     }
508                     else
509                     { // no, it's a separator, skip over it, continue
510                     }
511                 }
512             }
513             originalURIBase = originalURI.c_str() + ii;
514 
515             // look for the control candidate
516             for (ee = originalURIBase.length() - 1;
517                     ee >= 0;
518                     --ee
519                 )
520             {
521                 if ((CHAR_SLASH      ==  originalURIBase.c_str()[ee])
522                         || (CHAR_SEMICOLON  ==  originalURIBase.c_str()[ee])
523                    )
524                 {
525                     break;
526                 }
527             }
528             originalURIControlCandidate = originalURIBase.c_str() + ee + 1;
529 
530         }
531     }
532 
533 
534     // determine the total number of fields remaining to be seen
535 
536     endOfString = secondaryBuffer + secondaryBufferSizeUsed;
537     *(--endOfString) = CHAR_NULL;
538     --secondaryBufferSizeUsed;
539     if (CHAR_CR == *(endOfString - 1))
540     {
541         *(--endOfString) = CHAR_NULL;
542         --secondaryBufferSizeUsed;
543     }
544 
545 
546     totalFields = 0;
547     for (char * ptr = secondaryBufferSpace; ptr < endOfString; ++ptr)
548     {
549         if (CHAR_LF == *ptr)
550         {
551             ++totalFields;
552         }
553         else if (CHAR_CR == *ptr)
554         {
555             if (CHAR_LF != *(ptr + 1))
556             {
557                 ++totalFields;
558             }
559         }
560     }
561 
562     totalFieldsParsed = 0;
563     parseNextPortion();
564 
565     if (getTotalFields() != getTotalFieldsParsed())
566     {
567         amMalformed = RTSPErrorTooManyFields;
568     }
569 }
570 
571 bool
parseNextPortion()572 RTSPIncomingMessage::parseNextPortion()
573 {
574     if (totalFieldsParsed == totalFields)
575     {
576         return false;
577     }
578 
579     char * endOfMessage = secondaryBuffer + secondaryBufferSizeUsed;
580     char * ptr = secondaryBufferSpace;
581 
582     //  printf ("parcom::parseNextPortion: secondaryBuffer is \n %s \n",secondaryBuffer);
583 
584 
585     for (numPtrFields = 0;
586             (numPtrFields < RTSP_MAX_NUMBER_OF_FIELDS) && (ptr < endOfMessage);
587             ++numPtrFields)
588     {
589         char *endOfValue = ptr;
590         while (CHAR_LF != *(endOfValue)
591                 &&  CHAR_CR != *(endOfValue)
592                 &&  CHAR_NULL != *(endOfValue))
593         {
594             ++endOfValue;
595         }
596 
597         if (CHAR_CR == *(endOfValue) && CHAR_LF == *(endOfValue + 1))
598         {
599             // need to increment endOfValue for CR-LF, because
600             // it is needed later to step into the next field by shifting by 1
601             *(endOfValue) = CHAR_NULL;
602             *(++endOfValue) = CHAR_NULL;
603         }
604         else
605         {
606             *endOfValue = CHAR_NULL;
607         }
608 
609         char * separator = ptr;
610 
611         while ((CHAR_COLON != *separator)   && (CHAR_NULL != *separator))
612         {
613             ++separator;
614         }
615 
616         if (CHAR_COLON != *separator)
617         {
618             //amMalformed = RTSPErrorSyntax;
619             //ignore the unknown lines
620             ptr = endOfValue + 1;
621             continue;
622         }
623         else
624         {
625             *separator = CHAR_NULL;
626 
627             // get name pointer
628             char * namePtr = ptr;
629             // eat through trailing whitespace
630             for (char * wPtr1 = separator - 1;
631                     (wPtr1 >= namePtr) && ((*wPtr1 >= 0x09 && *wPtr1 <= 0x0D) || *wPtr1 == 0x20);
632                     --wPtr1)
633             {
634                 *wPtr1 = CHAR_NULL;
635             }
636             // eat through leading whitespace
637             while ((*namePtr >= 0x09 && *namePtr <= 0x0D) || *namePtr == 0x20)
638             {
639                 ++namePtr;
640             }
641 
642             // get value pointer
643             char * valuePtr = separator + 1;
644             // eat through trailing whitespace
645             for (char * wPtr2 = endOfValue - 1;
646                     (wPtr2 > separator)
647                     && ((*wPtr2 >= 0x09 && *wPtr2 <= 0x0D) || *wPtr2 == 0x20);
648                     --wPtr2)
649             {
650                 *wPtr2 = CHAR_NULL;
651             }
652             //eat through leading whitespace
653             while ((*valuePtr >= 0x09 && *valuePtr <= 0x0D) || *valuePtr == 0x20)
654             {
655                 ++valuePtr;
656             }
657 
658             // all right, set the pointers
659 
660             fieldKeys[ numPtrFields ] = namePtr;
661             fieldVals[ numPtrFields ] = valuePtr;
662 
663             // determine if we are supposed to recognize this
664             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
665                         RtspRecognizedFieldSessionId))
666             {
667                 {
668                     StrPtrLen tmp = fieldVals[ numPtrFields ];
669                     int Len = tmp.length();
670                     char * beginPtr = (char*)tmp.c_str();
671                     char * endPtr = beginPtr + Len;
672 
673                     while (beginPtr < endPtr)
674                     {
675                         if (*beginPtr == ';')
676                         {//we got timeout field
677                             while (beginPtr < endPtr)
678                             {
679                                 if ((*beginPtr == 't') && (beginPtr[6] == 't'))
680                                 {//a little bit validation
681                                     beginPtr += 8;
682                                     PV_atoi(beginPtr, 'd', timeout);
683                                     beginPtr = endPtr;
684                                 }
685                                 beginPtr++;
686                             }
687                         }
688                         beginPtr++;
689                     }
690                 }
691                 sessionId = fieldVals[ numPtrFields ];
692                 sessionIdIsSet = true;
693             }
694             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
695                         RtspRecognizedFieldCSeq))
696             {
697                 PV_atoi(valuePtr, 'd', cseq);
698                 cseqIsSet = true;
699             }
700             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
701                         RtspRecognizedFieldBufferSize
702                     ))
703             {
704                 PV_atoi(valuePtr, 'd', bufferSize);
705                 bufferSizeIsSet = true;
706             }
707             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
708                         RtspRecognizedFieldContentType))
709             {
710                 contentType = fieldVals[ numPtrFields ];
711                 contentTypeIsSet = true;
712             }
713             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
714                         RtspRecognizedFieldContentBase))
715             {
716                 contentBase = fieldVals[ numPtrFields ];
717                 contentBaseMode = CONTENT_BASE_SET;
718             }
719             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
720                         RtspRecognizedFieldContentLength))
721             {
722                 PV_atoi(valuePtr, 'd', contentLength);
723                 contentLengthIsSet = true;
724             }
725             if (fieldKeys[ numPtrFields].isCIEquivalentTo(
726                         RtspRecognizedFieldUserAgent))
727             {
728                 userAgent = fieldVals[ numPtrFields ];
729                 userAgentIsSet = true;
730             }
731             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
732                         RtspRecognizedFieldAccept))
733             {
734                 accept = fieldVals[ numPtrFields ];
735                 acceptIsSet = true;
736             }
737             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
738                         RtspRecognizedFieldRequire))
739             {
740                 require = fieldVals[ numPtrFields ];
741                 requireIsSet = true;
742             }
743             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
744                         RtspRecognizedFieldRTPInfo
745                     ))
746             {
747                 parseRTPInfo(numPtrFields);
748             }
749 
750             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
751                         RtspRecognizedFieldRange))
752             {
753                 parseRtspRange(fieldVals[ numPtrFields].c_str(), fieldVals[ numPtrFields].length(), range);
754                 rangeIsSet = true;
755             }
756             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
757                         RtspRecognizedFieldTransport))
758             {
759                 parseTransport(numPtrFields);
760             }
761 #ifdef RTSP_PLAYLIST_SUPPORT
762             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
763                         RtspRecognizedFieldSupported))
764             {
765                 parseSupported(fieldVals[ numPtrFields].c_str(), fieldVals[ numPtrFields].length() + 1);
766                 supportedFieldIsSet = true;
767             }
768 #endif
769         }
770 
771         ptr = endOfValue + 1;
772     }
773 
774     totalFieldsParsed += numPtrFields;
775 
776     secondaryBufferSpace = ptr;
777 
778     return true;
779 }
780 
781 #ifdef RTSP_PLAYLIST_SUPPORT
782 
783 void
parseSupported(const char * supportedString,int length)784 RTSPIncomingMessage::parseSupported(const char *supportedString, int length)
785 {
786     const StrPtrLen methodEosString("method.eos");
787     const StrPtrLen comPvPlaylistString("com.pv.server_playlist");
788 
789     const char *end = supportedString + length;
790 
791     char *sptr;//, *eptr;
792 
793     sptr = (char*)supportedString;
794 
795     while ((sptr < end) && (numOfSupportedEntries < RTSP_MAX_NUMBER_OF_SUPPORTED_ENTRIES))
796     {
797         char * separator = sptr;
798 
799         while ((CHAR_COMMA != *separator)
800                 && (CHAR_NULL != *separator)
801                 && (separator < end)
802               )
803         {
804             ++separator;
805         }
806 
807         if (CHAR_COMMA == *separator)
808         {
809             // make sure there is a terminating char
810             // in the other case, there will already be one because its the end of the line
811             // and the field parsing that called this function put one there
812             *separator = CHAR_NULL;
813         }
814 
815         // get name pointer
816         char * namePtr = sptr;
817         // eat through trailing whitespace
818         for (char * wPtr1 = separator - 1;
819                 (wPtr1 >= namePtr)
820                 && ((*wPtr1 >= 0x09 && *wPtr1 <= 0x0D) || *wPtr1 == 0x20);
821                 --wPtr1)
822         {
823             *wPtr1 = CHAR_NULL;
824         }
825         // eat through leading whitespace
826         while ((*namePtr >= 0x09 && *namePtr <= 0x0D) || *namePtr == 0x20)
827         {
828             ++namePtr;
829         }
830 
831         supportedField[numOfSupportedEntries++] = namePtr;
832 
833         if (!oscl_strncmp(namePtr, methodEosString.c_str(), methodEosString.length()))
834         {
835             methodEosIsSet = true;
836         }
837         else if (!oscl_strncmp(namePtr, comPvPlaylistString.c_str(), comPvPlaylistString.length()))
838         {
839             comPvServerPlaylistIsSet = true;
840         }
841 
842         sptr = separator + 1;
843 
844     }  // end while
845 }
846 
847 #endif /* RTSP_PLAYLIST_SUPPORT */
848 
849 
850 // relevant constants
851 const int MIN_CHANNEL_VALUE = 0;
852 const int MAX_CHANNEL_VALUE = 255;
853 const int PORT_MIN_VALUE = 0;
854 const int PORT_MAX_VALUE = 65535;
855 
856 #define interleaved_str "interleaved="
857 #define interleaved_str_len 12
858 
859 #define client_port_str "client_port="
860 #define client_port_str_len 12
861 
862 #define server_port_str "server_port="
863 #define server_port_str_len 12
864 
865 #define ttl_str "ttl="
866 #define ttl_str_len 4
867 
868 #define mode_str "mode="
869 #define mode_str_len 5
870 
871 #define port_str "port="
872 #define port_str_len 5
873 
874 #define layers_str "layers="
875 #define layers_str_len 7
876 
877 #define ssrc_str "ssrc="
878 #define ssrc_str_len 5
879 
880 #define destination_str "destination"
881 #define destination_str_len 11
882 
883 void
parseTransport(uint16 fieldIdx)884 RTSPIncomingMessage::parseTransport(uint16 fieldIdx)
885 {
886     char * cPtr;
887     char * finishPtr;
888 
889     cPtr = const_cast<char*>(fieldVals[ fieldIdx ].c_str());
890     finishPtr = cPtr + fieldVals[ fieldIdx ].length();
891 
892     do
893     {
894         parseOneTransportEntry(cPtr, finishPtr);
895 
896     }
897     while (RTSPOk == amMalformed
898             &&  cPtr < finishPtr
899           );
900 }
901 
902 
903 void
parseOneTransportEntry(char * & trans,char * final_end)904 RTSPIncomingMessage::parseOneTransportEntry(char*& trans, char *final_end)
905 {
906     const char *startPtr, *endPtr, *nxtPtr;
907     char *transSepPtr;
908 
909 
910 
911     // check the counter
912     //
913     if (RTSP_MAX_NUMBER_OF_TRANSPORT_ENTRIES == numOfTransportEntries)
914     { // limit reached
915         amMalformed = RTSPErrorSyntax;  // should it be different?
916         return;
917     }
918 
919     RtspTransport* rtspTrans = transport + numOfTransportEntries;
920     numOfTransportEntries++;
921 
922     startPtr = trans;
923 
924     if (*startPtr == ',')
925     {
926         // skip over any starting commas
927         ++startPtr;
928     }
929 
930     rtspTrans->appendIsSet = false;
931     rtspTrans->channelIsSet = false;
932     rtspTrans->client_portIsSet = false;
933     rtspTrans->deliveryIsSet = false;
934     rtspTrans->layersIsSet = false;
935     rtspTrans->modeIsSet = false;
936     rtspTrans->portIsSet = false;
937     rtspTrans->profileIsSet = false;
938     rtspTrans->protocolIsSet = false;
939     rtspTrans->transportTypeIsSet = false;
940     rtspTrans->server_portIsSet = false;
941     rtspTrans->ttlIsSet = false;
942     rtspTrans->destinationIsSet = false;
943 
944 
945 
946     // see if there is a tranport list separator
947     transSepPtr = OSCL_CONST_CAST(char*, oscl_strstr(startPtr, ","));
948     if (transSepPtr)
949     {
950 
951         const char *quotePtr = oscl_strstr(startPtr, "\"");
952         if (quotePtr && quotePtr < transSepPtr)
953         {
954             // this may be a comma in the mode list -- so find the end of the mode list
955             const char *quote_end = oscl_strstr(quotePtr + 1, "\"");
956             if (quote_end)
957             {
958                 // look for another comma
959                 if (NULL != (transSepPtr = OSCL_CONST_CAST(char*, oscl_strstr(quote_end, ","))))
960                 {
961                     // temporarily write a terminator to separate the transport specs.
962                     *transSepPtr = '\0';
963                 }
964             }
965         }
966         else
967         {
968             // temporarily write a terminator to separate the transport specs.
969             *transSepPtr = '\0';
970         }
971     }
972 
973 
974 //  for (; startPtr < final_end && isspace(*startPtr); ++startPtr);
975     for (; startPtr < final_end && ((*startPtr >= 0x09 && *startPtr <= 0x0D) || *startPtr == 0x20); ++startPtr);
976 
977     do
978     {
979         if (NULL == (endPtr = oscl_strstr(startPtr, "/")))
980         {
981             endPtr = final_end;
982         }
983 
984         rtspTrans->protocolIsSet = true;
985 
986         if (!oscl_strncmp(startPtr, "RTP", endPtr - startPtr))
987         {
988             rtspTrans->protocol = RtspTransport::RTP_PROTOCOL;
989         }
990         else if (!oscl_strncmp(startPtr, "x-pn-tng", endPtr - startPtr))
991         {
992             rtspTrans->protocol = RtspTransport::RDT_PROTOCOL;
993         }
994         else
995         {
996             rtspTrans->protocol = RtspTransport::UNKNOWN_PROTOCOL;
997         }
998 
999         if (endPtr == final_end)
1000         {
1001             break;
1002         }
1003 
1004         // increment the startPtr past the separator
1005         startPtr = endPtr + 1;
1006 
1007         // look for either the '/' or ';' separators
1008         endPtr = oscl_strstr(startPtr, "/");
1009         const char *endPtr2 = oscl_strstr(startPtr, ";");
1010 
1011         if (!endPtr)
1012         {
1013             endPtr = endPtr2;
1014         }
1015 
1016         if (endPtr2 && endPtr2 < endPtr)
1017         {
1018             endPtr = endPtr2;
1019         }
1020 
1021         if (!endPtr)
1022         {
1023             endPtr = final_end;
1024         }
1025 
1026         rtspTrans->profile = RtspTransport::UNKNOWN_PROFILE;
1027         rtspTrans->profileIsSet = true;
1028         if (!oscl_strncmp(startPtr, "AVP", endPtr - startPtr))
1029         {
1030             rtspTrans->profile = RtspTransport::AVP_PROFILE;
1031         }
1032         else if (!oscl_strncmp(startPtr, "tcp", endPtr - startPtr))
1033         {//RDT "x-pn-tng/tcp"
1034             rtspTrans->profile = RtspTransport::TCP_PROFILE;
1035         }
1036 
1037         if (*endPtr == '/')
1038         {
1039             // there is an optional transport spec
1040             startPtr = endPtr + 1;
1041 
1042             if (NULL == (endPtr = oscl_strstr(startPtr, ";")))
1043             {
1044                 endPtr = final_end;
1045             }
1046 
1047             rtspTrans->transportType = RtspTransport::UNKNOWN_TRANSPORT;
1048             rtspTrans->transportTypeIsSet = true;
1049 
1050             if (!oscl_strncmp(startPtr, "UDP", endPtr - startPtr))
1051             {
1052                 rtspTrans->transportType = RtspTransport::UDP_TRANSPORT;
1053             }
1054             else if (!oscl_strncmp(startPtr, "TCP", endPtr - startPtr))
1055             {
1056                 rtspTrans->transportType = RtspTransport::TCP_TRANSPORT;
1057             }
1058         }
1059 
1060         if (endPtr == final_end)
1061         {
1062             break;
1063         }
1064 
1065         // increment the startPtr past the separator
1066         startPtr = endPtr + 1;
1067 
1068     }
1069     while (0); // only go through this once
1070 
1071 
1072     while (startPtr < final_end)
1073     {
1074 
1075         for (; startPtr < final_end && ((*startPtr >= 0x09 && *startPtr <= 0x0D) || *startPtr == 0x20); ++startPtr);
1076 
1077         char *sepPtr;
1078         // find the next separator
1079         if (NULL == (sepPtr = (char*)(endPtr = oscl_strstr(startPtr, ";"))))
1080         {
1081             endPtr = final_end;
1082         }
1083 
1084         if (sepPtr)
1085         {
1086             *sepPtr = '\0';
1087         }
1088 
1089         if (!oscl_strncmp(startPtr, "unicast", endPtr - startPtr))
1090         {
1091             rtspTrans->delivery = RtspTransport::UNICAST_DELIVERY;
1092             rtspTrans->deliveryIsSet = true;
1093         }
1094         if (!oscl_strncmp(startPtr, "multicast", endPtr - startPtr))
1095         {
1096             rtspTrans->delivery = RtspTransport::MULTICAST_DELIVERY;
1097             rtspTrans->deliveryIsSet = true;
1098         }
1099         else if (!oscl_strncmp(startPtr, "append", endPtr - startPtr))
1100         {
1101             rtspTrans->append = true;
1102             rtspTrans->appendIsSet = true;
1103         }
1104         else if (!oscl_strncmp(startPtr, destination_str,
1105                                destination_str_len))
1106         {
1107             nxtPtr = startPtr + destination_str_len;
1108             char *curEndPtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "="));
1109             if (curEndPtr)
1110             {
1111                 nxtPtr = curEndPtr + 1;
1112 
1113                 // skip leading whitespace
1114                 for (; nxtPtr < endPtr && ((*nxtPtr >= 0x09 && *nxtPtr <= 0x0D) || *nxtPtr == 0x20); ++nxtPtr);
1115 
1116                 // now find the end
1117                 for (curEndPtr = (char*)nxtPtr; curEndPtr < endPtr && !((*curEndPtr >= 0x09 && *curEndPtr <= 0x0D) || *curEndPtr == 0x20);
1118                         ++curEndPtr);
1119 
1120                 if (curEndPtr - nxtPtr > 0)
1121                 {
1122                     if (curEndPtr < endPtr)
1123                     {
1124                         *curEndPtr = '\0';
1125                     }
1126                     else if (sepPtr)
1127                     {
1128                         // clear sepPtr so it won't overwrite the NULL character
1129                         sepPtr = NULL;
1130                     }
1131                     rtspTrans->destination.setPtrLen(nxtPtr,
1132                                                      curEndPtr - nxtPtr);
1133                     rtspTrans->destinationIsSet = true;
1134                 }
1135             }
1136 
1137         }
1138         else if (!oscl_strncmp(startPtr, interleaved_str,
1139                                interleaved_str_len))
1140         {
1141             int tmp;
1142             nxtPtr = startPtr + interleaved_str_len;
1143             char *curEndPtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "-"));
1144             if (curEndPtr) *curEndPtr = '\0';
1145             uint32 atoi_tmp;
1146             PV_atoi(nxtPtr, 'd', atoi_tmp);
1147             tmp = atoi_tmp;
1148             if (tmp < MIN_CHANNEL_VALUE || tmp > MAX_CHANNEL_VALUE)
1149             {
1150                 amMalformed = RTSPErrorSyntax;
1151                 if (sepPtr)
1152                 {
1153                     *sepPtr = ';';
1154                 };
1155                 break;
1156             }
1157             rtspTrans->channel1 = tmp;
1158             if (!curEndPtr)
1159             {
1160                 if (rtspTrans->channel1 >= MAX_CHANNEL_VALUE)
1161                 {
1162                     amMalformed = RTSPErrorSyntax;
1163                     if (sepPtr)
1164                     {
1165                         *sepPtr = ';';
1166                     };
1167                     break;
1168                 }
1169                 rtspTrans->channel2 = rtspTrans->channel1 + 1;
1170                 rtspTrans->channelIsSet = true;
1171             }
1172             else
1173             {
1174                 nxtPtr = curEndPtr + 1;
1175                 *curEndPtr = '-';
1176                 PV_atoi(nxtPtr, 'd', atoi_tmp);
1177                 tmp = atoi_tmp;
1178                 if (tmp < MIN_CHANNEL_VALUE || tmp > MAX_CHANNEL_VALUE)
1179                 {
1180                     amMalformed = RTSPErrorSyntax;
1181                     if (sepPtr)
1182                     {
1183                         *sepPtr = ';';
1184                     };
1185                     break;
1186                 }
1187                 rtspTrans->channel2 = tmp;
1188                 rtspTrans->channelIsSet = true;
1189             }
1190         }
1191         else if (!oscl_strncmp(startPtr, client_port_str,
1192                                client_port_str_len))
1193         {
1194             int tmp;
1195             uint32 atoi_tmp;
1196             nxtPtr = startPtr + client_port_str_len;
1197             char *curEndPtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "-"));
1198             if (curEndPtr) *curEndPtr = '\0';
1199             PV_atoi(nxtPtr, 'd', atoi_tmp);
1200             tmp = atoi_tmp;
1201             if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1202             {
1203                 amMalformed = RTSPErrorSyntax;
1204                 if (sepPtr)
1205                 {
1206                     *sepPtr = ';';
1207                 };
1208                 break;
1209             }
1210             rtspTrans->client_port1 = tmp;
1211             if (!curEndPtr)
1212             {
1213                 if (rtspTrans->client_port1 >= PORT_MAX_VALUE)
1214                 {
1215                     amMalformed = RTSPErrorSyntax;
1216                     if (sepPtr)
1217                     {
1218                         *sepPtr = ';';
1219                     };
1220                     break;
1221                 }
1222                 rtspTrans->client_port2 = rtspTrans->client_port1 + 1;
1223                 rtspTrans->client_portIsSet = true;
1224             }
1225             else
1226             {
1227                 nxtPtr = curEndPtr + 1;
1228                 *curEndPtr = '-';
1229                 PV_atoi(nxtPtr, 'd', atoi_tmp);
1230                 tmp = atoi_tmp;
1231                 if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1232                 {
1233                     amMalformed = RTSPErrorSyntax;
1234                     if (sepPtr)
1235                     {
1236                         *sepPtr = ';';
1237                     };
1238                     break;
1239                 }
1240                 rtspTrans->client_port2 = tmp;
1241                 rtspTrans->client_portIsSet = true;
1242             }
1243         }
1244         else if (!oscl_strncmp(startPtr, server_port_str,
1245                                server_port_str_len))
1246         {
1247             int tmp;
1248             uint32 atoi_tmp;
1249             nxtPtr = startPtr + server_port_str_len;
1250             char *curEndPtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "-"));
1251             if (curEndPtr) *curEndPtr = '\0';
1252             PV_atoi(nxtPtr, 'd', atoi_tmp);
1253             tmp = atoi_tmp;
1254             if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1255             {
1256                 amMalformed = RTSPErrorSyntax;
1257                 if (sepPtr)
1258                 {
1259                     *sepPtr = ';';
1260                 };
1261                 break;
1262             }
1263             rtspTrans->server_port1 = tmp;
1264             if (!curEndPtr)
1265             {
1266                 if (rtspTrans->server_port1 >= PORT_MAX_VALUE)
1267                 {
1268                     amMalformed = RTSPErrorSyntax;
1269                     if (sepPtr)
1270                     {
1271                         *sepPtr = ';';
1272                     };
1273                     break;
1274                 }
1275                 rtspTrans->server_port2 = rtspTrans->server_port1 + 1;
1276                 rtspTrans->server_portIsSet = true;
1277             }
1278             else
1279             {
1280                 nxtPtr = curEndPtr + 1;
1281                 *curEndPtr = '-';
1282                 PV_atoi(nxtPtr, 'd', atoi_tmp);
1283                 tmp = atoi_tmp;
1284                 if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1285                 {
1286                     amMalformed = RTSPErrorSyntax;
1287                     if (sepPtr)
1288                     {
1289                         *sepPtr = ';';
1290                     };
1291                     break;
1292                 }
1293                 rtspTrans->server_port2 = tmp;
1294                 rtspTrans->server_portIsSet = true;
1295             }
1296         }
1297         else if (!oscl_strncmp(startPtr, ttl_str, ttl_str_len))
1298         {
1299             nxtPtr = startPtr + ttl_str_len;
1300             int tmp;
1301             uint32 atoi_tmp;
1302             PV_atoi(nxtPtr, 'd', atoi_tmp);
1303             tmp = atoi_tmp;
1304             if (tmp < 0 || tmp > 255)
1305             {
1306                 amMalformed = RTSPErrorSyntax;
1307                 if (sepPtr)
1308                 {
1309                     *sepPtr = ';';
1310                 };
1311                 break;
1312             }
1313             rtspTrans->ttl = tmp;
1314             rtspTrans->ttlIsSet = true;
1315         }
1316         else if (!oscl_strncmp(startPtr, mode_str, mode_str_len))
1317         {
1318             rtspTrans->mode.play_mode = false;
1319             rtspTrans->mode.record_mode = false;
1320             nxtPtr = startPtr + mode_str_len;
1321             rtspTrans->modeIsSet = true;
1322             char *quotePtr = NULL;
1323             const char *wordEndPtr;
1324             if (*nxtPtr == '\"')
1325             {
1326                 ++nxtPtr;
1327                 if (NULL != (quotePtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "\""))))
1328                 {
1329                     *quotePtr = '\0';
1330                 }
1331             }
1332             while (nxtPtr < endPtr)
1333             {
1334                 if (NULL == (wordEndPtr = oscl_strstr(nxtPtr, ",")))
1335                 {
1336                     wordEndPtr = endPtr;
1337                 }
1338 
1339                 if (!oscl_strncmp(nxtPtr, "PLAY", wordEndPtr - nxtPtr))
1340                 {
1341                     rtspTrans->mode.play_mode = true;
1342                 }
1343                 else if (!oscl_strncmp(nxtPtr, "RECORD", wordEndPtr - nxtPtr))
1344                 {
1345                     rtspTrans->mode.record_mode = true;
1346                 }
1347                 nxtPtr = wordEndPtr + 1;
1348 
1349             }
1350 
1351             if (quotePtr)
1352             {
1353                 *quotePtr = '\"';
1354             }
1355         }
1356         else if (!oscl_strncmp(startPtr, port_str, port_str_len))
1357         {
1358             int tmp;
1359             uint32 atoi_tmp;
1360             nxtPtr = startPtr + port_str_len;
1361             char *curEndPtr = OSCL_CONST_CAST(char*, oscl_strstr(nxtPtr, "-"));
1362             if (curEndPtr) *curEndPtr = '\0';
1363             PV_atoi(nxtPtr, 'd', atoi_tmp);
1364             tmp = atoi_tmp;
1365             if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1366             {
1367                 amMalformed = RTSPErrorSyntax;
1368                 if (sepPtr)
1369                 {
1370                     *sepPtr = ';';
1371                 };
1372                 break;
1373             }
1374             rtspTrans->port1 = tmp;
1375             if (!curEndPtr)
1376             {
1377                 if (rtspTrans->port1 >= PORT_MAX_VALUE)
1378                 {
1379                     amMalformed = RTSPErrorSyntax;
1380                     if (sepPtr)
1381                     {
1382                         *sepPtr = ';';
1383                     };
1384                     break;
1385                 }
1386                 rtspTrans->port2 = rtspTrans->port1 + 1;
1387                 rtspTrans->portIsSet = true;
1388             }
1389             else
1390             {
1391                 nxtPtr = curEndPtr + 1;
1392                 *curEndPtr = '-';
1393                 PV_atoi(nxtPtr, 'd', atoi_tmp);
1394                 tmp = atoi_tmp;
1395                 if (tmp < PORT_MIN_VALUE || tmp > PORT_MAX_VALUE)
1396                 {
1397                     amMalformed = RTSPErrorSyntax;
1398                     if (sepPtr)
1399                     {
1400                         *sepPtr = ';';
1401                     };
1402                     break;
1403                 }
1404                 rtspTrans->port2 = tmp;
1405                 rtspTrans->portIsSet = true;
1406             }
1407         }
1408         else if (!oscl_strncmp(startPtr, layers_str, layers_str_len))
1409         {
1410             nxtPtr = startPtr + layers_str_len;
1411             PV_atoi(nxtPtr, 'd', rtspTrans->layers);
1412             rtspTrans->layersIsSet = true;
1413         }
1414         else if (!oscl_strncmp(startPtr, ssrc_str, ssrc_str_len))
1415         {
1416             nxtPtr = startPtr + ssrc_str_len;
1417             rtspTrans->ssrc = 0;
1418             rtspTrans->ssrcIsSet = false;
1419             if (!PV_atoi(nxtPtr, 'x', rtspTrans->ssrc))
1420             {
1421                 amMalformed = RTSPErrorSyntax;
1422                 if (sepPtr)
1423                 {
1424                     *sepPtr = ';';
1425                 };
1426                 break;
1427             }
1428             rtspTrans->ssrcIsSet = true;
1429         }
1430 
1431         if (sepPtr)
1432         {
1433             *sepPtr = ';';
1434         }
1435 
1436         startPtr = endPtr + 1;
1437 
1438     }
1439 
1440     if (transSepPtr)
1441     {
1442         // put the separator character back
1443         *transSepPtr = ',';
1444         trans = transSepPtr;
1445     }
1446     else
1447     {
1448         trans = final_end;
1449     }
1450 
1451 }
1452 
1453 void
parseRTPInfo(uint16 fieldIdx)1454 RTSPIncomingMessage::parseRTPInfo(uint16 fieldIdx)
1455 {
1456     char * cPtr;
1457     char * finishPtr;
1458 
1459     cPtr = const_cast<char*>(fieldVals[ fieldIdx ].c_str());
1460     finishPtr = cPtr + fieldVals[ fieldIdx ].length();
1461 
1462     do
1463     {
1464         parseOneRTPInfoEntry(cPtr, finishPtr);
1465 
1466     }
1467     while (RTSPOk == amMalformed
1468             &&  cPtr < finishPtr
1469           );
1470 }
1471 
1472 void
parseOneRTPInfoEntry(char * & cPtr,char * finishPtr)1473 RTSPIncomingMessage::parseOneRTPInfoEntry(char * & cPtr, char * finishPtr)
1474 {
1475     bool   getOut;
1476     char * subFieldName;
1477     char * separator;
1478     char * endOfIt;
1479 
1480     // check the counter
1481     //
1482     if (RTSP_MAX_NUMBER_OF_RTP_INFO_ENTRIES == numOfRtpInfoEntries)
1483     { // limit reached
1484         amMalformed = RTSPErrorSyntax;  // should it be different?
1485         return;
1486     }
1487     ++numOfRtpInfoEntries;
1488 
1489     // skip comma, if necessary
1490     //
1491     if (CHAR_COMMA == *cPtr)
1492     {
1493         ++cPtr;
1494     }
1495 
1496     getOut = false;
1497 
1498     while ((!getOut) && cPtr < finishPtr && CHAR_COMMA != *cPtr)
1499     {
1500         // reset pointers
1501 
1502         subFieldName = NULL;
1503         separator = NULL;
1504         endOfIt = NULL;
1505 
1506         // skip whitespace
1507 
1508         while (cPtr < finishPtr
1509                 && (CHAR_SPACE == *cPtr
1510                     || CHAR_TAB  == *cPtr
1511                     || CHAR_SEMICOLON == *cPtr
1512                     || CHAR_NULL == *cPtr
1513                    )
1514               )
1515         {
1516             ++cPtr;
1517         }
1518         if (cPtr >= finishPtr  || CHAR_COMMA  == *cPtr)
1519         {
1520             return;
1521         }
1522 
1523         // we see the beginning
1524         subFieldName = cPtr;
1525 
1526         // get the separator
1527         while (cPtr < finishPtr
1528                 && CHAR_EQUAL != *cPtr
1529               )
1530         {
1531             ++cPtr;
1532         }
1533         if (cPtr >= finishPtr)
1534         {
1535             return;
1536         }
1537         // we see the separator
1538         separator = cPtr;
1539 
1540         // get the end of it
1541         while (cPtr < finishPtr
1542                 && CHAR_SEMICOLON != *cPtr
1543                 && CHAR_SPACE != *cPtr
1544                 && CHAR_TAB != *cPtr
1545                 && CHAR_COMMA != *cPtr
1546               )
1547         {
1548             ++cPtr;
1549         }
1550 
1551         endOfIt = cPtr;
1552 
1553         if (3 == separator - subFieldName)
1554         { // url?
1555             if (('u' == (subFieldName[0] | OSCL_ASCII_CASE_MAGIC_BIT))
1556                     && ('r' == (subFieldName[1] | OSCL_ASCII_CASE_MAGIC_BIT))
1557                     && ('l' == (subFieldName[2] | OSCL_ASCII_CASE_MAGIC_BIT))
1558                )
1559             {
1560                 rtpInfo[ numOfRtpInfoEntries-1 ].url.setPtrLen(
1561                     separator + 1,
1562                     endOfIt - separator - 1
1563                 );
1564                 rtpInfo[ numOfRtpInfoEntries-1 ].urlIsSet = true;
1565                 if (CHAR_COMMA == *endOfIt)
1566                 {
1567                     getOut = true;
1568                 }
1569                 *endOfIt = CHAR_NULL;
1570                 if (getOut)
1571                 {
1572                     // skip ahead beyond the whitespace
1573                     // since we overwrote the comma with a NULL
1574                     while (cPtr < finishPtr
1575                             && (CHAR_SPACE == *cPtr
1576                                 || CHAR_TAB  == *cPtr
1577                                 || CHAR_SEMICOLON == *cPtr
1578                                 || CHAR_NULL == *cPtr
1579                                )
1580                           )
1581                     {
1582                         ++cPtr;
1583                     }
1584                 }
1585             }
1586             // or, maybe, seq?
1587             else if (('s' == (subFieldName[0] | OSCL_ASCII_CASE_MAGIC_BIT))
1588                      && ('e' == (subFieldName[1] | OSCL_ASCII_CASE_MAGIC_BIT))
1589                      && ('q' == (subFieldName[2] | OSCL_ASCII_CASE_MAGIC_BIT))
1590                     )
1591             {
1592                 uint32 atoi_tmp;
1593                 PV_atoi(separator + 1, 'd', atoi_tmp);
1594                 rtpInfo[ numOfRtpInfoEntries-1 ].seq  = (RtpSeqType)atoi_tmp;
1595 
1596                 rtpInfo[ numOfRtpInfoEntries-1 ].seqIsSet = true;
1597             }
1598             else
1599             {
1600                 amMalformed = RTSPErrorSyntax;
1601                 return;
1602             }
1603         }
1604         else if (7 == separator - subFieldName)
1605         { // rtptime?
1606             if (('r' == (subFieldName[0] | OSCL_ASCII_CASE_MAGIC_BIT))
1607                     && ('t' == (subFieldName[1] | OSCL_ASCII_CASE_MAGIC_BIT))
1608                     && ('p' == (subFieldName[2] | OSCL_ASCII_CASE_MAGIC_BIT))
1609                     && ('t' == (subFieldName[3] | OSCL_ASCII_CASE_MAGIC_BIT))
1610                     && ('i' == (subFieldName[4] | OSCL_ASCII_CASE_MAGIC_BIT))
1611                     && ('m' == (subFieldName[5] | OSCL_ASCII_CASE_MAGIC_BIT))
1612                     && ('e' == (subFieldName[6] | OSCL_ASCII_CASE_MAGIC_BIT))
1613                )
1614             {
1615                 uint32 rtptime = 0;
1616                 PV_atoi((separator + 1), 'd', rtptime);
1617                 rtpInfo[ numOfRtpInfoEntries-1 ].rtptime = rtptime;
1618                 rtpInfo[ numOfRtpInfoEntries-1 ].rtptimeIsSet = true;
1619             }
1620             else
1621             {
1622                 amMalformed = RTSPErrorSyntax;
1623                 return;
1624             }
1625         }
1626 
1627         else
1628         {
1629             amMalformed = RTSPErrorSyntax;
1630             return;
1631         }
1632 
1633         cPtr = endOfIt;
1634     }
1635 }
1636 
1637 #if (defined(ASF_STREAMING) || defined(RTSP_PLAYLIST_SUPPORT))
1638 OSCL_EXPORT_REF bool
parseEntityBody(RTSPEntityBody * entityBody)1639 RTSPIncomingMessage::parseEntityBody(RTSPEntityBody * entityBody)
1640 {
1641     char * endOfMessage = (char *) entityBody->ptr + entityBody->len;
1642     char * ptr;
1643 
1644     for (ptr = (char *) entityBody->ptr;
1645             ptr < endOfMessage ;
1646             ++numPtrFields
1647         )
1648     {
1649         char * endOfValue = ptr;
1650         while (CHAR_LF != *(endOfValue)
1651                 &&  CHAR_CR != *(endOfValue)
1652                 &&  CHAR_NULL != *(endOfValue))
1653         {
1654             ++endOfValue;
1655         }
1656 
1657         if (CHAR_CR == *(endOfValue) && CHAR_LF == *(endOfValue + 1))
1658         {
1659             // need to increment endOfValue for CR-LF, because
1660             // it is needed later to step into the next field by shifting by 1
1661             *(endOfValue) = CHAR_NULL;
1662             *(++endOfValue) = CHAR_NULL;
1663         }
1664         else
1665         {
1666             *endOfValue = CHAR_NULL;
1667         }
1668 
1669         char * separator = ptr;
1670 
1671         while ((CHAR_COLON != *separator)
1672                 && (CHAR_NULL != *separator)
1673               )
1674         {
1675             ++separator;
1676         }
1677 
1678         if (CHAR_COLON != *separator)
1679         {
1680             amMalformed = RTSPErrorSyntax;
1681         }
1682         else
1683         {   // field is pretty much normal
1684 
1685             *separator = CHAR_NULL;
1686 
1687             // get name pointer
1688             char * namePtr = ptr;
1689             // eat through trailing whitespace
1690             for (char * wPtr1 = separator - 1;
1691                     (wPtr1 >= namePtr)
1692                     && ((*wPtr1 >= 0x09 && *wPtr1 <= 0x0D) || *wPtr1 == 0x20);
1693                     --wPtr1)
1694             {
1695                 *wPtr1 = CHAR_NULL;
1696             }
1697             // eat through leading whitespace
1698             while ((*namePtr >= 0x09 && *namePtr <= 0x0D) || *namePtr == 0x20)
1699             {
1700                 ++namePtr;
1701             }
1702 
1703             // get value pointer
1704             char * valuePtr = separator + 1;
1705             // eat through trailing whitespace
1706             for (char * wPtr2 = endOfValue - 1;
1707                     (wPtr2 > separator)
1708                     && ((*wPtr2 >= 0x09 && *wPtr2 <= 0x0D) || *wPtr2 == 0x20);
1709                     --wPtr2)
1710             {
1711                 *wPtr2 = CHAR_NULL;
1712             }
1713             //eat through leading whitespace
1714             while ((*valuePtr >= 0x09 && *valuePtr <= 0x0D) || *valuePtr == 0x20)
1715             {
1716                 ++valuePtr;
1717             }
1718 
1719             // set the pointers
1720 
1721             fieldKeys[ numPtrFields ] = namePtr;
1722             fieldVals[ numPtrFields ] = valuePtr;
1723 
1724             // now, figure out if we are supposed to recognize this
1725             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
1726                         RtspRecognizedFieldSessionId))
1727             {
1728                 sessionId = fieldVals[ numPtrFields ];
1729                 sessionIdIsSet = true;
1730             }
1731 //RTSP_PAR_COM_CONSTANTS_H_
1732 #define RtspRecognizedFieldEOF "EOF"
1733 
1734             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
1735                         RtspRecognizedFieldEOF))
1736             {
1737                 eofField = fieldVals[ numPtrFields ];
1738                 eofFieldIsSet = true;
1739             }
1740 #ifdef RTSP_PLAYLIST_SUPPORT
1741             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
1742                         RtspRecognizedFieldPlaylistRange))
1743             {
1744                 playlistRangeField = fieldVals[ numPtrFields ];  // not sure we really need to store this, but do it for now anyway
1745                 playlistRangeFieldIsSet = true;
1746                 // now parse the entry
1747                 /*playlistRangeField.setPtrLen("",0);
1748                 playlistRangeFieldIsSet = false;
1749                 playlistErrorFieldIsSet = false;
1750                 playlistErrorFieldCount = 0;
1751                 playlistRangeUrl.setPtrLen("",0);
1752                 playlistRangeClipIndex=0;
1753                 playlistRangeClipOffset=0;
1754                 playlistRangeNptTime=0;*/
1755                 char* curr = valuePtr; // set curr to the start of the entry after the colon, whitespace was already removed
1756                 StrPtrLen eStr;
1757 
1758                 eStr = curr;
1759                 // look for playlist_play_time
1760                 const StrPtrLen RtspPlaylistPlayTimeStr = "playlist_play_time";
1761                 if (0 && RtspPlaylistPlayTimeStr.isCIPrefixOf(eStr))
1762                 {
1763                     curr += 18; // move past "playlist_play_time"
1764                     // eat through leading whitespace
1765                     while ((*curr >= 0x09 && *curr <= 0x0D) || *curr == 0x20)
1766                     {
1767                         ++curr;
1768                     }
1769                     if (*curr != CHAR_EQUAL)
1770                     {
1771                         // problem
1772                     }
1773                     // could be more whitespace
1774                     while ((*curr >= 0x09 && *curr <= 0x0D) || *curr == 0x20)
1775                     {
1776                         ++curr;
1777                     }
1778                     if (*curr != CHAR_LT)
1779                     {
1780                         // problem
1781                     }
1782                     ++curr; // move past '<'
1783                     // could be even more whitespace
1784                     while ((*curr >= 0x09 && *curr <= 0x0D) || *curr == 0x20)
1785                     {
1786                         ++curr;
1787                     }
1788                     // now comes the url
1789                     // find the end first
1790                     char* end = curr;
1791                     while (*end != CHAR_COMMA)
1792                     {
1793                         ++end;
1794                     }
1795                     char* endtmp = end;
1796                     // may have trailing whitespace
1797                     if (*(endtmp - 1) == 0x09 || *(endtmp - 1) == 0x0D || *(endtmp - 1) == 0x20)
1798                     {
1799                         --endtmp;
1800                         while ((*endtmp >= 0x09 && *endtmp <= 0x0D) || *endtmp == 0x20)
1801                         {
1802                             --endtmp;
1803                         }
1804                         // will be on a non space char, move it over
1805                         ++endtmp;
1806                     }
1807                     // to do - not sure if we need a '\0' here..
1808                     playlistRangeUrl.setPtrLen(curr, endtmp - curr);
1809 
1810                     curr = end + 1;
1811                     // next should be the clip index
1812                     // of course, could be more whitespace
1813                     while ((*curr >= 0x09 && *curr <= 0x0D) || *curr == 0x20)
1814                     {
1815                         ++curr;
1816                     }
1817                     // find next comma
1818                     end = curr;
1819                     while (*end != CHAR_COMMA)
1820                     {
1821                         ++end;
1822                     }
1823                     // may have trailing whitespace
1824                     // dont worry about it for now  atoi should be ok
1825                     /*if(*(end-1) == 0x09 ||*(end-1) == 0x0D ||*(end-1) == 0x20)
1826                     {
1827                     --end;
1828                     while( (*end >= 0x09 && *end <= 0x0D) || *end == 0x20 )
1829                     {
1830                     --end;
1831                     }
1832                     // will be on a non space char, move it over
1833                     ++end;
1834                     }*/
1835                     // finally get the value
1836                     uint32 atoi_tmp;
1837                     PV_atoi(curr, 'd', atoi_tmp);
1838                     playlistRangeClipIndex = atoi_tmp;
1839 
1840                     curr = end + 1;
1841                     // next should be the clip offset
1842                     // of course, could be more whitespace
1843                     while ((*curr >= 0x09 && *curr <= 0x0D) || *curr == 0x20)
1844                     {
1845                         ++curr;
1846                     }
1847                     // find next comma
1848                     end = curr;
1849                     while (*end != CHAR_GT)
1850                     {
1851                         ++end;
1852                     }
1853                     // may have trailing whitespace
1854                     // dont worry about it for now  atoi should be ok
1855                     /*if(*(end-1) == 0x09 ||*(end-1) == 0x0D ||*(end-1) == 0x20)
1856                     {
1857                     --end;
1858                     while( (*end >= 0x09 && *end <= 0x0D) || *end == 0x20 )
1859                     {
1860                     --end;
1861                     }
1862                     // will be on a non space char, move it over
1863                     ++end;
1864                     }*/
1865                     // finally get the value
1866                     PV_atoi(curr, 'd', atoi_tmp);
1867                     playlistRangeClipOffset = atoi_tmp;
1868 
1869                 }
1870                 else
1871                 {
1872                     // problem
1873                 }
1874             }
1875             if (fieldKeys[ numPtrFields ].isCIEquivalentTo(
1876                         RtspRecognizedFieldPlaylistError))
1877             {
1878                 if (playlistErrorFieldCount < RTSP_MAX_NUMBER_OF_PLAYLIST_ERROR_ENTRIES)
1879                 {
1880                     playlistErrorField[playlistErrorFieldCount++] = fieldVals[ numPtrFields ];  // this needs to be an array since the number can be unbounded
1881                     playlistErrorFieldIsSet = true;
1882                 }
1883             }
1884 #endif
1885         }
1886         ptr = endOfValue + 1;
1887     }
1888     return true;
1889 }
1890 
1891 #endif
1892 
1893