Blame view

trunk/src/rtmp/srs_protocol_amf0.hpp 24.6 KB
winlin authored
1 2 3
/*
The MIT License (MIT)
4
Copyright (c) 2013-2014 winlin
winlin authored
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
24 25
#ifndef SRS_RTMP_PROTOCOL_AMF0_HPP
#define SRS_RTMP_PROTOCOL_AMF0_HPP
winlin authored
26 27

/*
28
#include <srs_protocol_amf0.hpp>
winlin authored
29 30 31 32 33
*/

#include <srs_core.hpp>

#include <string>
34
#include <vector>
winlin authored
35 36

class SrsStream;
37 38
class SrsAmf0Object;
class SrsAmf0EcmaArray;
39
class SrsAmf0StrictArray;
40 41 42 43

// internal objects, user should never use it.
namespace _srs_internal
{
44 45
    class SrsUnSortedHashtable;
    class SrsAmf0ObjectEOF;
46
    class SrsAmf0Date;
47
}
winlin authored
48
winlin authored
49
/*
50 51 52
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
winlin authored
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
Usages:

1. the bytes proxy: SrsStream
    // when we got some bytes from file or network,
    // use SrsStream proxy to read/write bytes
    
    // for example, read bytes from file or network.
    char* bytes = ...; 
    
    // initialize the stream, proxy for bytes.
    SrsStream stream;
    stream.initialize(bytes);
    
    // use stream instead.

2. directly read AMF0 any instance from stream:
    SrsAmf0Any* pany = NULL;
    srs_amf0_read_any(&stream, &pany);

3. use SrsAmf0Any to discovery instance from stream:
    SrsAmf0Any* pany = NULL;
    SrsAmf0Any::discovery(&stream, &pany);

4. directly read specified AMF0 instance value from stream:
    string value;
    srs_amf0_read_string(&stream, value);
    
5. directly read specified AMF0 instance from stream:
    SrsAmf0Any* str = SrsAmf0Any::str();
    str->read(&stream);

6. get value from AMF0 instance:
    // parse or set by other user
    SrsAmf0Any* any = ...;
    
    if (any->is_string()) {
        string str = any->to_string();
    }

7. get complex object from AMF0 insance:
    // parse or set by other user
    SrsAmf0Any* any = ...;
    
    if (any->is_object()) {
        SrsAmf0Object* obj = any->to_object();
        obj->set("width", SrsAmf0Any::number(1024));
        obj->set("height", SrsAmf0Any::number(576));
    }

8. serialize AMF0 instance to bytes:
    // parse or set by other user
    SrsAmf0Any* any = ...;
    
    char* bytes = new char[any->total_size()];
    
    SrsStream stream;
    stream.initialize(bytes);
    
    any->write(&stream);

@remark: for detail usage, see interfaces of each object.
@remark: all examples ignore the error process.
115 116 117
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
winlin authored
118
*/
119
winlin authored
120 121 122 123
/**
* any amf0 value.
* 2.1 Types Overview
* value-type = number-type | boolean-type | string-type | object-type 
124 125 126
*         | null-marker | undefined-marker | reference-type | ecma-array-type 
*         | strict-array-type | date-type | long-string-type | xml-document-type 
*         | typed-object-type
winlin authored
127
*/
128
class SrsAmf0Any
winlin authored
129
{
130
public:
131
    char marker;
132
public:
133 134
    SrsAmf0Any();
    virtual ~SrsAmf0Any();
winlin authored
135
// type identify, user should identify the type then convert from/to value.
136
public:
winlin authored
137 138 139 140 141
    /**
    * whether current instance is an AMF0 string.
    * @return true if instance is an AMF0 string; otherwise, false.
    * @remark, if true, use to_string() to get its value.
    */
142
    virtual bool is_string();
winlin authored
143 144 145 146 147
    /**
    * whether current instance is an AMF0 boolean.
    * @return true if instance is an AMF0 boolean; otherwise, false.
    * @remark, if true, use to_boolean() to get its value.
    */
148
    virtual bool is_boolean();
winlin authored
149 150 151 152 153
    /**
    * whether current instance is an AMF0 number.
    * @return true if instance is an AMF0 number; otherwise, false.
    * @remark, if true, use to_number() to get its value.
    */
154
    virtual bool is_number();
winlin authored
155 156 157 158
    /**
    * whether current instance is an AMF0 null.
    * @return true if instance is an AMF0 null; otherwise, false.
    */
159
    virtual bool is_null();
winlin authored
160 161 162 163
    /**
    * whether current instance is an AMF0 undefined.
    * @return true if instance is an AMF0 undefined; otherwise, false.
    */
164
    virtual bool is_undefined();
winlin authored
165 166 167 168 169
    /**
    * whether current instance is an AMF0 object.
    * @return true if instance is an AMF0 object; otherwise, false.
    * @remark, if true, use to_object() to get its value.
    */
170
    virtual bool is_object();
winlin authored
171 172 173 174
    /**
    * whether current instance is an AMF0 object-EOF.
    * @return true if instance is an AMF0 object-EOF; otherwise, false.
    */
175
    virtual bool is_object_eof();
winlin authored
176 177 178 179 180
    /**
    * whether current instance is an AMF0 ecma-array.
    * @return true if instance is an AMF0 ecma-array; otherwise, false.
    * @remark, if true, use to_ecma_array() to get its value.
    */
181
    virtual bool is_ecma_array();
winlin authored
182 183 184 185 186
    /**
    * whether current instance is an AMF0 strict-array.
    * @return true if instance is an AMF0 strict-array; otherwise, false.
    * @remark, if true, use to_strict_array() to get its value.
    */
187
    virtual bool is_strict_array();
winlin authored
188
    /**
189 190 191 192 193 194
    * whether current instance is an AMF0 date.
    * @return true if instance is an AMF0 date; otherwise, false.
    * @remark, if true, use to_date() to get its value.
    */
    virtual bool is_date();
    /**
winlin authored
195 196
    * whether current instance is an AMF0 object, object-EOF, ecma-array or strict-array.
    */
197
    virtual bool is_complex_object();
winlin authored
198
// get value of instance
199
public:
200
    /**
winlin authored
201 202
    * get a string copy of instance.
    * @remark assert is_string(), user must ensure the type then convert.
203 204
    */
    virtual std::string to_str();
winlin authored
205 206 207 208 209
    /**
    * get the raw str of instance,
    * user can directly set the content of str.
    * @remark assert is_string(), user must ensure the type then convert.
    */
210
    virtual const char* to_str_raw();
211
    /**
winlin authored
212 213
    * convert instance to amf0 boolean,
    * @remark assert is_boolean(), user must ensure the type then convert.
214 215 216
    */
    virtual bool to_boolean();
    /**
winlin authored
217 218
    * convert instance to amf0 number,
    * @remark assert is_number(), user must ensure the type then convert.
219 220 221
    */
    virtual double to_number();
    /**
222 223 224 225 226 227
    * convert instance to date,
    * @remark assert is_date(), user must ensure the type then convert.
    */
    virtual int64_t to_date();
    virtual int16_t to_date_time_zone();
    /**
winlin authored
228 229
    * convert instance to amf0 object,
    * @remark assert is_object(), user must ensure the type then convert.
230 231 232
    */
    virtual SrsAmf0Object* to_object();
    /**
winlin authored
233 234
    * convert instance to ecma array,
    * @remark assert is_ecma_array(), user must ensure the type then convert.
235 236
    */
    virtual SrsAmf0EcmaArray* to_ecma_array();
winlin authored
237 238 239 240
    /**
    * convert instance to strict array,
    * @remark assert is_strict_array(), user must ensure the type then convert.
    */
241
    virtual SrsAmf0StrictArray* to_strict_array();
winlin authored
242
// set value of instance
243
public:
244
    /**
245 246 247 248
    * set the number of any when is_number() indicates true.
    * user must ensure the type is a number, or assert failed.
    */
    virtual void set_number(double value);
winlin authored
249
// serialize/deseriaize instance.
250 251
public:
    /**
252
    * get the size of amf0 any, including the marker size.
winlin authored
253
    * the size is the bytes which instance serialized to.
254 255 256
    */
    virtual int total_size() = 0;
    /**
winlin authored
257
    * read AMF0 instance from stream.
258 259
    */
    virtual int read(SrsStream* stream) = 0;
winlin authored
260 261 262
    /**
    * write AMF0 instance to stream.
    */
263
    virtual int write(SrsStream* stream) = 0;
winlin authored
264 265 266
    /**
    * copy current AMF0 instance.
    */
267
    virtual SrsAmf0Any* copy() = 0;
268 269 270 271
    /**
    * human readable print 
    * @param pdata, output the heap data, NULL to ignore.
    * @return return the *pdata for print. NULL to ignore.
winlin authored
272
    * @remark user must free the data returned or output by pdata.
273 274
    */
    virtual char* human_print(char** pdata, int* psize);
winlin authored
275
// create AMF0 instance.
276
public:
winlin authored
277 278 279
    /**
    * create an AMF0 string instance, set string content by value.
    */
280
    static SrsAmf0Any* str(const char* value = NULL); 
winlin authored
281 282 283
    /**
    * create an AMF0 boolean instance, set boolean content by value.
    */
284
    static SrsAmf0Any* boolean(bool value = false);
winlin authored
285 286 287
    /**
    * create an AMF0 number instance, set number content by value.
    */
288
    static SrsAmf0Any* number(double value = 0.0);
winlin authored
289
    /**
290 291 292 293
    * create an AMF0 date instance
    */
    static SrsAmf0Any* date(int64_t value = 0);
    /**
winlin authored
294 295
    * create an AMF0 null instance
    */
296
    static SrsAmf0Any* null();
winlin authored
297 298 299
    /**
    * create an AMF0 undefined instance
    */
300
    static SrsAmf0Any* undefined();
winlin authored
301 302 303
    /**
    * create an AMF0 empty object instance
    */
304
    static SrsAmf0Object* object();
winlin authored
305 306 307
    /**
    * create an AMF0 object-EOF instance
    */
308
    static SrsAmf0Any* object_eof();
winlin authored
309 310 311
    /**
    * create an AMF0 empty ecma-array instance
    */
312
    static SrsAmf0EcmaArray* ecma_array();
winlin authored
313 314 315
    /**
    * create an AMF0 empty strict-array instance
    */
316
    static SrsAmf0StrictArray* strict_array();
winlin authored
317
// discovery instance from stream
318
public:
winlin authored
319 320 321 322 323 324 325
    /**
    * discovery AMF0 instance from stream
    * @param ppvalue, output the discoveried AMF0 instance.
    *       NULL if error.
    * @remark, instance is created without read from stream, user must
    *       use (*ppvalue)->read(stream) to get the instance.
    */
326
    static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
winlin authored
327 328 329 330 331 332 333
};

/**
* 2.5 Object Type
* anonymous-object-type = object-marker *(object-property)
* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
*/
334
class SrsAmf0Object : public SrsAmf0Any
winlin authored
335 336
{
private:
337 338
    _srs_internal::SrsUnSortedHashtable* properties;
    _srs_internal::SrsAmf0ObjectEOF* eof;
339
private:
340
    friend class SrsAmf0Any;
winlin authored
341 342 343 344
    /**
    * make amf0 object to private,
    * use should never declare it, use SrsAmf0Any::object() to create it.
    */
345
    SrsAmf0Object();
346
public:
347
    virtual ~SrsAmf0Object();
winlin authored
348
// serialize/deserialize to/from stream.
349
public:
350 351 352
    virtual int total_size();
    virtual int read(SrsStream* stream);
    virtual int write(SrsStream* stream);
353
    virtual SrsAmf0Any* copy();
winlin authored
354
// properties iteration
355
public:
winlin authored
356 357 358
    /**
    * clear all propergies.
    */
winlin authored
359
    virtual void clear();
winlin authored
360 361 362
    /**
    * get the count of properties(key:value).
    */
363
    virtual int count();
winlin authored
364 365 366 367
    /**
    * get the property(key:value) key at index.
    * @remark: max index is count().
    */
368
    virtual std::string key_at(int index);
winlin authored
369 370 371 372 373
    /**
    * get the property(key:value) key raw bytes at index.
    * user can directly set the key bytes.
    * @remark: max index is count().
    */
374
    virtual const char* key_raw_at(int index);
winlin authored
375 376 377 378
    /**
    * get the property(key:value) value at index.
    * @remark: max index is count().
    */
379
    virtual SrsAmf0Any* value_at(int index);
winlin authored
380
// property set/get.
381
public:
winlin authored
382 383 384 385 386 387
    /**
    * set the property(key:value) of object,
    * @param key, string property name.
    * @param value, an AMF0 instance property value.
    * @remark user should never free the value, this instance will manage it.
    */
388
    virtual void set(std::string key, SrsAmf0Any* value);
winlin authored
389 390 391 392 393 394
    /**
    * get the property(key:value) of object,
    * @param name, the property name/key
    * @return the property AMF0 value, NULL if not found.
    * @remark user should never free the returned value, copy it if needed.
    */
395
    virtual SrsAmf0Any* get_property(std::string name);
winlin authored
396 397 398 399 400
    /**
    * get the string property, ensure the property is_string().
    * @return the property AMF0 value, NULL if not found, or not a string.
    * @remark user should never free the returned value, copy it if needed.
    */
401
    virtual SrsAmf0Any* ensure_property_string(std::string name);
winlin authored
402 403 404 405 406
    /**
    * get the number property, ensure the property is_number().
    * @return the property AMF0 value, NULL if not found, or not a number.
    * @remark user should never free the returned value, copy it if needed.
    */
407
    virtual SrsAmf0Any* ensure_property_number(std::string name);
winlin authored
408 409 410 411 412 413 414 415
};

/**
* 2.10 ECMA Array Type
* ecma-array-type = associative-count *(object-property)
* associative-count = U32
* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
*/
416
class SrsAmf0EcmaArray : public SrsAmf0Any
winlin authored
417 418
{
private:
419 420
    _srs_internal::SrsUnSortedHashtable* properties;
    _srs_internal::SrsAmf0ObjectEOF* eof;
421
    int32_t _count;
422
private:
423
    friend class SrsAmf0Any;
winlin authored
424 425 426 427
    /**
    * make amf0 object to private,
    * use should never declare it, use SrsAmf0Any::ecma_array() to create it.
    */
428
    SrsAmf0EcmaArray();
429
public:
430
    virtual ~SrsAmf0EcmaArray();
winlin authored
431
// serialize/deserialize to/from stream.
432
public:
433 434 435
    virtual int total_size();
    virtual int read(SrsStream* stream);
    virtual int write(SrsStream* stream);
436
    virtual SrsAmf0Any* copy();
winlin authored
437
// properties iteration
438
public:
winlin authored
439 440 441
    /**
    * clear all propergies.
    */
442
    virtual void clear();
winlin authored
443 444 445
    /**
    * get the count of properties(key:value).
    */
446
    virtual int count();
winlin authored
447 448 449 450
    /**
    * get the property(key:value) key at index.
    * @remark: max index is count().
    */
451
    virtual std::string key_at(int index);
winlin authored
452 453 454 455 456
    /**
    * get the property(key:value) key raw bytes at index.
    * user can directly set the key bytes.
    * @remark: max index is count().
    */
457
    virtual const char* key_raw_at(int index);
winlin authored
458 459 460 461
    /**
    * get the property(key:value) value at index.
    * @remark: max index is count().
    */
462
    virtual SrsAmf0Any* value_at(int index);
winlin authored
463
// property set/get.
464
public:
winlin authored
465 466 467 468 469 470
    /**
    * set the property(key:value) of array,
    * @param key, string property name.
    * @param value, an AMF0 instance property value.
    * @remark user should never free the value, this instance will manage it.
    */
471
    virtual void set(std::string key, SrsAmf0Any* value);
winlin authored
472 473 474 475 476 477
    /**
    * get the property(key:value) of array,
    * @param name, the property name/key
    * @return the property AMF0 value, NULL if not found.
    * @remark user should never free the returned value, copy it if needed.
    */
478
    virtual SrsAmf0Any* get_property(std::string name);
winlin authored
479 480 481 482 483
    /**
    * get the string property, ensure the property is_string().
    * @return the property AMF0 value, NULL if not found, or not a string.
    * @remark user should never free the returned value, copy it if needed.
    */
484
    virtual SrsAmf0Any* ensure_property_string(std::string name);
winlin authored
485 486 487 488 489
    /**
    * get the number property, ensure the property is_number().
    * @return the property AMF0 value, NULL if not found, or not a number.
    * @remark user should never free the returned value, copy it if needed.
    */
490
    virtual SrsAmf0Any* ensure_property_number(std::string name);
winlin authored
491 492 493
};

/**
494 495 496 497 498 499 500 501 502 503 504
* 2.12 Strict Array Type
* array-count = U32 
* strict-array-type = array-count *(value-type)
*/
class SrsAmf0StrictArray : public SrsAmf0Any
{
private:
    std::vector<SrsAmf0Any*> properties;
    int32_t _count;
private:
    friend class SrsAmf0Any;
winlin authored
505 506 507 508
    /**
    * make amf0 object to private,
    * use should never declare it, use SrsAmf0Any::strict_array() to create it.
    */
509 510 511
    SrsAmf0StrictArray();
public:
    virtual ~SrsAmf0StrictArray();
winlin authored
512
// serialize/deserialize to/from stream.
513 514 515 516
public:
    virtual int total_size();
    virtual int read(SrsStream* stream);
    virtual int write(SrsStream* stream);
517
    virtual SrsAmf0Any* copy();
winlin authored
518
// properties iteration
519
public:
winlin authored
520 521 522
    /**
    * clear all elements.
    */
523
    virtual void clear();
winlin authored
524 525 526
    /**
    * get the count of elements
    */
527
    virtual int count();
winlin authored
528 529 530 531
    /**
    * get the elements key at index.
    * @remark: max index is count().
    */
532
    virtual SrsAmf0Any* at(int index);
winlin authored
533 534 535 536 537 538 539
// property set/get.
public:
    /**
    * append new element to array
    * @param any, an AMF0 instance property value.
    * @remark user should never free the any, this instance will manage it.
    */
winlin authored
540
    virtual void append(SrsAmf0Any* any);
541 542 543
};

/**
544 545 546 547 548
* the class to get amf0 object size
*/
class SrsAmf0Size
{
public:
549 550 551
    static int utf8(std::string value);
    static int str(std::string value);
    static int number();
552
    static int date();
553 554 555 556 557 558
    static int null();
    static int undefined();
    static int boolean();
    static int object(SrsAmf0Object* obj);
    static int object_eof();
    static int ecma_array(SrsAmf0EcmaArray* arr);
559
    static int strict_array(SrsAmf0StrictArray* arr);
560
    static int any(SrsAmf0Any* o);
561 562 563
};

/**
564
* read anything from stream.
565
* @param ppvalue, the output amf0 any elem.
566
*         NULL if error; otherwise, never NULL and user must free it.
567 568 569 570
*/
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);

/**
winlin authored
571 572 573 574 575 576 577 578 579 580 581
* read amf0 string from stream.
* 2.4 String Type
* string-type = string-marker UTF-8
*/
extern int srs_amf0_read_string(SrsStream* stream, std::string& value);
extern int srs_amf0_write_string(SrsStream* stream, std::string value);

/**
* read amf0 boolean from stream.
* 2.4 String Type
* boolean-type = boolean-marker U8
582
*         0 is false, <> 0 is true
winlin authored
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
*/
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
extern int srs_amf0_write_boolean(SrsStream* stream, bool value);

/**
* read amf0 number from stream.
* 2.2 Number Type
* number-type = number-marker DOUBLE
*/
extern int srs_amf0_read_number(SrsStream* stream, double& value);
extern int srs_amf0_write_number(SrsStream* stream, double value);

/**
* read amf0 null from stream.
* 2.7 null Type
* null-type = null-marker
*/
extern int srs_amf0_read_null(SrsStream* stream);
extern int srs_amf0_write_null(SrsStream* stream);

/**
* read amf0 undefined from stream.
* 2.8 undefined Type
* undefined-type = undefined-marker
*/
extern int srs_amf0_read_undefined(SrsStream* stream);
extern int srs_amf0_write_undefined(SrsStream* stream);
611 612 613 614 615 616 617 618 619 620
// internal objects, user should never use it.
namespace _srs_internal
{
    /**
    * read amf0 string from stream.
    * 2.4 String Type
    * string-type = string-marker UTF-8
    * @return default value is empty string.
    * @remark: use SrsAmf0Any::str() to create it.
    */
621
    class SrsAmf0String : public SrsAmf0Any
622 623 624
    {
    public:
        std::string value;
625 626 627 628 629 630 631
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 string to private,
        * use should never declare it, use SrsAmf0Any::str() to create it.
        */
        SrsAmf0String(const char* _value);
632
    public:
633
        virtual ~SrsAmf0String();
634 635 636 637 638 639 640 641 642 643 644 645 646 647
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };
    
    /**
    * read amf0 boolean from stream.
    * 2.4 String Type
    * boolean-type = boolean-marker U8
    *         0 is false, <> 0 is true
    * @return default value is false.
    */
648
    class SrsAmf0Boolean : public SrsAmf0Any
649 650 651
    {
    public:
        bool value;
652 653 654 655 656 657 658
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 boolean to private,
        * use should never declare it, use SrsAmf0Any::boolean() to create it.
        */
        SrsAmf0Boolean(bool _value);
659
    public:
660
        virtual ~SrsAmf0Boolean();
661 662 663 664 665 666 667 668 669 670 671 672 673
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };
    
    /**
    * read amf0 number from stream.
    * 2.2 Number Type
    * number-type = number-marker DOUBLE
    * @return default value is 0.
    */
674
    class SrsAmf0Number : public SrsAmf0Any
675 676 677
    {
    public:
        double value;
678 679 680 681 682 683 684
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 number to private,
        * use should never declare it, use SrsAmf0Any::number() to create it.
        */
        SrsAmf0Number(double _value);
685
    public:
686
        virtual ~SrsAmf0Number();
687 688 689 690 691 692 693 694
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };
    
    /**
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
    * 2.13 Date Type
    * time-zone = S16 ; reserved, not supported should be set to 0x0000
    * date-type = date-marker DOUBLE time-zone
    * @see: https://github.com/winlinvip/simple-rtmp-server/issues/185
    */
    class SrsAmf0Date : public SrsAmf0Any
    {
    private:
        int64_t _date_value;
        int16_t _time_zone;
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 date to private,
        * use should never declare it, use SrsAmf0Any::date() to create it.
        */
        SrsAmf0Date(int64_t value);
    public:
        virtual ~SrsAmf0Date();
    // serialize/deserialize to/from stream.
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    public:
        /**
        * get the date value.
        */
        virtual int64_t date();
        /**
        * get the time_zone.
        */
        virtual int16_t time_zone();
    };
    
    /**
732 733 734 735
    * read amf0 null from stream.
    * 2.7 null Type
    * null-type = null-marker
    */
736
    class SrsAmf0Null : public SrsAmf0Any
737
    {
738 739 740 741 742 743 744
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 null to private,
        * use should never declare it, use SrsAmf0Any::null() to create it.
        */
        SrsAmf0Null();
745
    public:
746
        virtual ~SrsAmf0Null();
747 748 749 750 751 752 753 754 755 756 757 758
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };
    
    /**
    * read amf0 undefined from stream.
    * 2.8 undefined Type
    * undefined-type = undefined-marker
    */
759
    class SrsAmf0Undefined : public SrsAmf0Any
760
    {
761 762 763 764 765 766 767
    private:
        friend class SrsAmf0Any;
        /**
        * make amf0 undefined to private,
        * use should never declare it, use SrsAmf0Any::undefined() to create it.
        */
        SrsAmf0Undefined();
768
    public:
769
        virtual ~SrsAmf0Undefined();
770 771 772 773 774 775 776 777 778 779 780 781 782
    public:
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };
    
    /**
    * to ensure in inserted order.
    * for the FMLE will crash when AMF0Object is not ordered by inserted,
    * if ordered in map, the string compare order, the FMLE will creash when
    * get the response of connect app.
    */
783
    class SrsUnSortedHashtable
784 785 786 787 788
    {
    private:
        typedef std::pair<std::string, SrsAmf0Any*> SrsAmf0ObjectPropertyType;
        std::vector<SrsAmf0ObjectPropertyType> properties;
    public:
789 790
        SrsUnSortedHashtable();
        virtual ~SrsUnSortedHashtable();
791 792 793 794 795 796 797 798 799 800 801 802
    public:
        virtual int count();
        virtual void clear();
        virtual std::string key_at(int index);
        virtual const char* key_raw_at(int index);
        virtual SrsAmf0Any* value_at(int index);
        virtual void set(std::string key, SrsAmf0Any* value);
    public:
        virtual SrsAmf0Any* get_property(std::string name);
        virtual SrsAmf0Any* ensure_property_string(std::string name);
        virtual SrsAmf0Any* ensure_property_number(std::string name);
    public:
803
        virtual void copy(SrsUnSortedHashtable* src);
804 805 806 807 808 809 810
    };
    
    /**
    * 2.11 Object End Type
    * object-end-type = UTF-8-empty object-end-marker
    * 0x00 0x00 0x09
    */
811
    class SrsAmf0ObjectEOF : public SrsAmf0Any
812 813
    {
    public:
814 815 816
        SrsAmf0ObjectEOF();
        virtual ~SrsAmf0ObjectEOF();
    public:
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
        virtual int total_size();
        virtual int read(SrsStream* stream);
        virtual int write(SrsStream* stream);
        virtual SrsAmf0Any* copy();
    };

    /**
    * read amf0 utf8 string from stream.
    * 1.3.1 Strings and UTF-8
    * UTF-8 = U16 *(UTF8-char)
    * UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
    * UTF8-1 = %x00-7F
    * @remark only support UTF8-1 char.
    */
    extern int srs_amf0_read_utf8(SrsStream* stream, std::string& value);
    extern int srs_amf0_write_utf8(SrsStream* stream, std::string value);
    
    extern bool srs_amf0_is_object_eof(SrsStream* stream);
835
    extern int srs_amf0_write_object_eof(SrsStream* stream, SrsAmf0ObjectEOF* value);
836 837 838 839
    
    extern int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value);
};
840
#endif