• 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 #include "rtsp_par_com.h"
19 #include "oscl_string_utils.h"
20 #include "oscl_dll.h"
21 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()22 OSCL_DLL_ENTRY_POINT_DEFAULT()
23 
24 // This function searches for a substring in a string, just like strstr(), but
25 // with a couple of specific features:
26 //  1. It is case-insensitive, so "Ces" can be found in the word "success";
27 //  2. It is looking for substrings left-to-right, and if the string starts
28 //  matching, the state of search gets increased; if the whole string does not
29 //  match, this function does NOT step back; therefore, the string "KoKoMo"
30 //  will not be found correctly in the string "KoKoKoMo"; however, it will
31 //  work for substrings that have unique beginnings that don't repeat
32 //  themselves, such as "Content-length" ('c' is never repeated). Therefore,
33 //  such a search works for "Content-length", which is all that RtspParser
34 //  needs.
35 //
36 // This function is not part of OSCL precisely because of its limitations;
37 // however, these limitations are ok here because they contribute to the
38 // overall performance by not doing extra steps.
39 //
40 // added the size argument to deal with Real cloaking "H\02\00\00" 02/22/06
41 static inline char *
42 ci_local_strstr(char * bigString, int32 bigStringSize,
43                 const StrPtrLen & subString
44                )
45 {
46     uint32 state = 0;
47     uint32 targetState = subString.length();
48     char * pp;
49     //char * eos = bigString + oscl_strlen(bigString);
50     char * eos = bigString + bigStringSize;
51 
52     for (pp = bigString;
53             pp != eos;
54             ++pp
55         )
56     {
57         if (OSCL_ASCII_CASE_MAGIC_BIT
58                 == (((*pp) ^(subString.c_str()[state])) | OSCL_ASCII_CASE_MAGIC_BIT)
59            )
60         {
61             ++state;
62             if (state == targetState)
63             {
64                 return pp - targetState + 1;
65             }
66         }
67         else
68         {
69             state = 0;
70         }
71 
72     }
73 
74     return NULL;
75 }
76 
77 
78 static inline bool
isspaceNotNL(char ch)79 isspaceNotNL(char ch)
80 {
81     if ((CHAR_CR == ch) || (CHAR_LF == ch) || (CHAR_NULL == ch))
82     {
83         return false;
84     }
85 
86     return (0 != ((ch >= 0x09 && ch <= 0x0D) || ch == 0x20));
87 }
88 
89 OSCL_EXPORT_REF RTSPParser::ParserState
getState()90 RTSPParser::getState()
91 {
92     ParserState stateToReturn;
93 
94     switch (internalState)
95     {
96         case    IS_WAITING_FOR_REQUEST_MEMORY:
97             stateToReturn = WAITING_FOR_REQUEST_MEMORY;
98             break;
99 
100         case    IS_LOOKING_FOR_END_OF_REQUEST:
101         case  IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY:
102         case  IS_SKIPPING_OVER_ENTITY_BODY:
103         case  IS_LOOKING_FOR_RESYNC:
104         case  IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA:
105         case  IS_SKIPPING_OVER_EMBEDDED_DATA:
106             stateToReturn = WAITING_FOR_DATA;
107             break;
108 
109         case  IS_START_LOOKING_FOR_RESYNC:
110             stateToReturn = ERROR_REQUEST_TOO_BIG;
111             internalState = IS_LOOKING_FOR_RESYNC;
112             break;
113 
114         case  IS_WAITING_FOR_ENTITY_BODY_MEMORY:
115             stateToReturn = WAITING_FOR_ENTITY_BODY_MEMORY;
116             break;
117 
118         case IS_WAITING_FOR_EMBEDDED_DATA_MEMORY:
119             stateToReturn = WAITING_FOR_EMBEDDED_DATA_MEMORY;
120             break;
121 
122         case  IS_ERROR_REQUEST_TOO_BIG:
123         case    IS_REQUEST_IS_READY:
124             // both states are processed the same way,
125             // except that the state returned is different
126             //
127             stateToReturn = (IS_REQUEST_IS_READY == internalState) ?
128                             REQUEST_IS_READY : ERROR_REQUEST_TOO_BIG;
129 
130             // take care of the entity bodies
131             if (0 == ebFullSizeExpected)
132             { // no eb expected
133                 internalState = IS_WAITING_FOR_REQUEST_MEMORY;
134             }
135             else
136             { // check to see the nature of the entity body. if it
137                 // is embedded data, change internal state appropriately
138                 if (requestStruct->method != METHOD_BINARY_DATA)
139                 {
140                     internalState = IS_WAITING_FOR_ENTITY_BODY_MEMORY;
141                 }
142                 else
143                 {
144                     internalState = IS_WAITING_FOR_EMBEDDED_DATA_MEMORY;
145                 }
146             }
147             continueProcessing();
148 
149             break;
150 
151         case  IS_ENTITY_BODY_IS_READY:
152             stateToReturn = ENTITY_BODY_IS_READY;
153             internalState = IS_WAITING_FOR_REQUEST_MEMORY;
154             break;
155 
156         case IS_EMBEDDED_DATA_IS_READY:
157             stateToReturn = EMBEDDED_DATA_IS_READY;
158             internalState = IS_WAITING_FOR_REQUEST_MEMORY;
159             break;
160 
161         default:
162 
163             // now, this is an internal error
164             internalState = IS_INTERNAL_ERROR;
165             stateToReturn = INTERNAL_ERROR;
166     }
167 
168     return stateToReturn;
169 }
170 
RTSPParser()171 OSCL_EXPORT_REF RTSPParser::RTSPParser()
172 {
173     flush();
174 };
175 
176 void
continueProcessing()177 RTSPParser::continueProcessing()
178 {
179     switch (internalState)
180     {
181         case IS_WAITING_FOR_REQUEST_MEMORY:
182             break;
183 
184         case IS_LOOKING_FOR_END_OF_REQUEST:
185             lookForEndOfRequest();
186             break;
187 
188         case IS_START_LOOKING_FOR_RESYNC:
189         case IS_LOOKING_FOR_RESYNC:
190             lookForResync();
191             break;
192 
193         case IS_WAITING_FOR_ENTITY_BODY_MEMORY:
194             // nothing to do, really
195             break;
196 
197         case IS_SKIPPING_OVER_ENTITY_BODY:
198             skipOverEntityBody();
199             break;
200 
201         case IS_STARTING_TO_FILL_OUT_ENTITY_BODY:
202             startFillingOutEntityBody();
203             break;
204 
205         case IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY:
206             break;
207 
208         case IS_WAITING_FOR_EMBEDDED_DATA_MEMORY:
209             break;
210 
211         case IS_SKIPPING_OVER_EMBEDDED_DATA:
212             skipOverEmbeddedData();
213             break;
214 
215         case IS_STARTING_TO_FILL_OUT_EMBEDDED_DATA:
216             startFillingOutEmbeddedData();
217             break;
218 
219         case IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA:
220             break;
221 
222 
223         default:
224             internalState = IS_INTERNAL_ERROR;
225     }
226 }
227 
228 OSCL_EXPORT_REF bool
registerNewRequestStruct(RTSPIncomingMessage * newRequestStruct)229 RTSPParser::registerNewRequestStruct(RTSPIncomingMessage * newRequestStruct)
230 {
231     if (IS_WAITING_FOR_REQUEST_MEMORY != internalState)
232     {
233         return false;
234     }
235 
236     requestStruct = newRequestStruct;
237 
238     internalState = IS_LOOKING_FOR_END_OF_REQUEST;
239 
240     continueProcessing();
241 
242     return true;
243 }
244 
245 OSCL_EXPORT_REF const StrPtrLen *
getDataBufferSpec()246 RTSPParser::getDataBufferSpec()
247 {
248     if (internalState == IS_LOOKING_FOR_END_OF_REQUEST
249             ||  internalState == IS_START_LOOKING_FOR_RESYNC
250             ||  internalState == IS_LOOKING_FOR_RESYNC
251        )
252     {
253         // normal case - just put stuff into the buffer
254         dataBufferSpec.setPtrLen(mainBufferSpace,
255                                  mainBuffer + RTSP_PARSER_BUFFER_SIZE - mainBufferSpace);
256     }
257 
258     else if (internalState == IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY
259              || internalState == IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA
260             )
261     {
262 
263         // the whole entity body arithmetic is done here, not in
264         // registerDataWritten(), so here it comes
265         while (entityBody[ebCurrentIndex].len == ebCurrentOffset)
266         {
267             ++ebCurrentIndex;
268             ebCurrentOffset = 0;
269         }
270 
271         // so, we are at the appropriate fragment;
272         // figure out which is smaller
273         //
274         uint32 sizePossibleToWrite =
275             entityBody[ebCurrentIndex].len - ebCurrentOffset;
276         uint32 sizeLeftToWrite = ebFullSizeExpected - ebSizeCoveredSoFar;
277 
278         // set the data buffer spec
279         dataBufferSpec.setPtrLen(
280             static_cast<char*>(entityBody[ebCurrentIndex].ptr) + ebCurrentOffset,
281             (sizePossibleToWrite < sizeLeftToWrite) ?
282             sizePossibleToWrite : sizeLeftToWrite
283         );
284     }
285 
286     else if (IS_SKIPPING_OVER_ENTITY_BODY == internalState)
287     {
288         mainBufferEntry = mainBuffer;
289         mainBufferSpace = mainBuffer;
290 
291         dataBufferSpec.setPtrLen(mainBufferSpace, RTSP_PARSER_BUFFER_SIZE);
292     }
293 
294     else
295     {
296         // it's some kind of inconsistency on the Engine's part, or Parser's
297         // internal error
298 
299         return NULL;
300     }
301 
302     return & dataBufferSpec;
303 }
304 
305 void
lookForEndOfRequest()306 RTSPParser::lookForEndOfRequest()
307 {
308     // eorptr = mainBufferEntry;
309     uint32   newMessageSize;
310 
311     *mainBufferSpace = CHAR_NULL;
312 
313     bool  shouldMoveOverToBeginning = false;
314 
315     // now, it's either a binary data thing, or a regular message
316     if (CHAR_DOLLAR == *mainBufferEntry)
317     {
318 
319         if (mainBufferSpace - mainBufferEntry < 4)
320         { // not a complete message
321             shouldMoveOverToBeginning = true;
322         }
323         else
324         { // it is a complete thing
325             requestStruct->msgType = RTSPRequestMsg;
326             requestStruct->method = METHOD_BINARY_DATA;
327 
328             requestStruct->contentLength =
329                 ((static_cast<uint16>(
330                       (*(reinterpret_cast<unsigned char*>(mainBufferEntry + 2))
331                       ))) << 8)
332                 + static_cast<uint16>(
333                     *(reinterpret_cast<unsigned char*>(mainBufferEntry + 3))
334                 );
335             requestStruct->contentLengthIsSet = true;
336 
337             *(mainBufferEntry + 2) = CHAR_NULL;
338             requestStruct->contentType = mainBufferEntry + 1;
339             requestStruct->contentTypeIsSet = true;
340 
341             requestStruct->channelID = static_cast<uint8>(
342                                            *(reinterpret_cast<unsigned char*>(mainBufferEntry + 1)));
343 
344             mainBufferEntry += 4;
345 
346             eorptr = mainBufferEntry;
347 
348             ebFullSizeExpected = requestStruct->contentLength;
349 
350             internalState = IS_REQUEST_IS_READY;
351 
352             return;
353         }
354     }
355 
356     else
357     { // it's a normal message
358         bool found = false;
359 
360         for (/*eorptr = mainBufferEntry*/; eorptr < mainBufferSpace - 1; ++eorptr)
361         {
362             if (CHAR_LF == *eorptr || CHAR_CR == *eorptr)
363             {   // it's a possible
364 
365                 // is it two newlines?
366                 if (*eorptr == *(eorptr + 1))
367                 {   // yes, CR-CR or LF-LF format
368 
369                     found = true;
370                     eorptr += 2;
371                     break;
372                 }
373                 else if ((eorptr <= mainBufferSpace - 4)
374                          && (CHAR_CR == *(eorptr)) && (CHAR_LF == *(eorptr + 1))
375                          && (CHAR_CR == *(eorptr + 2)) && (CHAR_LF == *(eorptr + 3))
376                         )
377                 {   // yes, MS-WINDOWS format
378 
379                     found = true;
380                     eorptr += 4;
381                     break;
382                 }
383                 // else, continue on
384             }
385         }
386 
387         if (found)
388         {
389             // transfer the buffer, if necessary
390 
391             newMessageSize = eorptr - mainBufferEntry;
392 
393             // quickly take a peek at content-length
394             char * cl = ci_local_strstr(mainBufferEntry, newMessageSize,
395                                         RtspRecognizedFieldContentLength);
396             if (NULL == cl)
397             { // nothing visible
398                 ebFullSizeExpected = 0;
399             }
400             else if (cl >= mainBufferEntry + newMessageSize)
401             { // it's not part of this particular message
402                 ebFullSizeExpected = 0;
403             }
404             else
405             {
406                 cl += oscl_strlen(RtspRecognizedFieldContentLength);
407                 while (cl < eorptr && (isspaceNotNL(*cl) || (CHAR_COLON == *cl)))
408                 {
409                     ++cl;
410                 }
411 
412                 uint32 atoi_tmp;
413                 PV_atoi(cl, 'd', atoi_tmp);
414                 ebFullSizeExpected = atoi_tmp;
415             }
416 
417             // now, on with the moving around ...
418 
419             if (RTSP_MAX_FULL_REQUEST_SIZE < newMessageSize)
420             {
421                 // request too big
422 
423                 oscl_memcpy(requestStruct->secondaryBuffer, mainBufferEntry,
424                             RTSP_MAX_FULL_REQUEST_SIZE);
425                 requestStruct->secondaryBuffer[RTSP_MAX_FULL_REQUEST_SIZE] = CHAR_NULL;
426 
427                 requestStruct->secondaryBufferSizeUsed = newMessageSize;
428 
429                 requestStruct->amMalformed = RTSPErrorTooBig;
430 
431                 mainBufferEntry += newMessageSize;
432 
433                 eorptr = mainBufferEntry;
434 
435                 internalState = IS_ERROR_REQUEST_TOO_BIG;
436             }
437             else
438             {
439                 // everything is ok
440 
441                 oscl_memcpy(requestStruct->secondaryBuffer, mainBufferEntry,
442                             newMessageSize);
443                 requestStruct->secondaryBuffer[ newMessageSize ] = CHAR_NULL;
444 
445                 requestStruct->secondaryBufferSizeUsed = newMessageSize;
446 
447                 mainBufferEntry += newMessageSize;
448 
449                 eorptr = mainBufferEntry;
450 
451                 internalState = IS_REQUEST_IS_READY;
452             }
453 
454             dealWithLineContinuations(requestStruct);
455 
456             requestStruct->parseFirstFields();
457 
458         }
459         else
460         {
461             shouldMoveOverToBeginning = true;
462         }
463     }
464 
465     if (shouldMoveOverToBeginning)
466     {
467         // i.e. end of request was not found
468 
469         int sizeUsedSoFar = mainBufferSpace - mainBufferEntry;
470 
471         if (RTSP_PARSER_BUFFER_SIZE == sizeUsedSoFar)
472         {   // we hit the parser's buffer size
473             internalState = IS_START_LOOKING_FOR_RESYNC;
474             continueProcessing();
475 
476             return;
477         }
478 
479         if (mainBufferEntry != mainBuffer)
480         {
481             oscl_memmove(mainBuffer, mainBufferEntry, sizeUsedSoFar);
482             mainBufferEntry = mainBuffer;
483             eorptr = mainBufferEntry;
484             mainBufferSpace = mainBufferEntry + sizeUsedSoFar;
485         }
486         else
487         { // rewind eorptr
488 
489             eorptr -= 4;
490 
491             eorptr = (eorptr < mainBufferEntry) ? mainBufferEntry : eorptr;
492         }
493     }
494 }
495 
496 OSCL_EXPORT_REF bool
registerDataBufferWritten(uint32 sizeWritten)497 RTSPParser::registerDataBufferWritten(uint32 sizeWritten)
498 {
499     // take care of entity bodies and stuff
500 
501     if (IS_LOOKING_FOR_END_OF_REQUEST == internalState)
502     { // the memory being filled out is Parser's
503         mainBufferSpace += sizeWritten;
504 
505         continueProcessing();
506 
507         return true;
508     }
509     else if (IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY == internalState
510              || IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA == internalState
511             )
512     { // the memory being filled out is Engine's entity body
513         ebCurrentOffset += sizeWritten;
514         ebSizeCoveredSoFar += sizeWritten;
515 
516         if (ebSizeCoveredSoFar == ebFullSizeExpected)
517         {
518             eorptr = mainBufferEntry;
519             if (internalState == IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY)
520             {
521                 internalState = IS_ENTITY_BODY_IS_READY;
522             }
523             else // internalState=IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA
524             {
525                 internalState = IS_EMBEDDED_DATA_IS_READY;
526             }
527         }
528 
529         return true;
530     }
531 
532     else if (IS_SKIPPING_OVER_ENTITY_BODY == internalState)
533     {
534         mainBufferSpace += sizeWritten;
535         continueProcessing();
536     }
537 
538     else if (IS_START_LOOKING_FOR_RESYNC == internalState
539              ||  IS_LOOKING_FOR_RESYNC == internalState
540             )
541     {
542         mainBufferSpace += sizeWritten;
543         continueProcessing();
544     }
545 
546     else
547     {
548         // some kind of error on Engine's part, or Parser's internal inconsistency
549         return false;
550     }
551 
552     return false; // to appease compiler
553 }
554 
555 OSCL_EXPORT_REF bool
registerEntityBody(RTSPEntityBody * newBody)556 RTSPParser::registerEntityBody(RTSPEntityBody * newBody)
557 {
558     if (IS_WAITING_FOR_ENTITY_BODY_MEMORY != internalState)
559     {
560         return false;
561     }
562 
563     entityBody = newBody;
564 
565     if (NULL == entityBody)
566     {
567         internalState = IS_SKIPPING_OVER_ENTITY_BODY;
568         ebSizeCoveredSoFar = 0;
569         ebCurrentIndex = 0;
570         ebCurrentOffset = 0;
571     }
572     else
573     {
574         internalState = IS_STARTING_TO_FILL_OUT_ENTITY_BODY;
575         ebSizeCoveredSoFar = 0;
576         ebCurrentIndex = 0;
577         ebCurrentOffset = 0;
578     }
579 
580     continueProcessing();
581 
582     return true;
583 }
584 
585 void
skipOverEntityBody()586 RTSPParser::skipOverEntityBody()
587 {
588     uint32 sizeNeededToSkip = ebFullSizeExpected - ebSizeCoveredSoFar;
589     uint32 sizePossibleToSkip = mainBufferSpace - mainBufferEntry;
590 
591     uint32 sizeSkipped = (sizeNeededToSkip < sizePossibleToSkip) ?
592                          sizeNeededToSkip : sizePossibleToSkip;
593 
594     ebSizeCoveredSoFar += sizeSkipped;
595     mainBufferEntry += sizeSkipped;
596 
597     if (ebSizeCoveredSoFar == ebFullSizeExpected)
598     {
599         eorptr = mainBufferEntry;
600         internalState = IS_WAITING_FOR_REQUEST_MEMORY;
601     }
602 }
603 
604 void
startFillingOutEntityBody()605 RTSPParser::startFillingOutEntityBody()
606 {
607     while (ebFullSizeExpected != ebSizeCoveredSoFar)
608     {
609         // find an appropriate fragment
610         if (entityBody[ebCurrentIndex].len == ebCurrentOffset)
611         {
612             ++ebCurrentIndex;
613             ebCurrentOffset = 0;
614             continue;
615         }
616 
617         uint32 fragmentSizeAvailable = entityBody[ebCurrentIndex].len - ebCurrentOffset;
618 
619         // decide, which is smaller - size left in the main buffer, or size left
620         // in the current target buffer
621         uint32 sizeAvailableForWriting = mainBufferSpace - mainBufferEntry;
622         uint32 sizeActuallyToBeWritten =
623             (fragmentSizeAvailable < sizeAvailableForWriting) ?
624             fragmentSizeAvailable : sizeAvailableForWriting;
625 
626         // now decide, which is smaller - the previous result or the size actually
627         // left to fill out
628         uint32  sizeLeftToWrite = ebFullSizeExpected - ebSizeCoveredSoFar;
629         sizeActuallyToBeWritten = (sizeActuallyToBeWritten < sizeLeftToWrite) ?
630                                   sizeActuallyToBeWritten : sizeLeftToWrite;
631 
632         if (0 == sizeActuallyToBeWritten)
633         { // ran out of available data
634 
635             // now, further filling out will actually be done by the Engine, we'll
636             // just direct it to memory within entity body;
637             //
638             // this means a change of states
639             //
640             internalState = IS_CONTINUING_TO_FILL_OUT_ENTITY_BODY;
641 
642             return;
643         }
644 
645         // memory comes from different sources, so we can copy it without fear of
646         // overlaps
647 
648         oscl_memcpy(static_cast<char*>(entityBody[ebCurrentIndex].ptr) + ebCurrentOffset,
649                     mainBufferEntry,
650                     sizeActuallyToBeWritten
651                    );
652 
653         ebCurrentOffset += sizeActuallyToBeWritten;
654         mainBufferEntry += sizeActuallyToBeWritten;
655 
656         ebSizeCoveredSoFar += sizeActuallyToBeWritten;
657 
658     }
659 
660     // at this point, either we covered the whole thing, or we didn't
661 
662     // if we covered the whole thing, we jumped out from the loop according to
663     // the loop invariant
664     //
665     // if, however, we did not fill out the whole thing, then we have already
666     // returned from within the loop, switching to hungry state
667     //
668     // in other words, at this point we could ONLY succeed
669 
670     eorptr = mainBufferEntry;
671 
672     internalState = IS_ENTITY_BODY_IS_READY;
673 }
674 
675 OSCL_EXPORT_REF bool
registerEmbeddedDataMemory(RTSPEntityBody * newBody)676 RTSPParser::registerEmbeddedDataMemory(RTSPEntityBody * newBody)
677 {
678     if (IS_WAITING_FOR_EMBEDDED_DATA_MEMORY != internalState)
679     {
680         return false;
681     }
682 
683     entityBody = newBody;
684 
685     if (NULL == entityBody)
686     {
687         internalState = IS_SKIPPING_OVER_EMBEDDED_DATA;
688         ebSizeCoveredSoFar = 0;
689         ebCurrentIndex = 0;
690         ebCurrentOffset = 0;
691     }
692     else
693     {
694         internalState = IS_STARTING_TO_FILL_OUT_EMBEDDED_DATA;
695         ebSizeCoveredSoFar = 0;
696         ebCurrentIndex = 0;
697         ebCurrentOffset = 0;
698     }
699 
700     continueProcessing();
701 
702     return true;
703 }
704 
705 void
skipOverEmbeddedData()706 RTSPParser::skipOverEmbeddedData()
707 {
708     uint32 sizeNeededToSkip = ebFullSizeExpected - ebSizeCoveredSoFar;
709     uint32 sizePossibleToSkip = mainBufferSpace - mainBufferEntry;
710 
711     uint32 sizeSkipped = (sizeNeededToSkip < sizePossibleToSkip) ?
712                          sizeNeededToSkip : sizePossibleToSkip;
713 
714     ebSizeCoveredSoFar += sizeSkipped;
715     mainBufferEntry += sizeSkipped;
716 
717     if (ebSizeCoveredSoFar == ebFullSizeExpected)
718     {
719         eorptr = mainBufferEntry;
720         internalState = IS_WAITING_FOR_REQUEST_MEMORY;
721     }
722 }
723 
724 void
startFillingOutEmbeddedData()725 RTSPParser::startFillingOutEmbeddedData()
726 {
727     while (ebFullSizeExpected != ebSizeCoveredSoFar)
728     {    // find an appropriate fragment
729         if (entityBody[ebCurrentIndex].len == ebCurrentOffset)
730         {
731             ++ebCurrentIndex;
732             ebCurrentOffset = 0;
733             continue;
734         }
735 
736         uint32 fragmentSizeAvailable = entityBody[ebCurrentIndex].len - ebCurrentOffset;
737 
738         // decide, which is smaller - size left in the main buffer, or size left
739         // in the current target buffer
740         //
741         uint32 sizeAvailableForWriting = mainBufferSpace - mainBufferEntry;
742         uint32 sizeActuallyToBeWritten =
743             (fragmentSizeAvailable < sizeAvailableForWriting) ?
744             fragmentSizeAvailable : sizeAvailableForWriting;
745 
746         // now decide, which is smaller - the previous result or the size actually
747         // left to fill out
748         uint32  sizeLeftToWrite = ebFullSizeExpected - ebSizeCoveredSoFar;
749         sizeActuallyToBeWritten = (sizeActuallyToBeWritten < sizeLeftToWrite) ?
750                                   sizeActuallyToBeWritten : sizeLeftToWrite;
751 
752         if (0 == sizeActuallyToBeWritten)
753         { // ran out of available data
754 
755             // now, further filling out will actually be done by the Engine, we'll
756             // just direct it to memory within entity body;
757             //
758             // this means a change of states
759             //
760             internalState = IS_CONTINUING_TO_FILL_OUT_EMBEDDED_DATA;
761 
762             return;
763         }
764 
765         // memory comes from different sources, so we can copy it without fear of
766         // overlaps
767 
768         oscl_memcpy(static_cast<char*>(entityBody[ebCurrentIndex].ptr) + ebCurrentOffset,
769                     mainBufferEntry,
770                     sizeActuallyToBeWritten
771                    );
772 
773         ebCurrentOffset += sizeActuallyToBeWritten;
774         mainBufferEntry += sizeActuallyToBeWritten;
775 
776         ebSizeCoveredSoFar += sizeActuallyToBeWritten;
777 
778     }
779 
780     // at this point, either we covered the whole thing, or we didn't
781 
782     // if we covered the whole thing, we jumped out from the loop according to
783     // the loop invariant
784     //
785     // if, however, we did not fill out the whole thing, then we have already
786     // returned from within the loop, switching to hungry state
787     //
788     // in other words, at this point we could ONLY succeed
789 
790     eorptr = mainBufferEntry;
791 
792     internalState = IS_EMBEDDED_DATA_IS_READY;
793 }
794 
795 OSCL_EXPORT_REF void
flush(void)796 RTSPParser::flush(void)
797 {
798     internalState = IS_WAITING_FOR_REQUEST_MEMORY;
799     mainBufferEntry = mainBuffer;
800     mainBufferSpace = mainBuffer;
801     mainBufferSizeUsed = 0;
802     eorptr = mainBuffer;
803     mainBuffer[ RTSP_PARSER_BUFFER_SIZE ] = CHAR_NULL;
804     mainBuffer[ RTSP_PARSER_BUFFER_SIZE+1 ] = CHAR_NULL;
805 }
806 
807 void
dealWithLineContinuations(RTSPIncomingMessage * theStruct)808 RTSPParser::dealWithLineContinuations(RTSPIncomingMessage * theStruct)
809 {
810     char * cPtr;      // current pointer
811     char * nlEnd;     // new-line end pointer
812     char * finishPtr; // end-of-buffer pointer
813 
814     finishPtr = theStruct->secondaryBuffer + theStruct->secondaryBufferSizeUsed;
815 
816     for (cPtr = theStruct->secondaryBuffer;
817             cPtr < finishPtr;
818         )
819     {
820         // check if this point is suspicious
821         //
822         if (CHAR_CR == *cPtr)
823         {
824             if (cPtr < finishPtr - 1      // there's room for CR-LF
825                     &&  CHAR_LF == *(cPtr + 1)  // next char is LF
826                )
827             {
828                 nlEnd = cPtr + 1;
829 
830                 // newline, CR-LF
831             }
832             else
833             {
834                 nlEnd = cPtr;
835 
836                 // newline, CR
837             }
838         }
839         else if (CHAR_LF == *cPtr)
840         {
841             nlEnd = cPtr;
842 
843             // newline, LF
844         }
845         else
846         { // not a newline
847             ++cPtr;
848             continue;
849         }
850 
851         // it was a newline
852 
853         // now, is there a whitespace after it?
854         if (nlEnd >= finishPtr      // could be no room for a whitespace
855                 || (CHAR_SPACE != *(nlEnd + 1)      // could be a non-whitespace
856                     &&  CHAR_TAB   != *(nlEnd + 1)
857                    )
858            )
859         {
860             cPtr = nlEnd + 1;
861             continue;
862         }
863 
864         char * sPtr;
865         for (sPtr = nlEnd + 1;
866                 sPtr < finishPtr
867                 && (CHAR_SPACE == *sPtr
868                     ||  CHAR_TAB   == *sPtr
869                    );
870                 ++sPtr
871             )
872         { // nothing
873             ;;;;
874         }
875 
876         size_t sizeToMove = finishPtr - sPtr + 1;
877         size_t sizeCut = sPtr - cPtr - 1;
878 
879         // set a space
880         * cPtr = CHAR_SPACE;
881 
882         // move the rest, careful with overlaps
883         oscl_memmove(cPtr + 1, sPtr, sizeToMove);
884 
885         // reset the length
886         theStruct->secondaryBufferSizeUsed -= sizeCut;
887 
888         // reiterate
889         finishPtr -= sizeCut;
890         ++cPtr; // safe enough, still one whitespace has been written
891 
892         continue;
893     }
894 }
895 
896 
897 void
dealWithFieldRepetitions(RTSPIncomingMessage * theStruct)898 RTSPParser::dealWithFieldRepetitions(RTSPIncomingMessage * theStruct)
899 {
900     char * cPtr;
901     char * finishPtr =
902         theStruct->secondaryBuffer + theStruct->secondaryBufferSizeUsed;
903     char * nlEnd;
904 
905     for (cPtr = theStruct->secondaryBuffer;
906             cPtr < finishPtr;
907             ++cPtr
908         )
909     {
910         if (CHAR_CR == *cPtr)
911         {
912             if (cPtr < finishPtr - 1
913                     &&  CHAR_LF == *(cPtr + 1)
914                )
915             {
916                 nlEnd = cPtr + 1;
917             }
918             else
919             {
920                 nlEnd = cPtr;
921             }
922         }
923         else if (CHAR_LF == *cPtr)
924         {
925             nlEnd = cPtr;
926         }
927         else
928         {
929             continue;
930         }
931 
932         char * fieldNamePtr = nlEnd + 1;
933 
934         if (fieldNamePtr >= finishPtr
935                 ||  CHAR_CR     == *fieldNamePtr
936                 ||  CHAR_LF     == *fieldNamePtr
937                 ||  CHAR_SPACE  == *fieldNamePtr
938                 ||  CHAR_TAB    == *fieldNamePtr
939            )
940         {
941             // not a field, an end of message or an empty string
942 
943             continue;
944         }
945 
946         // we have a field
947     }
948 }
949 
950 
951 void
lookForResync()952 RTSPParser::lookForResync()
953 {
954     bool found = false;
955 
956     for (; eorptr < mainBufferSpace - 1; ++eorptr)
957     {
958         if (CHAR_LF == *eorptr || CHAR_CR == *eorptr)
959         {
960             if (*eorptr == *(eorptr + 1))
961             {
962                 found = true;
963                 eorptr += 2;
964                 break;
965             }
966             else if ((eorptr <= mainBufferSpace - 4)
967                      && (CHAR_CR == *(eorptr)) && (CHAR_LF == *(eorptr + 1))
968                      && (CHAR_CR == *(eorptr + 2)) && (CHAR_LF == *(eorptr + 3))
969                     )
970             {
971                 found = true;
972                 eorptr += 4;
973                 break;
974             }
975         }
976     }
977 
978     if (found)
979     {
980         mainBufferEntry = eorptr;
981 
982         if (mainBufferEntry == mainBufferSpace)
983         {
984             mainBufferEntry = mainBuffer;
985             eorptr = mainBufferEntry;
986             mainBufferSpace = mainBufferEntry;
987         }
988 
989         internalState = IS_WAITING_FOR_REQUEST_MEMORY;
990 
991         continueProcessing();
992     }
993     else
994     {
995         int sizeToMove = (RTSP_RESYNC_PRESERVE_SIZE < (mainBufferSpace - mainBufferEntry)) ?
996                          RTSP_RESYNC_PRESERVE_SIZE : (mainBufferSpace - mainBufferEntry);
997 
998         oscl_memmove(mainBuffer, mainBufferSpace - sizeToMove, sizeToMove);
999         mainBufferEntry = mainBuffer;
1000         mainBufferSpace = mainBufferEntry + sizeToMove;
1001         eorptr = mainBuffer;
1002     }
1003 
1004     return;
1005 }
1006