mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
change to 0.9.19, verify the s1/s2/c2, refine the handshake.
This commit is contained in:
parent
152d3539d8
commit
841f0f8899
8 changed files with 349 additions and 118 deletions
|
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue