From 841f0f8899ccd943f9ab4a7cbbb28abe8426e014 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 19 Mar 2014 14:58:29 +0800 Subject: [PATCH] change to 0.9.19, verify the s1/s2/c2, refine the handshake. --- trunk/src/core/srs_core.hpp | 2 +- trunk/src/core/srs_core_autofree.hpp | 2 +- trunk/src/rtmp/srs_protocol_handshake.cpp | 217 ++++++++++++---------- trunk/src/rtmp/srs_protocol_handshake.hpp | 28 ++- trunk/src/rtmp/srs_protocol_rtmp.cpp | 164 +++++++++++++++- trunk/src/rtmp/srs_protocol_rtmp.hpp | 28 +++ trunk/src/rtmp/srs_protocol_utility.cpp | 24 +++ trunk/src/rtmp/srs_protocol_utility.hpp | 2 + 8 files changed, 349 insertions(+), 118 deletions(-) diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 09ffa95e1..04da95617 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "0" #define VERSION_MINOR "9" -#define VERSION_REVISION "18" +#define VERSION_REVISION "19" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "srs" diff --git a/trunk/src/core/srs_core_autofree.hpp b/trunk/src/core/srs_core_autofree.hpp index 2938bdc82..0be49f79f 100644 --- a/trunk/src/core/srs_core_autofree.hpp +++ b/trunk/src/core/srs_core_autofree.hpp @@ -34,7 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * auto free the instance in the current scope. */ #define SrsAutoFree(className, instance, is_array) \ - __SrsAutoFree _auto_free_##instance(&instance, is_array) + __SrsAutoFree _auto_free_##instance((className**)&instance, is_array) template class __SrsAutoFree diff --git a/trunk/src/rtmp/srs_protocol_handshake.cpp b/trunk/src/rtmp/srs_protocol_handshake.cpp index 1d4810fb0..e04488a48 100644 --- a/trunk/src/rtmp/srs_protocol_handshake.cpp +++ b/trunk/src/rtmp/srs_protocol_handshake.cpp @@ -24,28 +24,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include #include #include #include #include +#include +#include using namespace srs; -void srs_random_generate(char* bytes, int size) -{ - static char cdata[] = { - 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, 0x31, 0x32, 0x36, - 0x2e, 0x63, 0x6f, 0x6d - }; - for (int i = 0; i < size; i++) { - bytes[i] = cdata[rand() % (sizeof(cdata) - 1)]; - } -} - #ifdef SRS_SSL // 68bytes FMS key which is used to sign the sever packet. @@ -569,6 +557,12 @@ void c2s2::dump(char* _c2s2) memcpy(_c2s2 + 1504, digest, 32); } +void c2s2::parse(char* _c2s2) +{ + memcpy(random, _c2s2, 1504); + memcpy(digest, _c2s2 + 1504, 32); +} + int c2s2::c2_create(c1s1* s1) { int ret = ERROR_SUCCESS; @@ -592,6 +586,30 @@ int c2s2::c2_create(c1s1* s1) return ret; } +int c2s2::c2_validate(c1s1* s1, bool& is_valid) +{ + is_valid = false; + int ret = ERROR_SUCCESS; + + char temp_key[OpensslHashSize]; + if ((ret = openssl_HMACsha256(s1->get_digest(), 32, SrsGenuineFPKey, 62, temp_key)) != ERROR_SUCCESS) { + srs_error("create c2 temp key failed. ret=%d", ret); + return ret; + } + srs_verbose("generate c2 temp key success."); + + char _digest[OpensslHashSize]; + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { + srs_error("create c2 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("generate c2 digest success."); + + is_valid = srs_bytes_equals(digest, _digest, 32); + + return ret; +} + int c2s2::s2_create(c1s1* c1) { int ret = ERROR_SUCCESS; @@ -615,6 +633,30 @@ int c2s2::s2_create(c1s1* c1) return ret; } +int c2s2::s2_validate(c1s1* c1, bool& is_valid) +{ + is_valid = false; + int ret = ERROR_SUCCESS; + + char temp_key[OpensslHashSize]; + if ((ret = openssl_HMACsha256(c1->get_digest(), 32, SrsGenuineFMSKey, 68, temp_key)) != ERROR_SUCCESS) { + srs_error("create s2 temp key failed. ret=%d", ret); + return ret; + } + srs_verbose("generate s2 temp key success."); + + char _digest[OpensslHashSize]; + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { + srs_error("create s2 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("generate s2 digest success."); + + is_valid = srs_bytes_equals(digest, _digest, 32); + + return ret; +} + c1s1::c1s1() { schema = srs_schema_invalid; @@ -738,6 +780,7 @@ int c1s1::c1_parse(char* _c1s1, srs_schema_type _schema) int c1s1::c1_validate_digest(bool& is_valid) { + is_valid = false; int ret = ERROR_SUCCESS; char* c1_digest = NULL; @@ -761,6 +804,7 @@ int c1s1::c1_validate_digest(bool& is_valid) int c1s1::s1_validate_digest(bool& is_valid) { + is_valid = false; int ret = ERROR_SUCCESS; char* s1_digest = NULL; @@ -918,125 +962,85 @@ SrsSimpleHandshake::~SrsSimpleHandshake() { } -int SrsSimpleHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs) +int SrsSimpleHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io) { int ret = ERROR_SUCCESS; ssize_t nsize; - char* c0c1 = new char[1537]; - SrsAutoFree(char, c0c1, true); - if ((ret = skt->read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { - srs_warn("read c0c1 failed. ret=%d", ret); + if ((ret = hs_bytes->read_c0c1(io)) != ERROR_SUCCESS) { return ret; } - srs_verbose("read c0c1 success."); // plain text required. - if (c0c1[0] != 0x03) { + if (hs_bytes->c0c1[0] != 0x03) { ret = ERROR_RTMP_PLAIN_REQUIRED; srs_warn("only support rtmp plain text. ret=%d", ret); return ret; } srs_verbose("check c0 success, required plain text."); - // try complex handshake - if (complex_hs) { - ret = complex_hs->handshake_with_client(skt, c0c1 + 1); - if (ret == ERROR_SUCCESS) { - srs_trace("complex handshake success."); - return ret; - } - if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { - srs_error("complex handshake failed. ret=%d", ret); - return ret; - } - srs_info("rollback complex to simple handshake. ret=%d", ret); + if ((ret = hs_bytes->create_s0s1s2()) != ERROR_SUCCESS) { + return ret; } - char* s0s1s2 = new char[3073]; - srs_random_generate(s0s1s2, 3073); - SrsAutoFree(char, s0s1s2, true); // plain text required. - s0s1s2[0] = 0x03; - if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { + hs_bytes->s0s1s2[0] = 0x03; + if ((ret = io->write(hs_bytes->s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret); return ret; } srs_verbose("simple handshake send s0s1s2 success."); - char* c2 = new char[1536]; - SrsAutoFree(char, c2, true); - if ((ret = skt->read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { - srs_warn("simple handshake read c2 failed. ret=%d", ret); + if ((ret = hs_bytes->read_c2(io)) != ERROR_SUCCESS) { return ret; } - srs_verbose("simple handshake read c2 success."); - srs_trace("simple handshake success."); + srs_trace("simple handshake with client success."); return ret; } -int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs) +int SrsSimpleHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io) { int ret = ERROR_SUCCESS; - // try complex handshake - if (complex_hs) { - ret = complex_hs->handshake_with_server(skt); - if (ret == ERROR_SUCCESS) { - srs_trace("complex handshake success."); - return ret; - } - if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { - srs_error("complex handshake failed. ret=%d", ret); - return ret; - } - srs_info("rollback complex to simple handshake. ret=%d", ret); - } - - // simple handshake ssize_t nsize; - char* c0c1 = new char[1537]; - SrsAutoFree(char, c0c1, true); - - srs_random_generate(c0c1, 1537); + // simple handshake + if ((ret = hs_bytes->create_c0c1()) != ERROR_SUCCESS) { + return ret; + } // plain text required. - c0c1[0] = 0x03; + hs_bytes->c0c1[0] = 0x03; - if ((ret = skt->write(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { + if ((ret = io->write(hs_bytes->c0c1, 1537, &nsize)) != ERROR_SUCCESS) { srs_warn("write c0c1 failed. ret=%d", ret); return ret; } srs_verbose("write c0c1 success."); - char* s0s1s2 = new char[3073]; - SrsAutoFree(char, s0s1s2, true); - if ((ret = skt->read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { - srs_warn("simple handshake recv s0s1s2 failed. ret=%d", ret); + if ((ret = hs_bytes->read_s0s1s2(io)) != ERROR_SUCCESS) { return ret; } - srs_verbose("simple handshake recv s0s1s2 success."); // plain text required. - if (s0s1s2[0] != 0x03) { + if (hs_bytes->s0s1s2[0] != 0x03) { ret = ERROR_RTMP_HANDSHAKE; srs_warn("handshake failed, plain text required. ret=%d", ret); return ret; } - char* c2 = new char[1536]; - SrsAutoFree(char, c2, true); - srs_random_generate(c2, 1536); - if ((ret = skt->write(c2, 1536, &nsize)) != ERROR_SUCCESS) { + if ((ret = hs_bytes->create_c2()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = io->write(hs_bytes->c2, 1536, &nsize)) != ERROR_SUCCESS) { srs_warn("simple handshake write c2 failed. ret=%d", ret); return ret; } srs_verbose("simple handshake write c2 success."); - srs_trace("simple handshake success."); + srs_trace("simple handshake with server success."); return ret; } @@ -1050,36 +1054,33 @@ SrsComplexHandshake::~SrsComplexHandshake() } #ifndef SRS_SSL -int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* /*skt*/, char* /*_c1*/) +int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* /*hs_bytes*/, ISrsProtocolReaderWriter* /*io*/) { srs_trace("directly use simple handshake for ssl disabled."); return ERROR_RTMP_TRY_SIMPLE_HS; } #else -int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, char* _c1) +int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io) { int ret = ERROR_SUCCESS; ssize_t nsize; - static bool _random_initialized = false; - if (!_random_initialized) { - srand(0); - _random_initialized = true; - srs_trace("srand initialized the random."); + if ((ret = hs_bytes->read_c0c1(io)) != ERROR_SUCCESS) { + return ret; } // decode c1 c1s1 c1; // try schema0. - if ((ret = c1.c1_parse(_c1, srs_schema0)) != ERROR_SUCCESS) { + if ((ret = c1.c1_parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) { srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); return ret; } // try schema1 bool is_valid = false; if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { - if ((ret = c1.c1_parse(_c1, srs_schema1)) != ERROR_SUCCESS) { + if ((ret = c1.c1_parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) { srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); return ret; } @@ -1102,10 +1103,10 @@ int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, ch // verify s1 if ((ret = s1.s1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { ret = ERROR_RTMP_TRY_SIMPLE_HS; - srs_info("valid s1 failed, try simple handshake. ret=%d", ret); + srs_info("verify s1 failed, try simple handshake. ret=%d", ret); return ret; } - srs_verbose("verify s1 from c1 success."); + srs_verbose("verify s1 success."); c2s2 s2; if ((ret = s2.s2_create(&c1)) != ERROR_SUCCESS) { @@ -1113,40 +1114,56 @@ int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, ch return ret; } srs_verbose("create s2 from c1 success."); + // verify s2 + if ((ret = s2.s2_validate(&c1, is_valid)) != ERROR_SUCCESS || !is_valid) { + ret = ERROR_RTMP_TRY_SIMPLE_HS; + srs_info("verify s2 failed, try simple handshake. ret=%d", ret); + return ret; + } + srs_verbose("verify s2 success."); // sendout s0s1s2 - char* s0s1s2 = new char[3073]; - SrsAutoFree(char, s0s1s2, true); + if ((ret = hs_bytes->create_s0s1s2()) != ERROR_SUCCESS) { + return ret; + } // plain text required. - s0s1s2[0] = 0x03; - s1.dump(s0s1s2 + 1); - s2.dump(s0s1s2 + 1537); - if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { + hs_bytes->s0s1s2[0] = 0x03; + s1.dump(hs_bytes->s0s1s2 + 1); + s2.dump(hs_bytes->s0s1s2 + 1537); + if ((ret = io->write(hs_bytes->s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { srs_warn("complex handshake send s0s1s2 failed. ret=%d", ret); return ret; } srs_verbose("complex handshake send s0s1s2 success."); // recv c2 - char* c2 = new char[1536]; - SrsAutoFree(char, c2, true); - if ((ret = skt->read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { - srs_warn("complex handshake read c2 failed. ret=%d", ret); + if ((ret = hs_bytes->read_c2(io)) != ERROR_SUCCESS) { return ret; } + c2s2 c2; + c2.parse(hs_bytes->c2); srs_verbose("complex handshake read c2 success."); + // verify c2 + if ((ret = c2.c2_validate(&s1, is_valid)) != ERROR_SUCCESS || !is_valid) { + ret = ERROR_RTMP_HANDSHAKE; + srs_trace("verify c2 failed. ret=%d", ret); + return ret; + } + srs_verbose("verify c2 success."); + + srs_trace("comple handshake with client success"); return ret; } #endif #ifndef SRS_SSL -int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/) +int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* /*hs_bytes*/, ISrsProtocolReaderWriter* /*io*/) { return ERROR_RTMP_TRY_SIMPLE_HS; } #else -int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/) +int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* /*hs_bytes*/, ISrsProtocolReaderWriter* /*io*/) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/rtmp/srs_protocol_handshake.hpp b/trunk/src/rtmp/srs_protocol_handshake.hpp index d38bc34e1..6bdcabcee 100644 --- a/trunk/src/rtmp/srs_protocol_handshake.hpp +++ b/trunk/src/rtmp/srs_protocol_handshake.hpp @@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class ISrsProtocolReaderWriter; class SrsComplexHandshake; +class SrsHandshakeBytes; /** * try complex handshake, if failed, fallback to simple handshake. @@ -44,12 +45,9 @@ public: public: /** * simple handshake. - * @param complex_hs, try complex handshake first, - * if NULL, use simple handshake. - * if failed, rollback to simple handshake. */ - virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); - virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); + virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io); + virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io); }; /** @@ -65,15 +63,13 @@ public: public: /** * complex hanshake. - * @_c1, size of c1 must be 1536. - * @remark, user must free the c1. * @return user must: * continue connect app if success, * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, * otherwise, disconnect */ - virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1); - virtual int handshake_with_server(ISrsProtocolReaderWriter* io); + virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io); + virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io); }; namespace srs @@ -241,6 +237,10 @@ namespace srs * copy to bytes. */ virtual void dump(char* _c2s2); + /** + * parse the c2s2 + */ + virtual void parse(char* _c2s2); /** * create c2. @@ -252,6 +252,11 @@ namespace srs */ virtual int c2_create(c1s1* s1); + /** + * validate the c2 from client. + */ + virtual int c2_validate(c1s1* s1, bool& is_valid); + /** * create s2. * random fill c2s2 1536 bytes @@ -261,6 +266,11 @@ namespace srs * s2-digest-data = HMACsha256(s2-random-data, temp-key, 32) */ virtual int s2_create(c1s1* c1); + + /** + * validate the s2 from server. + */ + virtual int s2_validate(c1s1* c1, bool& is_valid); }; /** diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp index 3d199708a..e87183abe 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp @@ -187,15 +187,131 @@ string srs_client_type_string(SrsClientType type) return "Unknown"; } +SrsHandshakeBytes::SrsHandshakeBytes() +{ + c0c1 = s0s1s2 = c2 = NULL; +} + +SrsHandshakeBytes::~SrsHandshakeBytes() +{ + srs_freepa(c0c1); + srs_freepa(s0s1s2); + srs_freepa(c2); +} + +int SrsHandshakeBytes::read_c0c1(ISrsProtocolReaderWriter* io) +{ + int ret = ERROR_SUCCESS; + + if (c0c1) { + return ret; + } + + ssize_t nsize; + + c0c1 = new char[1537]; + if ((ret = io->read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { + srs_warn("read c0c1 failed. ret=%d", ret); + return ret; + } + srs_verbose("read c0c1 success."); + + return ret; +} + +int SrsHandshakeBytes::read_s0s1s2(ISrsProtocolReaderWriter* io) +{ + int ret = ERROR_SUCCESS; + + if (s0s1s2) { + return ret; + } + + ssize_t nsize; + + c0c1 = new char[3073]; + if ((ret = io->read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { + srs_warn("read s0s1s2 failed. ret=%d", ret); + return ret; + } + srs_verbose("read s0s1s2 success."); + + return ret; +} + +int SrsHandshakeBytes::read_c2(ISrsProtocolReaderWriter* io) +{ + int ret = ERROR_SUCCESS; + + if (c2) { + return ret; + } + + ssize_t nsize; + + c2 = new char[1536]; + if ((ret = io->read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { + srs_warn("read c2 failed. ret=%d", ret); + return ret; + } + srs_verbose("read c2 success."); + + return ret; +} + +int SrsHandshakeBytes::create_c0c1() +{ + int ret = ERROR_SUCCESS; + + if (c0c1) { + return ret; + } + + c0c1 = new char[1537]; + srs_random_generate(c0c1, 1537); + + return ret; +} + +int SrsHandshakeBytes::create_s0s1s2() +{ + int ret = ERROR_SUCCESS; + + if (s0s1s2) { + return ret; + } + + s0s1s2 = new char[3073]; + srs_random_generate(s0s1s2, 3073); + + return ret; +} + +int SrsHandshakeBytes::create_c2() +{ + int ret = ERROR_SUCCESS; + + if (c2) { + return ret; + } + + c2 = new char[1536]; + srs_random_generate(c2, 1536); + + return ret; +} + SrsRtmpClient::SrsRtmpClient(ISrsProtocolReaderWriter* skt) { io = skt; protocol = new SrsProtocol(skt); + hs_bytes = new SrsHandshakeBytes(); } SrsRtmpClient::~SrsRtmpClient() { srs_freep(protocol); + srs_freep(hs_bytes); } void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) @@ -242,12 +358,21 @@ int SrsRtmpClient::handshake() { int ret = ERROR_SUCCESS; + srs_assert(hs_bytes); + SrsComplexHandshake complex_hs; - SrsSimpleHandshake simple_hs; - if ((ret = simple_hs.handshake_with_server(io, &complex_hs)) != ERROR_SUCCESS) { + if ((ret = complex_hs.handshake_with_server(hs_bytes, io)) != ERROR_SUCCESS) { + if (ret == ERROR_RTMP_TRY_SIMPLE_HS) { + SrsSimpleHandshake simple_hs; + if ((ret = simple_hs.handshake_with_server(hs_bytes, io)) != ERROR_SUCCESS) { + return ret; + } + } return ret; } + srs_freep(hs_bytes); + return ret; } @@ -255,18 +380,32 @@ int SrsRtmpClient::simple_handshake() { int ret = ERROR_SUCCESS; + srs_assert(hs_bytes); + SrsSimpleHandshake simple_hs; - if ((ret = simple_hs.handshake_with_server(io, NULL)) != ERROR_SUCCESS) { + if ((ret = simple_hs.handshake_with_server(hs_bytes, io)) != ERROR_SUCCESS) { return ret; } + srs_freep(hs_bytes); + return ret; } int SrsRtmpClient::complex_handshake() { - // TODO: FIXME: only use complex handshake. - return handshake(); + int ret = ERROR_SUCCESS; + + srs_assert(hs_bytes); + + SrsComplexHandshake complex_hs; + if ((ret = complex_hs.handshake_with_server(hs_bytes, io)) != ERROR_SUCCESS) { + return ret; + } + + srs_freep(hs_bytes); + + return ret; } int SrsRtmpClient::connect_app(string app, string tc_url) @@ -537,11 +676,13 @@ SrsRtmpServer::SrsRtmpServer(ISrsProtocolReaderWriter* skt) { io = skt; protocol = new SrsProtocol(skt); + hs_bytes = new SrsHandshakeBytes(); } SrsRtmpServer::~SrsRtmpServer() { srs_freep(protocol); + srs_freep(hs_bytes); } SrsProtocol* SrsRtmpServer::get_protocol() @@ -603,12 +744,21 @@ int SrsRtmpServer::handshake() { int ret = ERROR_SUCCESS; + srs_assert(hs_bytes); + SrsComplexHandshake complex_hs; - SrsSimpleHandshake simple_hs; - if ((ret = simple_hs.handshake_with_client(io, &complex_hs)) != ERROR_SUCCESS) { + if ((ret = complex_hs.handshake_with_client(hs_bytes, io)) != ERROR_SUCCESS) { + if (ret == ERROR_RTMP_TRY_SIMPLE_HS) { + SrsSimpleHandshake simple_hs; + if ((ret = simple_hs.handshake_with_client(hs_bytes, io)) != ERROR_SUCCESS) { + return ret; + } + } return ret; } + srs_freep(hs_bytes); + return ret; } diff --git a/trunk/src/rtmp/srs_protocol_rtmp.hpp b/trunk/src/rtmp/srs_protocol_rtmp.hpp index b863d3599..61c6026c6 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.hpp @@ -108,11 +108,38 @@ enum SrsClientType }; std::string srs_client_type_string(SrsClientType type); +/** +* store the handshake bytes, +* for smart switch between complex and simple handshake. +*/ +class SrsHandshakeBytes +{ +public: + // [1+1536] + char* c0c1; + // [1+1536+1536] + char* s0s1s2; + // [1536] + char* c2; +public: + SrsHandshakeBytes(); + virtual ~SrsHandshakeBytes(); +public: + virtual int read_c0c1(ISrsProtocolReaderWriter* io); + virtual int read_s0s1s2(ISrsProtocolReaderWriter* io); + virtual int read_c2(ISrsProtocolReaderWriter* io); + virtual int create_c0c1(); + virtual int create_s0s1s2(); + virtual int create_c2(); +}; + /** * implements the client role protocol. */ class SrsRtmpClient { +private: + SrsHandshakeBytes* hs_bytes; protected: SrsProtocol* protocol; ISrsProtocolReaderWriter* io; @@ -155,6 +182,7 @@ public: class SrsRtmpServer { private: + SrsHandshakeBytes* hs_bytes; SrsProtocol* protocol; ISrsProtocolReaderWriter* io; public: diff --git a/trunk/src/rtmp/srs_protocol_utility.cpp b/trunk/src/rtmp/srs_protocol_utility.cpp index b25d9e0aa..6ff8ae5ea 100644 --- a/trunk/src/rtmp/srs_protocol_utility.cpp +++ b/trunk/src/rtmp/srs_protocol_utility.cpp @@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + +#include + void srs_vhost_resolve(std::string& vhost, std::string& app) { app = srs_replace(app, "...", "?"); @@ -46,3 +50,23 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) } } } + +void srs_random_generate(char* bytes, int size) +{ + static bool _random_initialized = false; + if (!_random_initialized) { + srand(0); + _random_initialized = true; + srs_trace("srand initialized the random."); + } + + static char cdata[] = { + 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, 0x31, 0x32, 0x36, + 0x2e, 0x63, 0x6f, 0x6d + }; + for (int i = 0; i < size; i++) { + bytes[i] = cdata[rand() % (sizeof(cdata) - 1)]; + } +} diff --git a/trunk/src/rtmp/srs_protocol_utility.hpp b/trunk/src/rtmp/srs_protocol_utility.hpp index 10aaf246d..6ed126b76 100644 --- a/trunk/src/rtmp/srs_protocol_utility.hpp +++ b/trunk/src/rtmp/srs_protocol_utility.hpp @@ -40,4 +40,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // app...vhost...request_vhost extern void srs_vhost_resolve(std::string& vhost, std::string& app); +extern void srs_random_generate(char* bytes, int size); + #endif