正在显示
7 个修改的文件
包含
740 行增加
和
16 行删除
@@ -84,6 +84,11 @@ bool SrsAmf0Any::is_number() | @@ -84,6 +84,11 @@ bool SrsAmf0Any::is_number() | ||
84 | return marker == RTMP_AMF0_Number; | 84 | return marker == RTMP_AMF0_Number; |
85 | } | 85 | } |
86 | 86 | ||
87 | +bool SrsAmf0Any::is_null() | ||
88 | +{ | ||
89 | + return marker == RTMP_AMF0_Null; | ||
90 | +} | ||
91 | + | ||
87 | bool SrsAmf0Any::is_object() | 92 | bool SrsAmf0Any::is_object() |
88 | { | 93 | { |
89 | return marker == RTMP_AMF0_Object; | 94 | return marker == RTMP_AMF0_Object; |
@@ -131,6 +136,15 @@ SrsAmf0Number::~SrsAmf0Number() | @@ -131,6 +136,15 @@ SrsAmf0Number::~SrsAmf0Number() | ||
131 | { | 136 | { |
132 | } | 137 | } |
133 | 138 | ||
139 | +SrsAmf0Null::SrsAmf0Null() | ||
140 | +{ | ||
141 | + marker = RTMP_AMF0_Null; | ||
142 | +} | ||
143 | + | ||
144 | +SrsAmf0Null::~SrsAmf0Null() | ||
145 | +{ | ||
146 | +} | ||
147 | + | ||
134 | SrsAmf0ObjectEOF::SrsAmf0ObjectEOF() | 148 | SrsAmf0ObjectEOF::SrsAmf0ObjectEOF() |
135 | { | 149 | { |
136 | marker = RTMP_AMF0_ObjectEnd; | 150 | marker = RTMP_AMF0_ObjectEnd; |
@@ -470,6 +484,45 @@ int srs_amf0_write_number(SrsStream* stream, double value) | @@ -470,6 +484,45 @@ int srs_amf0_write_number(SrsStream* stream, double value) | ||
470 | return ret; | 484 | return ret; |
471 | } | 485 | } |
472 | 486 | ||
487 | +int srs_amf0_read_null(SrsStream* stream) | ||
488 | +{ | ||
489 | + int ret = ERROR_SUCCESS; | ||
490 | + | ||
491 | + // marker | ||
492 | + if (!stream->require(1)) { | ||
493 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
494 | + srs_error("amf0 read null marker failed. ret=%d", ret); | ||
495 | + return ret; | ||
496 | + } | ||
497 | + | ||
498 | + char marker = stream->read_1bytes(); | ||
499 | + if (marker != RTMP_AMF0_Null) { | ||
500 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
501 | + srs_error("amf0 check null marker failed. " | ||
502 | + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret); | ||
503 | + return ret; | ||
504 | + } | ||
505 | + srs_verbose("amf0 read null success"); | ||
506 | + | ||
507 | + return ret; | ||
508 | +} | ||
509 | +int srs_amf0_write_null(SrsStream* stream) | ||
510 | +{ | ||
511 | + int ret = ERROR_SUCCESS; | ||
512 | + | ||
513 | + // marker | ||
514 | + if (!stream->require(1)) { | ||
515 | + ret = ERROR_RTMP_AMF0_ENCODE; | ||
516 | + srs_error("amf0 write null marker failed. ret=%d", ret); | ||
517 | + return ret; | ||
518 | + } | ||
519 | + | ||
520 | + stream->write_1bytes(RTMP_AMF0_Null); | ||
521 | + srs_verbose("amf0 write null marker success"); | ||
522 | + | ||
523 | + return ret; | ||
524 | +} | ||
525 | + | ||
473 | int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) | 526 | int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) |
474 | { | 527 | { |
475 | int ret = ERROR_SUCCESS; | 528 | int ret = ERROR_SUCCESS; |
@@ -515,6 +568,10 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) | @@ -515,6 +568,10 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) | ||
515 | srs_amf0_convert<SrsAmf0Number>(value)->value = data; | 568 | srs_amf0_convert<SrsAmf0Number>(value)->value = data; |
516 | return ret; | 569 | return ret; |
517 | } | 570 | } |
571 | + case RTMP_AMF0_Null: { | ||
572 | + value = new SrsAmf0Null(); | ||
573 | + return ret; | ||
574 | + } | ||
518 | case RTMP_AMF0_ObjectEnd: { | 575 | case RTMP_AMF0_ObjectEnd: { |
519 | SrsAmf0ObjectEOF* p = NULL; | 576 | SrsAmf0ObjectEOF* p = NULL; |
520 | if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) { | 577 | if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) { |
@@ -568,6 +625,9 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | @@ -568,6 +625,9 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | ||
568 | double data = srs_amf0_convert<SrsAmf0Number>(value)->value; | 625 | double data = srs_amf0_convert<SrsAmf0Number>(value)->value; |
569 | return srs_amf0_write_number(stream, data); | 626 | return srs_amf0_write_number(stream, data); |
570 | } | 627 | } |
628 | + case RTMP_AMF0_Null: { | ||
629 | + return srs_amf0_write_null(stream); | ||
630 | + } | ||
571 | case RTMP_AMF0_ObjectEnd: { | 631 | case RTMP_AMF0_ObjectEnd: { |
572 | SrsAmf0ObjectEOF* p = srs_amf0_convert<SrsAmf0ObjectEOF>(value); | 632 | SrsAmf0ObjectEOF* p = srs_amf0_convert<SrsAmf0ObjectEOF>(value); |
573 | return srs_amf0_write_object_eof(stream, p); | 633 | return srs_amf0_write_object_eof(stream, p); |
@@ -590,7 +650,6 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | @@ -590,7 +650,6 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | ||
590 | 650 | ||
591 | return ret; | 651 | return ret; |
592 | } | 652 | } |
593 | - | ||
594 | int srs_amf0_get_any_size(SrsAmf0Any* value) | 653 | int srs_amf0_get_any_size(SrsAmf0Any* value) |
595 | { | 654 | { |
596 | if (!value) { | 655 | if (!value) { |
@@ -613,6 +672,10 @@ int srs_amf0_get_any_size(SrsAmf0Any* value) | @@ -613,6 +672,10 @@ int srs_amf0_get_any_size(SrsAmf0Any* value) | ||
613 | size += srs_amf0_get_number_size(); | 672 | size += srs_amf0_get_number_size(); |
614 | break; | 673 | break; |
615 | } | 674 | } |
675 | + case RTMP_AMF0_Null: { | ||
676 | + size += srs_amf0_get_null_size(); | ||
677 | + break; | ||
678 | + } | ||
616 | case RTMP_AMF0_ObjectEnd: { | 679 | case RTMP_AMF0_ObjectEnd: { |
617 | size += srs_amf0_get_object_eof_size(); | 680 | size += srs_amf0_get_object_eof_size(); |
618 | break; | 681 | break; |
@@ -941,6 +1004,11 @@ int srs_amf0_get_number_size() | @@ -941,6 +1004,11 @@ int srs_amf0_get_number_size() | ||
941 | return 1 + 8; | 1004 | return 1 + 8; |
942 | } | 1005 | } |
943 | 1006 | ||
1007 | +int srs_amf0_get_null_size() | ||
1008 | +{ | ||
1009 | + return 1; | ||
1010 | +} | ||
1011 | + | ||
944 | int srs_amf0_get_boolean_size() | 1012 | int srs_amf0_get_boolean_size() |
945 | { | 1013 | { |
946 | return 1 + 1; | 1014 | return 1 + 1; |
@@ -54,6 +54,7 @@ struct SrsAmf0Any | @@ -54,6 +54,7 @@ struct SrsAmf0Any | ||
54 | virtual bool is_string(); | 54 | virtual bool is_string(); |
55 | virtual bool is_boolean(); | 55 | virtual bool is_boolean(); |
56 | virtual bool is_number(); | 56 | virtual bool is_number(); |
57 | + virtual bool is_null(); | ||
57 | virtual bool is_object(); | 58 | virtual bool is_object(); |
58 | virtual bool is_object_eof(); | 59 | virtual bool is_object_eof(); |
59 | virtual bool is_ecma_array(); | 60 | virtual bool is_ecma_array(); |
@@ -103,6 +104,17 @@ struct SrsAmf0Number : public SrsAmf0Any | @@ -103,6 +104,17 @@ struct SrsAmf0Number : public SrsAmf0Any | ||
103 | }; | 104 | }; |
104 | 105 | ||
105 | /** | 106 | /** |
107 | +* read amf0 null from stream. | ||
108 | +* 2.7 null Type | ||
109 | +* null-type = null-marker | ||
110 | +*/ | ||
111 | +struct SrsAmf0Null : public SrsAmf0Any | ||
112 | +{ | ||
113 | + SrsAmf0Null(); | ||
114 | + virtual ~SrsAmf0Null(); | ||
115 | +}; | ||
116 | + | ||
117 | +/** | ||
106 | * 2.11 Object End Type | 118 | * 2.11 Object End Type |
107 | * object-end-type = UTF-8-empty object-end-marker | 119 | * object-end-type = UTF-8-empty object-end-marker |
108 | * 0x00 0x00 0x09 | 120 | * 0x00 0x00 0x09 |
@@ -188,6 +200,14 @@ extern int srs_amf0_read_number(SrsStream* stream, double& value); | @@ -188,6 +200,14 @@ extern int srs_amf0_read_number(SrsStream* stream, double& value); | ||
188 | extern int srs_amf0_write_number(SrsStream* stream, double value); | 200 | extern int srs_amf0_write_number(SrsStream* stream, double value); |
189 | 201 | ||
190 | /** | 202 | /** |
203 | +* read amf0 null from stream. | ||
204 | +* 2.7 null Type | ||
205 | +* null-type = null-marker | ||
206 | +*/ | ||
207 | +extern int srs_amf0_read_null(SrsStream* stream); | ||
208 | +extern int srs_amf0_write_null(SrsStream* stream); | ||
209 | + | ||
210 | +/** | ||
191 | * read amf0 object from stream. | 211 | * read amf0 object from stream. |
192 | * 2.5 Object Type | 212 | * 2.5 Object Type |
193 | * anonymous-object-type = object-marker *(object-property) | 213 | * anonymous-object-type = object-marker *(object-property) |
@@ -212,6 +232,7 @@ extern int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* va | @@ -212,6 +232,7 @@ extern int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* va | ||
212 | extern int srs_amf0_get_utf8_size(std::string value); | 232 | extern int srs_amf0_get_utf8_size(std::string value); |
213 | extern int srs_amf0_get_string_size(std::string value); | 233 | extern int srs_amf0_get_string_size(std::string value); |
214 | extern int srs_amf0_get_number_size(); | 234 | extern int srs_amf0_get_number_size(); |
235 | +extern int srs_amf0_get_null_size(); | ||
215 | extern int srs_amf0_get_boolean_size(); | 236 | extern int srs_amf0_get_boolean_size(); |
216 | extern int srs_amf0_get_object_size(SrsAmf0Object* obj); | 237 | extern int srs_amf0_get_object_size(SrsAmf0Object* obj); |
217 | extern int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr); | 238 | extern int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr); |
@@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
29 | #include <srs_core_log.hpp> | 29 | #include <srs_core_log.hpp> |
30 | #include <srs_core_rtmp.hpp> | 30 | #include <srs_core_rtmp.hpp> |
31 | 31 | ||
32 | +// default stream id for response the createStream request. | ||
33 | +#define SRS_DEFAULT_SID 1 | ||
34 | + | ||
32 | SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) | 35 | SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) |
33 | : SrsConnection(srs_server, client_stfd) | 36 | : SrsConnection(srs_server, client_stfd) |
34 | { | 37 | { |
@@ -98,6 +101,20 @@ int SrsClient::do_cycle() | @@ -98,6 +101,20 @@ int SrsClient::do_cycle() | ||
98 | return ret; | 101 | return ret; |
99 | } | 102 | } |
100 | srs_verbose("response connect app success"); | 103 | srs_verbose("response connect app success"); |
104 | + | ||
105 | + if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) { | ||
106 | + srs_error("on_bw_done failed. ret=%d", ret); | ||
107 | + return ret; | ||
108 | + } | ||
109 | + srs_verbose("on_bw_done success"); | ||
110 | + | ||
111 | + SrsClientType type; | ||
112 | + std::string stream_name; | ||
113 | + if ((ret = rtmp->identify_client(SRS_DEFAULT_SID, type, stream_name)) != ERROR_SUCCESS) { | ||
114 | + srs_error("identify client failed. ret=%d", ret); | ||
115 | + return ret; | ||
116 | + } | ||
117 | + srs_verbose("identify client success. type=%d", type); | ||
101 | 118 | ||
102 | return ret; | 119 | return ret; |
103 | } | 120 | } |
@@ -202,9 +202,13 @@ messages. | @@ -202,9 +202,13 @@ messages. | ||
202 | ***************************************************************************** | 202 | ***************************************************************************** |
203 | ****************************************************************************/ | 203 | ****************************************************************************/ |
204 | /** | 204 | /** |
205 | -* amf0 command message, command name: "connect" | 205 | +* amf0 command message, command name macros |
206 | */ | 206 | */ |
207 | #define RTMP_AMF0_COMMAND_CONNECT "connect" | 207 | #define RTMP_AMF0_COMMAND_CONNECT "connect" |
208 | +#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" | ||
209 | +#define RTMP_AMF0_COMMAND_PLAY "play" | ||
210 | +#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" | ||
211 | +#define RTMP_AMF0_COMMAND_RESULT "_result" | ||
208 | 212 | ||
209 | /**************************************************************************** | 213 | /**************************************************************************** |
210 | ***************************************************************************** | 214 | ***************************************************************************** |
@@ -585,11 +589,12 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -585,11 +589,12 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
585 | int ret = ERROR_SUCCESS; | 589 | int ret = ERROR_SUCCESS; |
586 | 590 | ||
587 | // when not exists cached msg, means get an new message, | 591 | // when not exists cached msg, means get an new message, |
588 | - // the fmt must be type0 which means new message. | ||
589 | - if (!chunk->msg && fmt != RTMP_FMT_TYPE0) { | 592 | + // the fmt must be type0/type1 which means new message. |
593 | + if (!chunk->msg && fmt != RTMP_FMT_TYPE0 && fmt != RTMP_FMT_TYPE1) { | ||
590 | ret = ERROR_RTMP_CHUNK_START; | 594 | ret = ERROR_RTMP_CHUNK_START; |
591 | srs_error("chunk stream start, " | 595 | srs_error("chunk stream start, " |
592 | - "fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); | 596 | + "fmt must be %d or %d, actual is %d. ret=%d", |
597 | + RTMP_FMT_TYPE0, RTMP_FMT_TYPE1, fmt, ret); | ||
593 | return ret; | 598 | return ret; |
594 | } | 599 | } |
595 | 600 | ||
@@ -604,7 +609,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -604,7 +609,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
604 | 609 | ||
605 | // create msg when new chunk stream start | 610 | // create msg when new chunk stream start |
606 | if (!chunk->msg) { | 611 | if (!chunk->msg) { |
607 | - srs_assert(fmt == RTMP_FMT_TYPE0); | 612 | + srs_assert(fmt == RTMP_FMT_TYPE0 || fmt == RTMP_FMT_TYPE1); |
608 | chunk->msg = new SrsMessage(); | 613 | chunk->msg = new SrsMessage(); |
609 | srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); | 614 | srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); |
610 | } | 615 | } |
@@ -802,6 +807,21 @@ SrsMessageHeader::~SrsMessageHeader() | @@ -802,6 +807,21 @@ SrsMessageHeader::~SrsMessageHeader() | ||
802 | { | 807 | { |
803 | } | 808 | } |
804 | 809 | ||
810 | +bool SrsMessageHeader::is_amf0_command() | ||
811 | +{ | ||
812 | + return message_type == RTMP_MSG_AMF0CommandMessage; | ||
813 | +} | ||
814 | + | ||
815 | +bool SrsMessageHeader::is_amf3_command() | ||
816 | +{ | ||
817 | + return message_type == RTMP_MSG_AMF3CommandMessage; | ||
818 | +} | ||
819 | + | ||
820 | +bool SrsMessageHeader::is_window_ackledgement_size() | ||
821 | +{ | ||
822 | + return message_type == RTMP_MSG_WindowAcknowledgementSize; | ||
823 | +} | ||
824 | + | ||
805 | SrsChunkStream::SrsChunkStream(int _cid) | 825 | SrsChunkStream::SrsChunkStream(int _cid) |
806 | { | 826 | { |
807 | fmt = 0; | 827 | fmt = 0; |
@@ -870,30 +890,50 @@ int SrsMessage::decode_packet() | @@ -870,30 +890,50 @@ int SrsMessage::decode_packet() | ||
870 | srs_verbose("decode stream initialized success"); | 890 | srs_verbose("decode stream initialized success"); |
871 | 891 | ||
872 | // decode specified packet type | 892 | // decode specified packet type |
873 | - if (header.message_type == RTMP_MSG_AMF0CommandMessage) { | ||
874 | - srs_verbose("start to decode AMF0 command message."); | 893 | + if (header.is_amf0_command() || header.is_amf3_command()) { |
894 | + srs_verbose("start to decode AMF0/AMF3 command message."); | ||
895 | + | ||
896 | + // skip 1bytes to decode the amf3 command. | ||
897 | + if (header.is_amf3_command() && stream->require(1)) { | ||
898 | + srs_verbose("skip 1bytes to decode AMF3 command"); | ||
899 | + stream->skip(1); | ||
900 | + } | ||
875 | 901 | ||
876 | // amf0 command message. | 902 | // amf0 command message. |
877 | // need to read the command name. | 903 | // need to read the command name. |
878 | std::string command; | 904 | std::string command; |
879 | if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) { | 905 | if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) { |
880 | - srs_error("decode AMF0 command name failed. ret=%d", ret); | 906 | + srs_error("decode AMF0/AMF3 command name failed. ret=%d", ret); |
881 | return ret; | 907 | return ret; |
882 | } | 908 | } |
883 | - srs_verbose("AMF0 command message, command_name=%s", command.c_str()); | 909 | + srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str()); |
884 | 910 | ||
911 | + // reset to zero(amf3 to 1) to restart decode. | ||
885 | stream->reset(); | 912 | stream->reset(); |
913 | + if (header.is_amf3_command()) { | ||
914 | + stream->skip(1); | ||
915 | + } | ||
916 | + | ||
917 | + // decode command object. | ||
886 | if (command == RTMP_AMF0_COMMAND_CONNECT) { | 918 | if (command == RTMP_AMF0_COMMAND_CONNECT) { |
887 | - srs_info("decode the AMF0 command(connect vhost/app message)."); | 919 | + srs_info("decode the AMF0/AMF3 command(connect vhost/app message)."); |
888 | packet = new SrsConnectAppPacket(); | 920 | packet = new SrsConnectAppPacket(); |
889 | return packet->decode(stream); | 921 | return packet->decode(stream); |
922 | + } else if(command == RTMP_AMF0_COMMAND_CREATE_STREAM) { | ||
923 | + srs_info("decode the AMF0/AMF3 command(createStream message)."); | ||
924 | + packet = new SrsCreateStreamPacket(); | ||
925 | + return packet->decode(stream); | ||
926 | + } else if(command == RTMP_AMF0_COMMAND_PLAY) { | ||
927 | + srs_info("decode the AMF0/AMF3 command(paly message)."); | ||
928 | + packet = new SrsPlayPacket(); | ||
929 | + return packet->decode(stream); | ||
890 | } | 930 | } |
891 | 931 | ||
892 | // default packet to drop message. | 932 | // default packet to drop message. |
893 | - srs_trace("drop the AMF0 command message, command_name=%s", command.c_str()); | 933 | + srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str()); |
894 | packet = new SrsPacket(); | 934 | packet = new SrsPacket(); |
895 | return ret; | 935 | return ret; |
896 | - } else if(header.message_type == RTMP_MSG_WindowAcknowledgementSize) { | 936 | + } else if(header.is_window_ackledgement_size()) { |
897 | srs_verbose("start to decode set ack window size message."); | 937 | srs_verbose("start to decode set ack window size message."); |
898 | packet = new SrsSetWindowAckSizePacket(); | 938 | packet = new SrsSetWindowAckSizePacket(); |
899 | return packet->decode(stream); | 939 | return packet->decode(stream); |
@@ -1106,7 +1146,7 @@ int SrsConnectAppPacket::decode(SrsStream* stream) | @@ -1106,7 +1146,7 @@ int SrsConnectAppPacket::decode(SrsStream* stream) | ||
1106 | 1146 | ||
1107 | SrsConnectAppResPacket::SrsConnectAppResPacket() | 1147 | SrsConnectAppResPacket::SrsConnectAppResPacket() |
1108 | { | 1148 | { |
1109 | - command_name = RTMP_AMF0_COMMAND_CONNECT; | 1149 | + command_name = RTMP_AMF0_COMMAND_RESULT; |
1110 | transaction_id = 1; | 1150 | transaction_id = 1; |
1111 | props = new SrsAmf0Object(); | 1151 | props = new SrsAmf0Object(); |
1112 | info = new SrsAmf0Object(); | 1152 | info = new SrsAmf0Object(); |
@@ -1175,6 +1215,313 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream) | @@ -1175,6 +1215,313 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream) | ||
1175 | return ret; | 1215 | return ret; |
1176 | } | 1216 | } |
1177 | 1217 | ||
1218 | +SrsCreateStreamPacket::SrsCreateStreamPacket() | ||
1219 | +{ | ||
1220 | + command_name = RTMP_AMF0_COMMAND_CREATE_STREAM; | ||
1221 | + transaction_id = 2; | ||
1222 | + command_object = new SrsAmf0Null(); | ||
1223 | +} | ||
1224 | + | ||
1225 | +SrsCreateStreamPacket::~SrsCreateStreamPacket() | ||
1226 | +{ | ||
1227 | + if (command_object) { | ||
1228 | + delete command_object; | ||
1229 | + command_object = NULL; | ||
1230 | + } | ||
1231 | +} | ||
1232 | + | ||
1233 | +int SrsCreateStreamPacket::decode(SrsStream* stream) | ||
1234 | +{ | ||
1235 | + int ret = ERROR_SUCCESS; | ||
1236 | + | ||
1237 | + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { | ||
1238 | + srs_error("amf0 decode createStream command_name failed. ret=%d", ret); | ||
1239 | + return ret; | ||
1240 | + } | ||
1241 | + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CREATE_STREAM) { | ||
1242 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
1243 | + srs_error("amf0 decode createStream command_name failed. " | ||
1244 | + "command_name=%s, ret=%d", command_name.c_str(), ret); | ||
1245 | + return ret; | ||
1246 | + } | ||
1247 | + | ||
1248 | + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
1249 | + srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret); | ||
1250 | + return ret; | ||
1251 | + } | ||
1252 | + | ||
1253 | + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { | ||
1254 | + srs_error("amf0 decode createStream command_object failed. ret=%d", ret); | ||
1255 | + return ret; | ||
1256 | + } | ||
1257 | + | ||
1258 | + srs_info("amf0 decode createStream packet success"); | ||
1259 | + | ||
1260 | + return ret; | ||
1261 | +} | ||
1262 | + | ||
1263 | +SrsCreateStreamResPacket::SrsCreateStreamResPacket(double _transaction_id, double _stream_id) | ||
1264 | +{ | ||
1265 | + command_name = RTMP_AMF0_COMMAND_RESULT; | ||
1266 | + transaction_id = _transaction_id; | ||
1267 | + command_object = new SrsAmf0Null(); | ||
1268 | + stream_id = _stream_id; | ||
1269 | +} | ||
1270 | + | ||
1271 | +SrsCreateStreamResPacket::~SrsCreateStreamResPacket() | ||
1272 | +{ | ||
1273 | + if (command_object) { | ||
1274 | + delete command_object; | ||
1275 | + command_object = NULL; | ||
1276 | + } | ||
1277 | +} | ||
1278 | + | ||
1279 | +int SrsCreateStreamResPacket::get_perfer_cid() | ||
1280 | +{ | ||
1281 | + return RTMP_CID_OverConnection; | ||
1282 | +} | ||
1283 | + | ||
1284 | +int SrsCreateStreamResPacket::get_message_type() | ||
1285 | +{ | ||
1286 | + return RTMP_MSG_AMF0CommandMessage; | ||
1287 | +} | ||
1288 | + | ||
1289 | +int SrsCreateStreamResPacket::get_size() | ||
1290 | +{ | ||
1291 | + return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size() | ||
1292 | + + srs_amf0_get_null_size() + srs_amf0_get_number_size(); | ||
1293 | +} | ||
1294 | + | ||
1295 | +int SrsCreateStreamResPacket::encode_packet(SrsStream* stream) | ||
1296 | +{ | ||
1297 | + int ret = ERROR_SUCCESS; | ||
1298 | + | ||
1299 | + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { | ||
1300 | + srs_error("encode command_name failed. ret=%d", ret); | ||
1301 | + return ret; | ||
1302 | + } | ||
1303 | + srs_verbose("encode command_name success."); | ||
1304 | + | ||
1305 | + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
1306 | + srs_error("encode transaction_id failed. ret=%d", ret); | ||
1307 | + return ret; | ||
1308 | + } | ||
1309 | + srs_verbose("encode transaction_id success."); | ||
1310 | + | ||
1311 | + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { | ||
1312 | + srs_error("encode command_object failed. ret=%d", ret); | ||
1313 | + return ret; | ||
1314 | + } | ||
1315 | + srs_verbose("encode command_object success."); | ||
1316 | + | ||
1317 | + if ((ret = srs_amf0_write_number(stream, stream_id)) != ERROR_SUCCESS) { | ||
1318 | + srs_error("encode stream_id failed. ret=%d", ret); | ||
1319 | + return ret; | ||
1320 | + } | ||
1321 | + srs_verbose("encode stream_id success."); | ||
1322 | + | ||
1323 | + | ||
1324 | + srs_info("encode createStream response packet success."); | ||
1325 | + | ||
1326 | + return ret; | ||
1327 | +} | ||
1328 | + | ||
1329 | +SrsPlayPacket::SrsPlayPacket() | ||
1330 | +{ | ||
1331 | + command_name = RTMP_AMF0_COMMAND_PLAY; | ||
1332 | + transaction_id = 0; | ||
1333 | + command_object = new SrsAmf0Null(); | ||
1334 | + | ||
1335 | + start = -2; | ||
1336 | + duration = -1; | ||
1337 | + reset = true; | ||
1338 | +} | ||
1339 | + | ||
1340 | +SrsPlayPacket::~SrsPlayPacket() | ||
1341 | +{ | ||
1342 | + if (command_object) { | ||
1343 | + delete command_object; | ||
1344 | + command_object = NULL; | ||
1345 | + } | ||
1346 | +} | ||
1347 | + | ||
1348 | +int SrsPlayPacket::decode(SrsStream* stream) | ||
1349 | +{ | ||
1350 | + int ret = ERROR_SUCCESS; | ||
1351 | + | ||
1352 | + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { | ||
1353 | + srs_error("amf0 decode play command_name failed. ret=%d", ret); | ||
1354 | + return ret; | ||
1355 | + } | ||
1356 | + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PLAY) { | ||
1357 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
1358 | + srs_error("amf0 decode play command_name failed. " | ||
1359 | + "command_name=%s, ret=%d", command_name.c_str(), ret); | ||
1360 | + return ret; | ||
1361 | + } | ||
1362 | + | ||
1363 | + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
1364 | + srs_error("amf0 decode play transaction_id failed. ret=%d", ret); | ||
1365 | + return ret; | ||
1366 | + } | ||
1367 | + | ||
1368 | + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { | ||
1369 | + srs_error("amf0 decode play command_object failed. ret=%d", ret); | ||
1370 | + return ret; | ||
1371 | + } | ||
1372 | + | ||
1373 | + if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { | ||
1374 | + srs_error("amf0 decode play stream_name failed. ret=%d", ret); | ||
1375 | + return ret; | ||
1376 | + } | ||
1377 | + | ||
1378 | + if (!stream->empty() && (ret = srs_amf0_read_number(stream, start)) != ERROR_SUCCESS) { | ||
1379 | + srs_error("amf0 decode play start failed. ret=%d", ret); | ||
1380 | + return ret; | ||
1381 | + } | ||
1382 | + if (!stream->empty() && (ret = srs_amf0_read_number(stream, duration)) != ERROR_SUCCESS) { | ||
1383 | + srs_error("amf0 decode play duration failed. ret=%d", ret); | ||
1384 | + return ret; | ||
1385 | + } | ||
1386 | + if (!stream->empty() && (ret = srs_amf0_read_boolean(stream, reset)) != ERROR_SUCCESS) { | ||
1387 | + srs_error("amf0 decode play reset failed. ret=%d", ret); | ||
1388 | + return ret; | ||
1389 | + } | ||
1390 | + | ||
1391 | + srs_info("amf0 decode play packet success"); | ||
1392 | + | ||
1393 | + return ret; | ||
1394 | +} | ||
1395 | + | ||
1396 | +SrsPlayResPacket::SrsPlayResPacket() | ||
1397 | +{ | ||
1398 | + command_name = RTMP_AMF0_COMMAND_RESULT; | ||
1399 | + transaction_id = 0; | ||
1400 | + command_object = new SrsAmf0Null(); | ||
1401 | + desc = new SrsAmf0Object(); | ||
1402 | +} | ||
1403 | + | ||
1404 | +SrsPlayResPacket::~SrsPlayResPacket() | ||
1405 | +{ | ||
1406 | + if (command_object) { | ||
1407 | + delete command_object; | ||
1408 | + command_object = NULL; | ||
1409 | + } | ||
1410 | + | ||
1411 | + if (desc) { | ||
1412 | + delete desc; | ||
1413 | + desc = NULL; | ||
1414 | + } | ||
1415 | +} | ||
1416 | + | ||
1417 | +int SrsPlayResPacket::get_perfer_cid() | ||
1418 | +{ | ||
1419 | + return RTMP_CID_OverStream; | ||
1420 | +} | ||
1421 | + | ||
1422 | +int SrsPlayResPacket::get_message_type() | ||
1423 | +{ | ||
1424 | + return RTMP_MSG_AMF0CommandMessage; | ||
1425 | +} | ||
1426 | + | ||
1427 | +int SrsPlayResPacket::get_size() | ||
1428 | +{ | ||
1429 | + return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size() | ||
1430 | + + srs_amf0_get_null_size() + srs_amf0_get_object_size(desc); | ||
1431 | +} | ||
1432 | + | ||
1433 | +int SrsPlayResPacket::encode_packet(SrsStream* stream) | ||
1434 | +{ | ||
1435 | + int ret = ERROR_SUCCESS; | ||
1436 | + | ||
1437 | + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { | ||
1438 | + srs_error("encode command_name failed. ret=%d", ret); | ||
1439 | + return ret; | ||
1440 | + } | ||
1441 | + srs_verbose("encode command_name success."); | ||
1442 | + | ||
1443 | + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
1444 | + srs_error("encode transaction_id failed. ret=%d", ret); | ||
1445 | + return ret; | ||
1446 | + } | ||
1447 | + srs_verbose("encode transaction_id success."); | ||
1448 | + | ||
1449 | + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { | ||
1450 | + srs_error("encode command_object failed. ret=%d", ret); | ||
1451 | + return ret; | ||
1452 | + } | ||
1453 | + srs_verbose("encode command_object success."); | ||
1454 | + | ||
1455 | + if ((ret = srs_amf0_write_object(stream, desc)) != ERROR_SUCCESS) { | ||
1456 | + srs_error("encode desc failed. ret=%d", ret); | ||
1457 | + return ret; | ||
1458 | + } | ||
1459 | + srs_verbose("encode desc success."); | ||
1460 | + | ||
1461 | + | ||
1462 | + srs_info("encode play response packet success."); | ||
1463 | + | ||
1464 | + return ret; | ||
1465 | +} | ||
1466 | + | ||
1467 | +SrsOnBWDonePacket::SrsOnBWDonePacket() | ||
1468 | +{ | ||
1469 | + command_name = RTMP_AMF0_COMMAND_ON_BW_DONE; | ||
1470 | + transaction_id = 0; | ||
1471 | + args = new SrsAmf0Null(); | ||
1472 | +} | ||
1473 | + | ||
1474 | +SrsOnBWDonePacket::~SrsOnBWDonePacket() | ||
1475 | +{ | ||
1476 | + if (args) { | ||
1477 | + delete args; | ||
1478 | + args = NULL; | ||
1479 | + } | ||
1480 | +} | ||
1481 | + | ||
1482 | +int SrsOnBWDonePacket::get_perfer_cid() | ||
1483 | +{ | ||
1484 | + return RTMP_CID_OverConnection; | ||
1485 | +} | ||
1486 | + | ||
1487 | +int SrsOnBWDonePacket::get_message_type() | ||
1488 | +{ | ||
1489 | + return RTMP_MSG_AMF0CommandMessage; | ||
1490 | +} | ||
1491 | + | ||
1492 | +int SrsOnBWDonePacket::get_size() | ||
1493 | +{ | ||
1494 | + return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size() | ||
1495 | + + srs_amf0_get_null_size(); | ||
1496 | +} | ||
1497 | + | ||
1498 | +int SrsOnBWDonePacket::encode_packet(SrsStream* stream) | ||
1499 | +{ | ||
1500 | + int ret = ERROR_SUCCESS; | ||
1501 | + | ||
1502 | + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { | ||
1503 | + srs_error("encode command_name failed. ret=%d", ret); | ||
1504 | + return ret; | ||
1505 | + } | ||
1506 | + srs_verbose("encode command_name success."); | ||
1507 | + | ||
1508 | + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
1509 | + srs_error("encode transaction_id failed. ret=%d", ret); | ||
1510 | + return ret; | ||
1511 | + } | ||
1512 | + srs_verbose("encode transaction_id success."); | ||
1513 | + | ||
1514 | + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { | ||
1515 | + srs_error("encode args failed. ret=%d", ret); | ||
1516 | + return ret; | ||
1517 | + } | ||
1518 | + srs_verbose("encode args success."); | ||
1519 | + | ||
1520 | + srs_info("encode onBWDone packet success."); | ||
1521 | + | ||
1522 | + return ret; | ||
1523 | +} | ||
1524 | + | ||
1178 | SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket() | 1525 | SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket() |
1179 | { | 1526 | { |
1180 | ackowledgement_window_size = 0; | 1527 | ackowledgement_window_size = 0; |
@@ -45,6 +45,7 @@ class SrsStream; | @@ -45,6 +45,7 @@ class SrsStream; | ||
45 | class SrsMessage; | 45 | class SrsMessage; |
46 | class SrsChunkStream; | 46 | class SrsChunkStream; |
47 | class SrsAmf0Object; | 47 | class SrsAmf0Object; |
48 | +class SrsAmf0Null; | ||
48 | 49 | ||
49 | // convert class name to string. | 50 | // convert class name to string. |
50 | #define CLASS_NAME_STRING(className) #className | 51 | #define CLASS_NAME_STRING(className) #className |
@@ -166,6 +167,10 @@ struct SrsMessageHeader | @@ -166,6 +167,10 @@ struct SrsMessageHeader | ||
166 | 167 | ||
167 | SrsMessageHeader(); | 168 | SrsMessageHeader(); |
168 | virtual ~SrsMessageHeader(); | 169 | virtual ~SrsMessageHeader(); |
170 | + | ||
171 | + bool is_amf0_command(); | ||
172 | + bool is_amf3_command(); | ||
173 | + bool is_window_ackledgement_size(); | ||
169 | }; | 174 | }; |
170 | 175 | ||
171 | /** | 176 | /** |
@@ -358,6 +363,146 @@ protected: | @@ -358,6 +363,146 @@ protected: | ||
358 | }; | 363 | }; |
359 | 364 | ||
360 | /** | 365 | /** |
366 | +* 4.1.3. createStream | ||
367 | +* The client sends this command to the server to create a logical | ||
368 | +* channel for message communication The publishing of audio, video, and | ||
369 | +* metadata is carried out over stream channel created using the | ||
370 | +* createStream command. | ||
371 | +*/ | ||
372 | +class SrsCreateStreamPacket : public SrsPacket | ||
373 | +{ | ||
374 | +private: | ||
375 | + typedef SrsPacket super; | ||
376 | +protected: | ||
377 | + virtual const char* get_class_name() | ||
378 | + { | ||
379 | + return CLASS_NAME_STRING(SrsCreateStreamPacket); | ||
380 | + } | ||
381 | +public: | ||
382 | + std::string command_name; | ||
383 | + double transaction_id; | ||
384 | + SrsAmf0Null* command_object; | ||
385 | +public: | ||
386 | + SrsCreateStreamPacket(); | ||
387 | + virtual ~SrsCreateStreamPacket(); | ||
388 | +public: | ||
389 | + virtual int decode(SrsStream* stream); | ||
390 | +}; | ||
391 | +/** | ||
392 | +* response for SrsCreateStreamPacket. | ||
393 | +*/ | ||
394 | +class SrsCreateStreamResPacket : public SrsPacket | ||
395 | +{ | ||
396 | +private: | ||
397 | + typedef SrsPacket super; | ||
398 | +protected: | ||
399 | + virtual const char* get_class_name() | ||
400 | + { | ||
401 | + return CLASS_NAME_STRING(SrsCreateStreamResPacket); | ||
402 | + } | ||
403 | +public: | ||
404 | + std::string command_name; | ||
405 | + double transaction_id; | ||
406 | + SrsAmf0Null* command_object; | ||
407 | + double stream_id; | ||
408 | +public: | ||
409 | + SrsCreateStreamResPacket(double _transaction_id, double _stream_id); | ||
410 | + virtual ~SrsCreateStreamResPacket(); | ||
411 | +public: | ||
412 | + virtual int get_perfer_cid(); | ||
413 | +public: | ||
414 | + virtual int get_message_type(); | ||
415 | +protected: | ||
416 | + virtual int get_size(); | ||
417 | + virtual int encode_packet(SrsStream* stream); | ||
418 | +}; | ||
419 | + | ||
420 | +/** | ||
421 | +* 4.2.1. play | ||
422 | +* The client sends this command to the server to play a stream. | ||
423 | +*/ | ||
424 | +class SrsPlayPacket : public SrsPacket | ||
425 | +{ | ||
426 | +private: | ||
427 | + typedef SrsPacket super; | ||
428 | +protected: | ||
429 | + virtual const char* get_class_name() | ||
430 | + { | ||
431 | + return CLASS_NAME_STRING(SrsPlayPacket); | ||
432 | + } | ||
433 | +public: | ||
434 | + std::string command_name; | ||
435 | + double transaction_id; | ||
436 | + SrsAmf0Null* command_object; | ||
437 | + std::string stream_name; | ||
438 | + double start; | ||
439 | + double duration; | ||
440 | + bool reset; | ||
441 | +public: | ||
442 | + SrsPlayPacket(); | ||
443 | + virtual ~SrsPlayPacket(); | ||
444 | +public: | ||
445 | + virtual int decode(SrsStream* stream); | ||
446 | +}; | ||
447 | +/** | ||
448 | +* response for SrsPlayPacket. | ||
449 | +* @remark, user must set the stream_id in header. | ||
450 | +*/ | ||
451 | +class SrsPlayResPacket : public SrsPacket | ||
452 | +{ | ||
453 | +private: | ||
454 | + typedef SrsPacket super; | ||
455 | +protected: | ||
456 | + virtual const char* get_class_name() | ||
457 | + { | ||
458 | + return CLASS_NAME_STRING(SrsPlayResPacket); | ||
459 | + } | ||
460 | +public: | ||
461 | + std::string command_name; | ||
462 | + double transaction_id; | ||
463 | + SrsAmf0Null* command_object; | ||
464 | + SrsAmf0Object* desc; | ||
465 | +public: | ||
466 | + SrsPlayResPacket(); | ||
467 | + virtual ~SrsPlayResPacket(); | ||
468 | +public: | ||
469 | + virtual int get_perfer_cid(); | ||
470 | +public: | ||
471 | + virtual int get_message_type(); | ||
472 | +protected: | ||
473 | + virtual int get_size(); | ||
474 | + virtual int encode_packet(SrsStream* stream); | ||
475 | +}; | ||
476 | + | ||
477 | +/** | ||
478 | +* when bandwidth test done, notice client. | ||
479 | +*/ | ||
480 | +class SrsOnBWDonePacket : public SrsPacket | ||
481 | +{ | ||
482 | +private: | ||
483 | + typedef SrsPacket super; | ||
484 | +protected: | ||
485 | + virtual const char* get_class_name() | ||
486 | + { | ||
487 | + return CLASS_NAME_STRING(SrsOnBWDonePacket); | ||
488 | + } | ||
489 | +public: | ||
490 | + std::string command_name; | ||
491 | + double transaction_id; | ||
492 | + SrsAmf0Null* args; | ||
493 | +public: | ||
494 | + SrsOnBWDonePacket(); | ||
495 | + virtual ~SrsOnBWDonePacket(); | ||
496 | +public: | ||
497 | + virtual int get_perfer_cid(); | ||
498 | +public: | ||
499 | + virtual int get_message_type(); | ||
500 | +protected: | ||
501 | + virtual int get_size(); | ||
502 | + virtual int encode_packet(SrsStream* stream); | ||
503 | +}; | ||
504 | + | ||
505 | +/** | ||
361 | * 5.5. Window Acknowledgement Size (5) | 506 | * 5.5. Window Acknowledgement Size (5) |
362 | * The client or the server sends this message to inform the peer which | 507 | * The client or the server sends this message to inform the peer which |
363 | * window size to use when sending acknowledgment. | 508 | * window size to use when sending acknowledgment. |
@@ -221,8 +221,6 @@ int SrsRtmp::response_connect_app() | @@ -221,8 +221,6 @@ int SrsRtmp::response_connect_app() | ||
221 | SrsMessage* msg = new SrsMessage(); | 221 | SrsMessage* msg = new SrsMessage(); |
222 | SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); | 222 | SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); |
223 | 223 | ||
224 | - pkt->command_name = "_result"; | ||
225 | - | ||
226 | pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER); | 224 | pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER); |
227 | pkt->props->properties["capabilities"] = new SrsAmf0Number(123); | 225 | pkt->props->properties["capabilities"] = new SrsAmf0Number(123); |
228 | pkt->props->properties["mode"] = new SrsAmf0Number(1); | 226 | pkt->props->properties["mode"] = new SrsAmf0Number(1); |
@@ -250,3 +248,110 @@ int SrsRtmp::response_connect_app() | @@ -250,3 +248,110 @@ int SrsRtmp::response_connect_app() | ||
250 | return ret; | 248 | return ret; |
251 | } | 249 | } |
252 | 250 | ||
251 | +int SrsRtmp::on_bw_done() | ||
252 | +{ | ||
253 | + int ret = ERROR_SUCCESS; | ||
254 | + | ||
255 | + SrsMessage* msg = new SrsMessage(); | ||
256 | + SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); | ||
257 | + | ||
258 | + msg->set_packet(pkt); | ||
259 | + | ||
260 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
261 | + srs_error("send onBWDone message failed. ret=%d", ret); | ||
262 | + return ret; | ||
263 | + } | ||
264 | + srs_info("send onBWDone message success."); | ||
265 | + | ||
266 | + return ret; | ||
267 | +} | ||
268 | + | ||
269 | +int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name) | ||
270 | +{ | ||
271 | + type = SrsClientUnknown; | ||
272 | + int ret = ERROR_SUCCESS; | ||
273 | + | ||
274 | + while (true) { | ||
275 | + SrsMessage* msg = NULL; | ||
276 | + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
277 | + srs_error("recv identify client message failed. ret=%d", ret); | ||
278 | + return ret; | ||
279 | + } | ||
280 | + | ||
281 | + SrsAutoFree(SrsMessage, msg, false); | ||
282 | + | ||
283 | + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
284 | + srs_trace("identify ignore messages except " | ||
285 | + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
286 | + continue; | ||
287 | + } | ||
288 | + | ||
289 | + if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { | ||
290 | + srs_error("identify decode message failed. ret=%d", ret); | ||
291 | + return ret; | ||
292 | + } | ||
293 | + | ||
294 | + SrsPacket* pkt = msg->get_packet(); | ||
295 | + if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) { | ||
296 | + return identify_create_stream_client( | ||
297 | + dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name); | ||
298 | + } | ||
299 | + | ||
300 | + srs_trace("ignore AMF0/AMF3 command message."); | ||
301 | + } | ||
302 | + | ||
303 | + return ret; | ||
304 | +} | ||
305 | + | ||
306 | +int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) | ||
307 | +{ | ||
308 | + int ret = ERROR_SUCCESS; | ||
309 | + | ||
310 | + if (true) { | ||
311 | + SrsMessage* msg = new SrsMessage(); | ||
312 | + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); | ||
313 | + | ||
314 | + msg->set_packet(pkt); | ||
315 | + | ||
316 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
317 | + srs_error("send createStream response message failed. ret=%d", ret); | ||
318 | + return ret; | ||
319 | + } | ||
320 | + srs_info("send createStream response message success."); | ||
321 | + } | ||
322 | + | ||
323 | + while (true) { | ||
324 | + SrsMessage* msg = NULL; | ||
325 | + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
326 | + srs_error("recv identify client message failed. ret=%d", ret); | ||
327 | + return ret; | ||
328 | + } | ||
329 | + | ||
330 | + SrsAutoFree(SrsMessage, msg, false); | ||
331 | + | ||
332 | + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
333 | + srs_trace("identify ignore messages except " | ||
334 | + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
335 | + continue; | ||
336 | + } | ||
337 | + | ||
338 | + if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { | ||
339 | + srs_error("identify decode message failed. ret=%d", ret); | ||
340 | + return ret; | ||
341 | + } | ||
342 | + | ||
343 | + SrsPacket* pkt = msg->get_packet(); | ||
344 | + if (dynamic_cast<SrsPlayPacket*>(pkt)) { | ||
345 | + SrsPlayPacket* play = dynamic_cast<SrsPlayPacket*>(pkt); | ||
346 | + type = SrsClientPublish; | ||
347 | + stream_name = play->stream_name; | ||
348 | + srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); | ||
349 | + return ret; | ||
350 | + } | ||
351 | + | ||
352 | + srs_trace("ignore AMF0/AMF3 command message."); | ||
353 | + } | ||
354 | + | ||
355 | + return ret; | ||
356 | +} | ||
357 | + |
@@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
35 | #include <st.h> | 35 | #include <st.h> |
36 | 36 | ||
37 | class SrsProtocol; | 37 | class SrsProtocol; |
38 | +class SrsCreateStreamPacket; | ||
38 | 39 | ||
39 | /** | 40 | /** |
40 | * the original request from client. | 41 | * the original request from client. |
@@ -58,6 +59,16 @@ struct SrsRequest | @@ -58,6 +59,16 @@ struct SrsRequest | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | /** | 61 | /** |
62 | +* the rtmp client type. | ||
63 | +*/ | ||
64 | +enum SrsClientType | ||
65 | +{ | ||
66 | + SrsClientUnknown, | ||
67 | + SrsClientPlay, | ||
68 | + SrsClientPublish, | ||
69 | +}; | ||
70 | + | ||
71 | +/** | ||
61 | * the rtmp provices rtmp-command-protocol services, | 72 | * the rtmp provices rtmp-command-protocol services, |
62 | * a high level protocol, media stream oriented services, | 73 | * a high level protocol, media stream oriented services, |
63 | * such as connect to vhost/app, play stream, get audio/video data. | 74 | * such as connect to vhost/app, play stream, get audio/video data. |
@@ -80,6 +91,16 @@ public: | @@ -80,6 +91,16 @@ public: | ||
80 | */ | 91 | */ |
81 | virtual int set_peer_bandwidth(int bandwidth, int type); | 92 | virtual int set_peer_bandwidth(int bandwidth, int type); |
82 | virtual int response_connect_app(); | 93 | virtual int response_connect_app(); |
94 | + virtual int on_bw_done(); | ||
95 | + /** | ||
96 | + * recv some message to identify the client. | ||
97 | + * @stream_id, client will createStream to play or publish by flash, | ||
98 | + * the stream_id used to response the createStream request. | ||
99 | + * @type, output the client type. | ||
100 | + */ | ||
101 | + virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name); | ||
102 | +private: | ||
103 | + virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); | ||
83 | }; | 104 | }; |
84 | 105 | ||
85 | #endif | 106 | #endif |
-
请 注册 或 登录 后发表评论