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