source: trunk/sources/thelib/src/protocols/rtmp/amf3serializer.cpp @ 759

Revision 759, 15.9 KB checked in by shiretu, 8 weeks ago (diff)

-- fixed various bugs related to the new way in which the new xcode compiler is reporting errors

Line 
1/*
2 *  Copyright (c) 2010,
3 *  Gavriloaie Eugen-Andrei (shiretu@gmail.com)
4 *
5 *  This file is part of crtmpserver.
6 *  crtmpserver is free software: you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation, either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  crtmpserver is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with crtmpserver.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAS_PROTOCOL_RTMP
21#include "protocols/rtmp/amf3serializer.h"
22#include "protocols/rtmp/amftypes.h"
23#include "protocols/baseprotocol.h"
24
25#define READ_AMF3_TYPE(wanted) \
26if (readType) { \
27    AMF_CHECK_BOUNDARIES(buffer, 1); \
28    if (GETIBPOINTER(buffer)[0] != wanted) { \
29        FATAL("AMF type not valid: want: %hhu; got: %hhu", \
30                (uint8_t)wanted, GETIBPOINTER(buffer)[0]); \
31        return false; \
32    } \
33    \
34    if (!buffer.Ignore(1)) { \
35        FATAL("Unable to ignore 1 bytes"); \
36        return false; \
37    } \
38}
39
40#define WRITE_AMF3_TYPE(type) \
41if (writeType) { \
42    buffer.ReadFromRepeat(type,1); \
43}
44
45AMF3Serializer::AMF3Serializer() {
46
47}
48
49AMF3Serializer::~AMF3Serializer() {
50}
51
52bool AMF3Serializer::Read(IOBuffer &buffer, Variant & variant) {
53        AMF_CHECK_BOUNDARIES(buffer, 1);
54        switch (GETIBPOINTER(buffer)[0]) {
55                case AMF3_UNDEFINED:
56                {
57                        return ReadUndefined(buffer, variant);
58                }
59                case AMF3_NULL:
60                {
61                        return ReadNull(buffer, variant);
62                }
63                case AMF3_FALSE:
64                {
65                        return ReadFalse(buffer, variant);
66                }
67                case AMF3_TRUE:
68                {
69                        return ReadTrue(buffer, variant);
70                }
71                case AMF3_INTEGER:
72                {
73                        return ReadInteger(buffer, variant);
74                }
75                case AMF3_DOUBLE:
76                {
77                        return ReadDouble(buffer, variant);
78                }
79                case AMF3_STRING:
80                {
81                        return ReadString(buffer, variant);
82                }
83                case AMF3_XMLDOC:
84                {
85                        return ReadXMLDoc(buffer, variant);
86                }
87                case AMF3_DATE:
88                {
89                        return ReadDate(buffer, variant);
90                }
91                case AMF3_ARRAY:
92                {
93                        return ReadArray(buffer, variant);
94                }
95                case AMF3_OBJECT:
96                {
97                        return ReadObject(buffer, variant);
98                }
99                case AMF3_XML:
100                {
101                        return ReadXML(buffer, variant);
102                }
103                case AMF3_BYTEARRAY:
104                {
105                        return ReadByteArray(buffer, variant);
106                }
107                default:
108                {
109                        FATAL("Unable to deserialize type %hhu; Buffer is:\n%s",
110                                        GETIBPOINTER(buffer)[0], STR(buffer));
111                        return false;
112                }
113        }
114}
115
116bool AMF3Serializer::Write(IOBuffer &buffer, Variant &variant) {
117        switch ((VariantType) variant) {
118                case V_NULL:
119                {
120                        return WriteNull(buffer);
121                }
122                case V_UNDEFINED:
123                {
124                        return WriteUndefined(buffer);
125                }
126                case V_BYTEARRAY:
127                {
128                        return WriteByteArray(buffer, variant);
129                }
130                case V_BOOL:
131                {
132                        if ((bool)variant)
133                                return WriteTrue(buffer);
134                        return WriteFalse(buffer);
135                }
136                case V_MAP:
137                {
138                        if (variant.IsArray())
139                                return WriteArray(buffer, variant);
140                        else
141                                return WriteObject(buffer, variant);
142                }
143                case V_STRING:
144                {
145                        return WriteString(buffer, variant);
146                }
147                case V_INT8:
148                case V_INT16:
149                case V_INT32:
150                case V_UINT8:
151                case V_UINT16:
152                case V_UINT32:
153                case V_UINT64:
154                case V_INT64:
155                case V_DOUBLE:
156                {
157                        return WriteDouble(buffer, variant);
158                }
159                case V_DATE:
160                case V_TIME:
161                case V_TIMESTAMP:
162                {
163                        return WriteDate(buffer, variant);
164                }
165                default:
166                {
167                        FATAL("Unable to serialize type %d; variant is:\n%s",
168                                        (VariantType) variant, STR(variant.ToString()));
169                        return false;
170                }
171        }
172}
173
174bool AMF3Serializer::ReadUndefined(IOBuffer &buffer, Variant &variant, bool readType) {
175        READ_AMF3_TYPE(AMF3_UNDEFINED);
176
177        variant.Reset();
178        return true;
179}
180
181bool AMF3Serializer::WriteUndefined(IOBuffer &buffer) {
182        buffer.ReadFromRepeat(AMF3_UNDEFINED, 1);
183        return true;
184}
185
186bool AMF3Serializer::ReadNull(IOBuffer &buffer, Variant &variant, bool readType) {
187        READ_AMF3_TYPE(AMF3_NULL);
188
189        variant.Reset();
190        return true;
191}
192
193bool AMF3Serializer::WriteNull(IOBuffer &buffer) {
194        buffer.ReadFromRepeat(AMF3_NULL, 1);
195        return true;
196}
197
198bool AMF3Serializer::ReadFalse(IOBuffer &buffer, Variant &variant, bool readType) {
199        READ_AMF3_TYPE(AMF3_FALSE);
200
201        variant = (bool)false;
202        return true;
203}
204
205bool AMF3Serializer::WriteFalse(IOBuffer &buffer) {
206        buffer.ReadFromRepeat(AMF3_FALSE, 1);
207        return true;
208}
209
210bool AMF3Serializer::ReadTrue(IOBuffer &buffer, Variant &variant, bool readType) {
211        READ_AMF3_TYPE(AMF3_TRUE);
212
213        variant = (bool)true;
214        return true;
215}
216
217bool AMF3Serializer::WriteTrue(IOBuffer &buffer) {
218        buffer.ReadFromRepeat(AMF3_TRUE, 1);
219        return true;
220}
221
222bool AMF3Serializer::ReadInteger(IOBuffer &buffer, Variant &variant, bool readType) {
223        READ_AMF3_TYPE(AMF3_INTEGER);
224
225        uint32_t result;
226        if (!ReadU29(buffer, result)) {
227                FATAL("Unable to read integer");
228                return false;
229        }
230
231        variant = (uint32_t) result;
232
233        return true;
234}
235
236bool AMF3Serializer::WriteInteger(IOBuffer &buffer, uint32_t value, bool writeType) {
237        WRITE_AMF3_TYPE(AMF3_INTEGER);
238
239        return WriteU29(buffer, value);
240}
241
242bool AMF3Serializer::ReadDouble(IOBuffer &buffer, Variant &variant, bool readType) {
243        READ_AMF3_TYPE(AMF3_DOUBLE);
244
245        AMF_CHECK_BOUNDARIES(buffer, 8);
246        double temp = 0;
247        ENTOHDP(GETIBPOINTER(buffer), temp);
248        variant = (double) temp;
249
250        if (!buffer.Ignore(8)) {
251                FATAL("Unable to ignore 8 bytes");
252                return false;
253        }
254        return true;
255}
256
257bool AMF3Serializer::WriteDouble(IOBuffer &buffer, double value, bool writeType) {
258        WRITE_AMF3_TYPE(AMF3_DOUBLE);
259
260        uint64_t u64Val = 0;
261        EHTOND(value, u64Val);
262
263        return buffer.ReadFromBuffer((uint8_t *) & u64Val, 8);
264}
265
266bool AMF3Serializer::ReadString(IOBuffer &buffer, Variant &variant, bool readType) {
267        READ_AMF3_TYPE(AMF3_STRING);
268
269        uint32_t temp;
270        if (!ReadU29(buffer, temp)) {
271                FATAL("Unable to read reference");
272                return false;
273        }
274
275        if ((temp & 0x01) == 1) {
276                //new string
277                uint32_t length = temp >> 1;
278                if (length != 0) {
279                        AMF_CHECK_BOUNDARIES(buffer, length);
280                        string result = string((char *) GETIBPOINTER(buffer), length);
281                        if (!buffer.Ignore(length)) {
282                                FATAL("Unable to ignore %u bytes", length);
283                                return false;
284                        }
285                        variant = result;
286                        ADD_VECTOR_END(_strings, result);
287                } else {
288                        variant = "";
289                }
290        } else {
291                //cached string
292                variant = _strings[temp >> 1];
293        }
294
295        return true;
296}
297
298bool AMF3Serializer::WriteString(IOBuffer &buffer, string value, bool writeType) {
299        WRITE_AMF3_TYPE(AMF3_STRING);
300
301        if (!WriteU29(buffer, (((uint32_t) value.size()) << 1) | 0x01)) {
302                FATAL("Unable to read reference");
303                return false;
304        }
305
306        buffer.ReadFromString(value);
307
308        return true;
309}
310
311bool AMF3Serializer::ReadXMLDoc(IOBuffer &buffer, Variant &variant, bool readType) {
312        READ_AMF3_TYPE(AMF3_XMLDOC);
313        NYIR;
314}
315
316bool AMF3Serializer::WriteXMLDoc(IOBuffer &buffer, Variant &variant, bool writeType) {
317        NYIR;
318}
319
320bool AMF3Serializer::ReadDate(IOBuffer &buffer, Variant &variant, bool readType) {
321        READ_AMF3_TYPE(AMF3_DATE);
322
323        uint32_t temp;
324        if (!ReadU29(buffer, temp)) {
325                FATAL("Unable to read reference");
326                return false;
327        }
328
329        if ((temp & 0x01) == 1) {
330                //new date
331                AMF_CHECK_BOUNDARIES(buffer, 8);
332                uint64_t u64Val = ENTOHLLP(GETIBPOINTER(buffer));
333                if (!buffer.Ignore(8)) {
334                        FATAL("Unable to ignore 8 bytes");
335                        return false;
336                }
337                time_t tVal = (time_t) ((*((double *) & u64Val)) / 1000.00);
338                Timestamp tsVal = *(gmtime(&tVal));
339                variant = tsVal;
340                ADD_VECTOR_END(_objects, variant);
341        } else {
342                //cached string
343                variant = _objects[temp >> 1];
344        }
345
346        return true;
347}
348
349bool AMF3Serializer::WriteDate(IOBuffer &buffer, Timestamp value, bool writeType) {
350        WRITE_AMF3_TYPE(AMF3_DATE);
351        if (!WriteU29(buffer, 1)) {
352                FATAL("Unable to write U29");
353                return false;
354        }
355
356        double seconds = (double) timegm(&value)*1000.00;
357        if (!WriteDouble(buffer, seconds, false)) {
358                FATAL("Unable to write double");
359                return false;
360        }
361
362        return true;
363}
364
365bool AMF3Serializer::ReadArray(IOBuffer &buffer, Variant &variant, bool readType) {
366        READ_AMF3_TYPE(AMF3_ARRAY);
367
368        //1. Read the flags
369        uint32_t temp;
370        if (!ReadU29(buffer, temp)) {
371                FATAL("Unable to read reference");
372                return false;
373        }
374
375        if ((temp & 0x01) == 0) {
376                WARN("Array reference: %u", temp >> 1);
377                variant = _objects[temp >> 1];
378                return true;
379        }
380
381        //2. Read the associative portion
382        while (true) {
383                Variant key;
384                if (!ReadString(buffer, key, false)) {
385                        FATAL("Unable to read the key");
386                        return false;
387                }
388                if (key == "")
389                        break;
390                if (!Read(buffer, variant[(string) key])) {
391                        FATAL("Unable to read the value");
392                        return false;
393                }
394        }
395
396        //3. read the dense portion
397        uint32_t denseSize = temp >> 1;
398        for (uint32_t i = 0; i < denseSize; i++) {
399                if (!Read(buffer, variant[(uint32_t) i])) {
400                        FATAL("Unable to read value");
401                        return false;
402                }
403        }
404
405        //4. Mark the object as an array
406        variant.IsArray(true);
407
408        //5. Store it in the reference table
409        ADD_VECTOR_END(_objects, variant);
410
411        //6. Done
412        return true;
413}
414
415bool AMF3Serializer::WriteArray(IOBuffer &buffer, Variant &variant, bool writeType) {
416        WRITE_AMF3_TYPE(AMF3_ARRAY);
417
418        Variant v = variant;
419
420        uint32_t denseSize = v.MapDenseSize();
421
422        for (uint32_t i = 0; i < denseSize; i++) {
423                v.RemoveAt(i);
424        }
425
426        if (!WriteU29(buffer, (denseSize << 1) | 0x01)) {
427                FATAL("Unable to write dense size");
428                return false;
429        }
430
431        Variant key = "";
432
433        FOR_MAP(v, string, Variant, i) {
434                key = MAP_KEY(i);
435                if (!WriteString(buffer, key, false)) {
436                        FATAL("Unable to write key");
437                        return false;
438                }
439                if (!Write(buffer, MAP_VAL(i))) {
440                        FATAL("Unable to write value");
441                        return false;
442                }
443        }
444
445        key = "";
446        if (!WriteString(buffer, key, false)) {
447                FATAL("Unable to write key");
448                return false;
449        }
450
451        for (uint32_t i = 0; i < denseSize; i++) {
452                if (!Write(buffer, variant[i])) {
453                        FATAL("Unable to write value");
454                        return false;
455                }
456        }
457
458        return true;
459}
460
461bool AMF3Serializer::ReadObject(IOBuffer &buffer, Variant &variant, bool readType) {
462        READ_AMF3_TYPE(AMF3_OBJECT);
463
464        uint32_t temp;
465        if (!ReadU29(buffer, temp)) {
466                FATAL("Unable to read reference");
467                return false;
468        }
469
470        bool objectReference = ((temp & 0x01) == 0);
471        uint32_t objectReferenceIndex = temp >> 1;
472
473        bool traitsReference = ((temp & 0x02) == 0);
474        uint32_t traitsReferenceIndex = temp >> 2;
475
476        bool traitsExtended = ((temp & 0x07) == 0x07);
477
478        bool isDynamic = ((temp & 0x08) != 0);
479        uint32_t traitsCount = temp >> 4;
480
481
482        if (objectReference) {
483                variant = _objects[objectReferenceIndex];
484                return true;
485        }
486
487        if (traitsExtended) {
488                Variant className;
489                if (!ReadString(buffer, className, false)) {
490                        FATAL("Unable to read the class name");
491                        return false;
492                }
493
494                if (className == "flex.messaging.io.ArrayCollection") {
495                        variant.SetTypeName((string) className);
496                        if (!Read(buffer, variant)) {
497                                FATAL("Unable to read object");
498                                return false;
499                        }
500                        ADD_VECTOR_END(_objects, variant);
501                        return true;
502                } else {
503                        FATAL("Class name %s not supported yet", STR(className));
504                        return false;
505                }
506        }
507
508        uint32_t objectIndex = (uint32_t) _objects.size();
509        Variant tempVariant = Variant();
510        ADD_VECTOR_END(_objects, tempVariant);
511
512        Variant traits;
513
514        if (traitsReference) {
515                traits = _traits[traitsReferenceIndex];
516                //FINEST("Traits:\n%s", STR(traits.ToString()));
517        } else {
518                uint32_t traitsIndex = (uint32_t) _traits.size();
519
520                tempVariant = Variant();
521                ADD_VECTOR_END(_traits, tempVariant);
522                traits[AMF3_TRAITS_DYNAMIC] = (bool)isDynamic;
523
524                Variant className;
525                if (!ReadString(buffer, className, false)) {
526                        FATAL("Unable to read the class name");
527                        return false;
528                }
529                traits[AMF3_TRAITS_CLASSNAME] = className;
530
531                for (uint32_t i = 0; i < traitsCount; i++) {
532                        Variant traitName;
533                        if (!ReadString(buffer, traitName, false)) {
534                                FATAL("Unable to read trait name");
535                                return false;
536                        }
537                        traits[AMF3_TRAITS][i] = traitName;
538                }
539
540                _traits[traitsIndex] = traits;
541        }
542
543        if (traits[AMF3_TRAITS_CLASSNAME] != "") {
544                variant.SetTypeName(traits[AMF3_TRAITS_CLASSNAME]);
545                ASSERT("%s", STR(traits.ToString()));
546        }
547        for (uint32_t i = 0; i < traits[AMF3_TRAITS].MapSize(); i++) {
548                string traitName = traits[AMF3_TRAITS][i];
549                FINEST("Read value for trait %s", STR(traitName));
550                if (!Read(buffer, variant[AMF3_TRAITS][traitName])) {
551                        FATAL("Unable to read trait value");
552                        return false;
553                }
554        }
555
556        bool readDynamicPoperties = false;
557
558        if (traitsReference) {
559                readDynamicPoperties = (bool)traits[AMF3_TRAITS_DYNAMIC];
560        } else {
561                readDynamicPoperties = isDynamic;
562        }
563
564        if (readDynamicPoperties) {
565                while (true) {
566                        Variant key;
567                        if (!ReadString(buffer, key, false)) {
568                                FATAL("Unable to read the key");
569                                return false;
570                        }
571                        if (key == "") {
572                                break;
573                        }
574
575                        if (!Read(buffer, variant[(string) key])) {
576                                FATAL("Unable to read the value");
577                                return false;
578                        }
579                }
580        }
581
582        _objects[objectIndex] = variant;
583        return true;
584}
585
586bool AMF3Serializer::WriteObject(IOBuffer &buffer, Variant &variant, bool writeType) {
587        WRITE_AMF3_TYPE(AMF3_OBJECT);
588        if (!WriteU29(buffer, 0x0b)) {
589                FATAL("Unable to save the traits count");
590                return false;
591        }
592
593        Variant className = "";
594        if (!WriteString(buffer, className, false)) {
595                FATAL("Unable to read the class name");
596                return false;
597        }
598
599        FOR_MAP(variant, string, Variant, i) {
600                if (!WriteString(buffer, MAP_KEY(i), false)) {
601                        FATAL("Unable to write key");
602                        return false;
603                }
604                if (!Write(buffer, MAP_VAL(i))) {
605                        FATAL("Unable to write value");
606                        return false;
607                }
608        }
609
610        if (!WriteString(buffer, "", false)) {
611                FATAL("Unable to write key");
612                return false;
613        }
614
615        return true;
616}
617
618bool AMF3Serializer::ReadXML(IOBuffer &buffer, Variant &variant, bool readType) {
619
620        READ_AMF3_TYPE(AMF3_XML);
621        NYIR;
622}
623
624bool AMF3Serializer::WriteXML(IOBuffer &buffer, Variant &variant, bool writeType) {
625
626        NYIR;
627}
628
629bool AMF3Serializer::ReadByteArray(IOBuffer &buffer, Variant &variant, bool readType) {
630        READ_AMF3_TYPE(AMF3_BYTEARRAY);
631
632        uint32_t temp;
633        if (!ReadU29(buffer, temp)) {
634                FATAL("Unable to read reference");
635                return false;
636        }
637
638        if ((temp & 0x01) == 1) {
639                //new byte array
640                uint32_t length = temp >> 1;
641                if (length != 0) {
642                        AMF_CHECK_BOUNDARIES(buffer, length);
643                        string result = string((char *) GETIBPOINTER(buffer), length);
644                        if (!buffer.Ignore(length)) {
645                                FATAL("Unable to ignore %u bytes", length);
646                                return false;
647                        }
648                        variant = result;
649                        variant.IsByteArray(true);
650                        ADD_VECTOR_END(_byteArrays, result);
651                } else {
652                        variant = "";
653                        variant.IsByteArray(true);
654                }
655        } else {
656                //cached string
657
658                variant = _byteArrays[temp >> 1];
659        }
660
661        return true;
662}
663
664bool AMF3Serializer::WriteByteArray(IOBuffer &buffer, Variant &variant, bool writeType) {
665        WRITE_AMF3_TYPE(AMF3_BYTEARRAY);
666
667        string temp = (string) variant;
668
669        if (!WriteU29(buffer, (((uint32_t) temp.length()) << 1) | 0x01)) {
670                FATAL("Unable to write U29");
671
672                return false;
673        }
674
675        return buffer.ReadFromString(temp);
676}
677
678bool AMF3Serializer::ReadU29(IOBuffer &buffer, uint32_t & value) {
679        value = 0;
680        for (uint32_t i = 0; i < 4; i++) {
681                AMF_CHECK_BOUNDARIES(buffer, 1);
682                uint8_t byte = GETIBPOINTER(buffer)[0];
683                if (!buffer.Ignore(1)) {
684                        FATAL("Unable to ignore 1 byte");
685                        return false;
686                }
687                if (i != 3) {
688                        value = (value << 7) | (byte & 0x7f);
689                } else {
690                        value = (value << 8) | byte;
691                }
692                if ((byte & 0x80) == 0)
693                        break;
694        }
695
696        return true;
697}
698
699bool AMF3Serializer::WriteU29(IOBuffer &buffer, uint32_t value) {
700        uint32_t temp = EHTONL(value);
701        uint8_t *pBuffer = (uint8_t*) & temp;
702        if (value <= 0x0000007f) {
703                buffer.ReadFromRepeat(pBuffer[3], 1);
704                return true;
705        } else if ((0x00000080 <= value) && (value <= 0x00003fff)) {
706                buffer.ReadFromRepeat(((pBuffer[2] << 1) | (pBuffer[3] >> 7)) | 0x80, 1);
707                buffer.ReadFromRepeat(pBuffer[3]&0x7f, 1);
708                return true;
709        } else if ((0x00004000 <= value) && (value <= 0x001fffff)) {
710                buffer.ReadFromRepeat(((pBuffer[1] << 2) | (pBuffer[2] >> 6)) | 0x80, 1);
711                buffer.ReadFromRepeat(((pBuffer[2] << 1) | (pBuffer[3] >> 7)) | 0x80, 1);
712                buffer.ReadFromRepeat(pBuffer[3]&0x7f, 1);
713                return true;
714        } else if ((0x0020000 <= value) && (value <= 0x01fffffff)) {
715                buffer.ReadFromRepeat(((pBuffer[0] << 2) | (pBuffer[1] >> 6)) | 0x80, 1);
716                buffer.ReadFromRepeat(((pBuffer[1] << 1) | (pBuffer[2] >> 7)) | 0x80, 1);
717                buffer.ReadFromRepeat(pBuffer[2] | 0x80, 1);
718                buffer.ReadFromRepeat(pBuffer[3], 1);
719                return true;
720        }
721
722        return false;
723}
724#endif /* HAS_PROTOCOL_RTMP */
725
Note: See TracBrowser for help on using the repository browser.