winlin

change to 0.9.19, verify the s1/s2/c2, refine the handshake.

... ... @@ -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"
... ...
... ... @@ -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<className> _auto_free_##instance(&instance, is_array)
__SrsAutoFree<className> _auto_free_##instance((className**)&instance, is_array)
template<class T>
class __SrsAutoFree
... ...
... ... @@ -24,28 +24,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_protocol_handshake.hpp>
#include <time.h>
#include <stdlib.h>
#include <srs_core_autofree.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
#include <srs_protocol_io.hpp>
#include <srs_protocol_utility.hpp>
#include <srs_protocol_rtmp.hpp>
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;
... ...
... ... @@ -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.
... ... @@ -253,6 +253,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);
};
/**
... ...
... ... @@ -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;
}
... ...
... ... @@ -109,10 +109,37 @@ 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:
... ...
... ... @@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_protocol_utility.hpp>
#include <stdlib.h>
#include <srs_kernel_log.hpp>
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)];
}
}
... ...
... ... @@ -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
... ...