mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Merge branch 'master' of github.com:winlinvip/simple-rtmp-server
This commit is contained in:
commit
c63ad48893
11 changed files with 1170 additions and 1020 deletions
|
@ -167,6 +167,8 @@ See also: [Performance Test Guide](https://github.com/winlinvip/simple-rtmp-serv
|
||||||
* nginx v1.5.0: 139524 lines <br/>
|
* nginx v1.5.0: 139524 lines <br/>
|
||||||
|
|
||||||
### History
|
### History
|
||||||
|
* v1.0, 2014-03-19, add vn/an for FFMPEG to drop video/audio for radio stream.
|
||||||
|
* v1.0, 2014-03-19, refine handshake, client support coplex handshake, add utest.
|
||||||
* v1.0, 2014-03-16, support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.
|
* v1.0, 2014-03-16, support ARM([debian armhf, v7cpu](https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm)) with rtmp/ssl/hls/librtmp.
|
||||||
* v1.0, 2014-03-12, finish utest for amf0 codec.
|
* v1.0, 2014-03-12, finish utest for amf0 codec.
|
||||||
* v1.0, 2014-03-06, add gperftools for mem leak detect, mem/cpu profile.
|
* v1.0, 2014-03-06, add gperftools for mem leak detect, mem/cpu profile.
|
||||||
|
|
21
trunk/conf/full.conf
Normal file → Executable file
21
trunk/conf/full.conf
Normal file → Executable file
|
@ -291,6 +291,25 @@ vhost audio.transcode.vhost.com {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# disable video, transcode/copy audio.
|
||||||
|
# for example, publish pure audio stream.
|
||||||
|
vhost vn.transcode.vhost.com {
|
||||||
|
transcode {
|
||||||
|
enabled on;
|
||||||
|
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
|
||||||
|
engine vn {
|
||||||
|
enabled on;
|
||||||
|
vcodec vn;
|
||||||
|
acodec libaacplus;
|
||||||
|
abitrate 45;
|
||||||
|
asample_rate 44100;
|
||||||
|
achannels 2;
|
||||||
|
aparams {
|
||||||
|
}
|
||||||
|
output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
# ffmpeg-copy(forward implements by ffmpeg).
|
# ffmpeg-copy(forward implements by ffmpeg).
|
||||||
# copy the video and audio to a new stream.
|
# copy the video and audio to a new stream.
|
||||||
vhost copy.transcode.vhost.com {
|
vhost copy.transcode.vhost.com {
|
||||||
|
@ -333,6 +352,7 @@ vhost all.transcode.vhost.com {
|
||||||
# video encoder name. can be:
|
# video encoder name. can be:
|
||||||
# libx264: use h.264(libx264) video encoder.
|
# libx264: use h.264(libx264) video encoder.
|
||||||
# copy: donot encoder the video stream, copy it.
|
# copy: donot encoder the video stream, copy it.
|
||||||
|
# vn: disable video output.
|
||||||
vcodec libx264;
|
vcodec libx264;
|
||||||
# video bitrate, in kbps
|
# video bitrate, in kbps
|
||||||
vbitrate 1500;
|
vbitrate 1500;
|
||||||
|
@ -364,6 +384,7 @@ vhost all.transcode.vhost.com {
|
||||||
# audio encoder name. can be:
|
# audio encoder name. can be:
|
||||||
# libaacplus: use aac(libaacplus) audio encoder.
|
# libaacplus: use aac(libaacplus) audio encoder.
|
||||||
# copy: donot encoder the audio stream, copy it.
|
# copy: donot encoder the audio stream, copy it.
|
||||||
|
# an: disable audio output.
|
||||||
acodec libaacplus;
|
acodec libaacplus;
|
||||||
# audio bitrate, in kbps. [16, 72] for libaacplus.
|
# audio bitrate, in kbps. [16, 72] for libaacplus.
|
||||||
abitrate 70;
|
abitrate 70;
|
||||||
|
|
0
trunk/conf/srs.conf
Normal file → Executable file
0
trunk/conf/srs.conf
Normal file → Executable file
|
@ -42,6 +42,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#ifdef SRS_FFMPEG
|
#ifdef SRS_FFMPEG
|
||||||
|
|
||||||
#define SRS_ENCODER_COPY "copy"
|
#define SRS_ENCODER_COPY "copy"
|
||||||
|
#define SRS_ENCODER_NO_VIDEO "vn"
|
||||||
|
#define SRS_ENCODER_NO_AUDIO "an"
|
||||||
#define SRS_ENCODER_VCODEC "libx264"
|
#define SRS_ENCODER_VCODEC "libx264"
|
||||||
#define SRS_ENCODER_ACODEC "libaacplus"
|
#define SRS_ENCODER_ACODEC "libaacplus"
|
||||||
|
|
||||||
|
@ -138,7 +140,13 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
|
||||||
}
|
}
|
||||||
_transcoded_url.push_back(output);
|
_transcoded_url.push_back(output);
|
||||||
|
|
||||||
if (vcodec != SRS_ENCODER_COPY) {
|
if (vcodec == SRS_ENCODER_NO_VIDEO && acodec == SRS_ENCODER_NO_AUDIO) {
|
||||||
|
ret = ERROR_ENCODER_VCODEC;
|
||||||
|
srs_warn("video and audio disabled. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vcodec != SRS_ENCODER_COPY && vcodec != SRS_ENCODER_NO_VIDEO) {
|
||||||
if (vcodec != SRS_ENCODER_VCODEC) {
|
if (vcodec != SRS_ENCODER_VCODEC) {
|
||||||
ret = ERROR_ENCODER_VCODEC;
|
ret = ERROR_ENCODER_VCODEC;
|
||||||
srs_error("invalid vcodec, must be %s, actual %s, ret=%d",
|
srs_error("invalid vcodec, must be %s, actual %s, ret=%d",
|
||||||
|
@ -182,7 +190,7 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acodec != SRS_ENCODER_COPY) {
|
if (acodec != SRS_ENCODER_COPY && acodec != SRS_ENCODER_NO_AUDIO) {
|
||||||
if (acodec != SRS_ENCODER_ACODEC) {
|
if (acodec != SRS_ENCODER_ACODEC) {
|
||||||
ret = ERROR_ENCODER_ACODEC;
|
ret = ERROR_ENCODER_ACODEC;
|
||||||
srs_error("invalid acodec, must be %s, actual %s, ret=%d",
|
srs_error("invalid acodec, must be %s, actual %s, ret=%d",
|
||||||
|
@ -254,11 +262,15 @@ int SrsFFMPEG::start()
|
||||||
}
|
}
|
||||||
|
|
||||||
// video specified.
|
// video specified.
|
||||||
|
if (vcodec != SRS_ENCODER_NO_VIDEO) {
|
||||||
params.push_back("-vcodec");
|
params.push_back("-vcodec");
|
||||||
params.push_back(vcodec);
|
params.push_back(vcodec);
|
||||||
|
} else {
|
||||||
|
params.push_back("-vn");
|
||||||
|
}
|
||||||
|
|
||||||
// the codec params is disabled when copy
|
// the codec params is disabled when copy
|
||||||
if (vcodec != SRS_ENCODER_COPY) {
|
if (vcodec != SRS_ENCODER_COPY && vcodec != SRS_ENCODER_NO_VIDEO) {
|
||||||
params.push_back("-b:v");
|
params.push_back("-b:v");
|
||||||
snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000);
|
snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000);
|
||||||
params.push_back(tmp);
|
params.push_back(tmp);
|
||||||
|
@ -299,11 +311,15 @@ int SrsFFMPEG::start()
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio specified.
|
// audio specified.
|
||||||
|
if (acodec != SRS_ENCODER_NO_AUDIO) {
|
||||||
params.push_back("-acodec");
|
params.push_back("-acodec");
|
||||||
params.push_back(acodec);
|
params.push_back(acodec);
|
||||||
|
} else {
|
||||||
|
params.push_back("-an");
|
||||||
|
}
|
||||||
|
|
||||||
// the codec params is disabled when copy
|
// the codec params is disabled when copy
|
||||||
if (acodec != SRS_ENCODER_COPY) {
|
if (acodec != SRS_ENCODER_COPY && acodec != SRS_ENCODER_NO_AUDIO) {
|
||||||
params.push_back("-b:a");
|
params.push_back("-b:a");
|
||||||
snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000);
|
snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000);
|
||||||
params.push_back(tmp);
|
params.push_back(tmp);
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "0"
|
#define VERSION_MAJOR "0"
|
||||||
#define VERSION_MINOR "9"
|
#define VERSION_MINOR "9"
|
||||||
#define VERSION_REVISION "21"
|
#define VERSION_REVISION "22"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "srs"
|
#define RTMP_SIG_SRS_KEY "srs"
|
||||||
|
|
|
@ -32,12 +32,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_protocol_utility.hpp>
|
#include <srs_protocol_utility.hpp>
|
||||||
#include <srs_protocol_rtmp.hpp>
|
#include <srs_protocol_rtmp.hpp>
|
||||||
|
|
||||||
using namespace srs;
|
|
||||||
|
|
||||||
#ifdef SRS_SSL
|
#ifdef SRS_SSL
|
||||||
|
|
||||||
// 68bytes FMS key which is used to sign the sever packet.
|
using namespace srs;
|
||||||
u_int8_t srs::SrsGenuineFMSKey[] = {
|
|
||||||
|
// for openssl_HMACsha256
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
// for __openssl_generate_key
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
|
||||||
|
namespace srs
|
||||||
|
{
|
||||||
|
// 68bytes FMS key which is used to sign the sever packet.
|
||||||
|
u_int8_t SrsGenuineFMSKey[] = {
|
||||||
0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,
|
0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,
|
||||||
0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,
|
0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,
|
||||||
0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,
|
0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,
|
||||||
|
@ -47,10 +55,10 @@ u_int8_t srs::SrsGenuineFMSKey[] = {
|
||||||
0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,
|
0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,
|
||||||
0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
|
0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
|
||||||
0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
|
0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
|
||||||
}; // 68
|
}; // 68
|
||||||
|
|
||||||
// 62bytes FP key which is used to sign the client packet.
|
// 62bytes FP key which is used to sign the client packet.
|
||||||
u_int8_t srs::SrsGenuineFPKey[] = {
|
u_int8_t SrsGenuineFPKey[] = {
|
||||||
0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,
|
0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,
|
||||||
0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,
|
0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,
|
||||||
0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,
|
0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,
|
||||||
|
@ -59,12 +67,10 @@ u_int8_t srs::SrsGenuineFPKey[] = {
|
||||||
0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,
|
0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,
|
||||||
0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
|
0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
|
||||||
0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
|
0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
|
||||||
}; // 62
|
}; // 62
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest)
|
||||||
#include <openssl/hmac.h>
|
{
|
||||||
int srs::openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest)
|
|
||||||
{
|
|
||||||
HMAC_CTX ctx;
|
HMAC_CTX ctx;
|
||||||
|
|
||||||
HMAC_CTX_init(&ctx);
|
HMAC_CTX_init(&ctx);
|
||||||
|
@ -81,20 +87,19 @@ int srs::openssl_HMACsha256(const void* data, int data_size, const void* key, in
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <openssl/dh.h>
|
#define RFC2409_PRIME_1024 \
|
||||||
#define RFC2409_PRIME_1024 \
|
|
||||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
|
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
|
||||||
"FFFFFFFFFFFFFFFF"
|
"FFFFFFFFFFFFFFFF"
|
||||||
int __openssl_generate_key(
|
int __openssl_generate_key(
|
||||||
u_int8_t*& _private_key, u_int8_t*& _public_key, int32_t& size,
|
u_int8_t* _private_key, u_int8_t* _public_key, int32_t& size,
|
||||||
DH*& pdh, int32_t& bits_count, u_int8_t*& shared_key, int32_t& shared_key_length, BIGNUM*& peer_public_key
|
DH*& pdh, int32_t& bits_count, u_int8_t*& shared_key, int32_t& shared_key_length, BIGNUM*& peer_public_key
|
||||||
){
|
){
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
//1. Create the DH
|
//1. Create the DH
|
||||||
|
@ -182,9 +187,9 @@ int __openssl_generate_key(
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
|
int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
|
@ -195,7 +200,7 @@ int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
|
||||||
BIGNUM* peer_public_key = NULL;
|
BIGNUM* peer_public_key = NULL;
|
||||||
|
|
||||||
ret = __openssl_generate_key(
|
ret = __openssl_generate_key(
|
||||||
(u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size,
|
(u_int8_t*)_private_key, (u_int8_t*)_public_key, size,
|
||||||
pdh, bits_count, shared_key, shared_key_length, peer_public_key
|
pdh, bits_count, shared_key, shared_key_length, peer_public_key
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -223,12 +228,12 @@ int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calc the offset of key,
|
// calc the offset of key,
|
||||||
// the key->offset cannot be used as the offset of key.
|
// the key->offset cannot be used as the offset of key.
|
||||||
int srs_key_block_get_offset(key_block* key)
|
int srs_key_block_get_offset(key_block* key)
|
||||||
{
|
{
|
||||||
int max_offset_size = 764 - 128 - 4;
|
int max_offset_size = 764 - 128 - 4;
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
@ -239,11 +244,12 @@ int srs_key_block_get_offset(key_block* key)
|
||||||
offset += *pp++;
|
offset += *pp++;
|
||||||
|
|
||||||
return offset % max_offset_size;
|
return offset % max_offset_size;
|
||||||
}
|
}
|
||||||
// create new key block data.
|
|
||||||
// if created, user must free it by srs_key_block_free
|
// create new key block data.
|
||||||
void srs_key_block_init(key_block* key)
|
// if created, user must free it by srs_key_block_free
|
||||||
{
|
void srs_key_block_init(key_block* key)
|
||||||
|
{
|
||||||
key->offset = (int32_t)rand();
|
key->offset = (int32_t)rand();
|
||||||
key->random0 = NULL;
|
key->random0 = NULL;
|
||||||
key->random1 = NULL;
|
key->random1 = NULL;
|
||||||
|
@ -264,12 +270,13 @@ void srs_key_block_init(key_block* key)
|
||||||
key->random1 = new char[key->random1_size];
|
key->random1 = new char[key->random1_size];
|
||||||
srs_random_generate(key->random1, key->random1_size);
|
srs_random_generate(key->random1, key->random1_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// parse key block from c1s1.
|
|
||||||
// if created, user must free it by srs_key_block_free
|
// parse key block from c1s1.
|
||||||
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
|
// if created, user must free it by srs_key_block_free
|
||||||
int srs_key_block_parse(key_block* key, char* c1s1_key_bytes)
|
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
|
||||||
{
|
int srs_key_block_parse(key_block* key, char* c1s1_key_bytes)
|
||||||
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
char* pp = c1s1_key_bytes + 764;
|
char* pp = c1s1_key_bytes + 764;
|
||||||
|
@ -301,23 +308,24 @@ int srs_key_block_parse(key_block* key, char* c1s1_key_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// free the block data create by
|
|
||||||
// srs_key_block_init or srs_key_block_parse
|
// free the block data create by
|
||||||
void srs_key_block_free(key_block* key)
|
// srs_key_block_init or srs_key_block_parse
|
||||||
{
|
void srs_key_block_free(key_block* key)
|
||||||
|
{
|
||||||
if (key->random0) {
|
if (key->random0) {
|
||||||
srs_freepa(key->random0);
|
srs_freepa(key->random0);
|
||||||
}
|
}
|
||||||
if (key->random1) {
|
if (key->random1) {
|
||||||
srs_freepa(key->random1);
|
srs_freepa(key->random1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calc the offset of digest,
|
// calc the offset of digest,
|
||||||
// the key->offset cannot be used as the offset of digest.
|
// the key->offset cannot be used as the offset of digest.
|
||||||
int srs_digest_block_get_offset(digest_block* digest)
|
int srs_digest_block_get_offset(digest_block* digest)
|
||||||
{
|
{
|
||||||
int max_offset_size = 764 - 32 - 4;
|
int max_offset_size = 764 - 32 - 4;
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
@ -328,11 +336,12 @@ int srs_digest_block_get_offset(digest_block* digest)
|
||||||
offset += *pp++;
|
offset += *pp++;
|
||||||
|
|
||||||
return offset % max_offset_size;
|
return offset % max_offset_size;
|
||||||
}
|
}
|
||||||
// create new digest block data.
|
|
||||||
// if created, user must free it by srs_digest_block_free
|
// create new digest block data.
|
||||||
void srs_digest_block_init(digest_block* digest)
|
// if created, user must free it by srs_digest_block_free
|
||||||
{
|
void srs_digest_block_init(digest_block* digest)
|
||||||
|
{
|
||||||
digest->offset = (int32_t)rand();
|
digest->offset = (int32_t)rand();
|
||||||
digest->random0 = NULL;
|
digest->random0 = NULL;
|
||||||
digest->random1 = NULL;
|
digest->random1 = NULL;
|
||||||
|
@ -353,12 +362,13 @@ void srs_digest_block_init(digest_block* digest)
|
||||||
digest->random1 = new char[digest->random1_size];
|
digest->random1 = new char[digest->random1_size];
|
||||||
srs_random_generate(digest->random1, digest->random1_size);
|
srs_random_generate(digest->random1, digest->random1_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// parse digest block from c1s1.
|
|
||||||
// if created, user must free it by srs_digest_block_free
|
// parse digest block from c1s1.
|
||||||
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
|
// if created, user must free it by srs_digest_block_free
|
||||||
int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes)
|
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
|
||||||
{
|
int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes)
|
||||||
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
char* pp = c1s1_digest_bytes;
|
char* pp = c1s1_digest_bytes;
|
||||||
|
@ -389,33 +399,34 @@ int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// free the block data create by
|
|
||||||
// srs_digest_block_init or srs_digest_block_parse
|
// free the block data create by
|
||||||
void srs_digest_block_free(digest_block* digest)
|
// srs_digest_block_init or srs_digest_block_parse
|
||||||
{
|
void srs_digest_block_free(digest_block* digest)
|
||||||
|
{
|
||||||
if (digest->random0) {
|
if (digest->random0) {
|
||||||
srs_freepa(digest->random0);
|
srs_freepa(digest->random0);
|
||||||
}
|
}
|
||||||
if (digest->random1) {
|
if (digest->random1) {
|
||||||
srs_freepa(digest->random1);
|
srs_freepa(digest->random1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __srs_time_copy_to(char*& pp, int32_t time)
|
void __srs_time_copy_to(char*& pp, int32_t time)
|
||||||
{
|
{
|
||||||
// 4bytes time
|
// 4bytes time
|
||||||
*(int32_t*)pp = time;
|
*(int32_t*)pp = time;
|
||||||
pp += 4;
|
pp += 4;
|
||||||
}
|
}
|
||||||
void __srs_version_copy_to(char*& pp, int32_t version)
|
void __srs_version_copy_to(char*& pp, int32_t version)
|
||||||
{
|
{
|
||||||
// 4bytes version
|
// 4bytes version
|
||||||
*(int32_t*)pp = version;
|
*(int32_t*)pp = version;
|
||||||
pp += 4;
|
pp += 4;
|
||||||
}
|
}
|
||||||
void __srs_key_copy_to(char*& pp, key_block* key)
|
void __srs_key_copy_to(char*& pp, key_block* key)
|
||||||
{
|
{
|
||||||
// 764bytes key block
|
// 764bytes key block
|
||||||
if (key->random0_size > 0) {
|
if (key->random0_size > 0) {
|
||||||
memcpy(pp, key->random0, key->random0_size);
|
memcpy(pp, key->random0, key->random0_size);
|
||||||
|
@ -432,9 +443,9 @@ void __srs_key_copy_to(char*& pp, key_block* key)
|
||||||
|
|
||||||
*(int32_t*)pp = key->offset;
|
*(int32_t*)pp = key->offset;
|
||||||
pp += 4;
|
pp += 4;
|
||||||
}
|
}
|
||||||
void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
|
void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
|
||||||
{
|
{
|
||||||
// 732bytes digest block without the 32bytes digest-data
|
// 732bytes digest block without the 32bytes digest-data
|
||||||
// nbytes digest block part1
|
// nbytes digest block part1
|
||||||
*(int32_t*)pp = digest->offset;
|
*(int32_t*)pp = digest->offset;
|
||||||
|
@ -456,14 +467,14 @@ void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
|
||||||
memcpy(pp, digest->random1, digest->random1_size);
|
memcpy(pp, digest->random1, digest->random1_size);
|
||||||
}
|
}
|
||||||
pp += digest->random1_size;
|
pp += digest->random1_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy whole c1s1 to bytes.
|
* copy whole c1s1 to bytes.
|
||||||
*/
|
*/
|
||||||
void srs_schema0_copy_to(char* bytes, bool with_digest,
|
void srs_schema0_copy_to(char* bytes, bool with_digest,
|
||||||
int32_t time, int32_t version, key_block* key, digest_block* digest)
|
int32_t time, int32_t version, key_block* key, digest_block* digest)
|
||||||
{
|
{
|
||||||
char* pp = bytes;
|
char* pp = bytes;
|
||||||
|
|
||||||
__srs_time_copy_to(pp, time);
|
__srs_time_copy_to(pp, time);
|
||||||
|
@ -476,10 +487,10 @@ void srs_schema0_copy_to(char* bytes, bool with_digest,
|
||||||
} else {
|
} else {
|
||||||
srs_assert(pp - bytes == 1536 - 32);
|
srs_assert(pp - bytes == 1536 - 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void srs_schema1_copy_to(char* bytes, bool with_digest,
|
void srs_schema1_copy_to(char* bytes, bool with_digest,
|
||||||
int32_t time, int32_t version, digest_block* digest, key_block* key)
|
int32_t time, int32_t version, digest_block* digest, key_block* key)
|
||||||
{
|
{
|
||||||
char* pp = bytes;
|
char* pp = bytes;
|
||||||
|
|
||||||
__srs_time_copy_to(pp, time);
|
__srs_time_copy_to(pp, time);
|
||||||
|
@ -492,46 +503,54 @@ void srs_schema1_copy_to(char* bytes, bool with_digest,
|
||||||
} else {
|
} else {
|
||||||
srs_assert(pp - bytes == 1536 - 32);
|
srs_assert(pp - bytes == 1536 - 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* c1s1 is splited by digest:
|
* c1s1 is splited by digest:
|
||||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||||
* digest-data: 32bytes
|
* digest-data: 32bytes
|
||||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||||
*/
|
*/
|
||||||
char* srs::srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest)
|
char* srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest)
|
||||||
{
|
{
|
||||||
char* bytes = new char[1536 -32];
|
char* bytes = new char[1536 -32];
|
||||||
|
|
||||||
srs_schema0_copy_to(bytes, false, time, version, key, digest);
|
srs_schema0_copy_to(bytes, false, time, version, key, digest);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* c1s1 is splited by digest:
|
* c1s1 is splited by digest:
|
||||||
* c1s1-part1: n bytes (time, version and digest-part1).
|
* c1s1-part1: n bytes (time, version and digest-part1).
|
||||||
* digest-data: 32bytes
|
* digest-data: 32bytes
|
||||||
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
|
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
|
||||||
*/
|
*/
|
||||||
char* srs::srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key)
|
char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key)
|
||||||
{
|
{
|
||||||
char* bytes = new char[1536 -32];
|
char* bytes = new char[1536 -32];
|
||||||
|
|
||||||
srs_schema1_copy_to(bytes, false, time, version, digest, key);
|
srs_schema1_copy_to(bytes, false, time, version, digest, key);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compare the memory in bytes.
|
* compare the memory in bytes.
|
||||||
*/
|
*/
|
||||||
bool srs::srs_bytes_equals(void* pa, void* pb, int size)
|
bool srs_bytes_equals(void* pa, void* pb, int size)
|
||||||
{
|
{
|
||||||
u_int8_t* a = (u_int8_t*)pa;
|
u_int8_t* a = (u_int8_t*)pa;
|
||||||
u_int8_t* b = (u_int8_t*)pb;
|
u_int8_t* b = (u_int8_t*)pb;
|
||||||
|
|
||||||
|
if (!a && !b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a || !b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < size; i++){
|
for(int i = 0; i < size; i++){
|
||||||
if(a[i] != b[i]){
|
if(a[i] != b[i]){
|
||||||
return false;
|
return false;
|
||||||
|
@ -539,32 +558,32 @@ bool srs::srs_bytes_equals(void* pa, void* pb, int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
c2s2::c2s2()
|
c2s2::c2s2()
|
||||||
{
|
{
|
||||||
srs_random_generate(random, 1504);
|
srs_random_generate(random, 1504);
|
||||||
srs_random_generate(digest, 32);
|
srs_random_generate(digest, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
c2s2::~c2s2()
|
c2s2::~c2s2()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void c2s2::dump(char* _c2s2)
|
void c2s2::dump(char* _c2s2)
|
||||||
{
|
{
|
||||||
memcpy(_c2s2, random, 1504);
|
memcpy(_c2s2, random, 1504);
|
||||||
memcpy(_c2s2 + 1504, digest, 32);
|
memcpy(_c2s2 + 1504, digest, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void c2s2::parse(char* _c2s2)
|
void c2s2::parse(char* _c2s2)
|
||||||
{
|
{
|
||||||
memcpy(random, _c2s2, 1504);
|
memcpy(random, _c2s2, 1504);
|
||||||
memcpy(digest, _c2s2 + 1504, 32);
|
memcpy(digest, _c2s2 + 1504, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
int c2s2::c2_create(c1s1* s1)
|
int c2s2::c2_create(c1s1* s1)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
char temp_key[OpensslHashSize];
|
char temp_key[OpensslHashSize];
|
||||||
|
@ -584,10 +603,10 @@ int c2s2::c2_create(c1s1* s1)
|
||||||
memcpy(digest, _digest, 32);
|
memcpy(digest, _digest, 32);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c2s2::c2_validate(c1s1* s1, bool& is_valid)
|
int c2s2::c2_validate(c1s1* s1, bool& is_valid)
|
||||||
{
|
{
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -608,10 +627,10 @@ int c2s2::c2_validate(c1s1* s1, bool& is_valid)
|
||||||
is_valid = srs_bytes_equals(digest, _digest, 32);
|
is_valid = srs_bytes_equals(digest, _digest, 32);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c2s2::s2_create(c1s1* c1)
|
int c2s2::s2_create(c1s1* c1)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
char temp_key[OpensslHashSize];
|
char temp_key[OpensslHashSize];
|
||||||
|
@ -631,10 +650,10 @@ int c2s2::s2_create(c1s1* c1)
|
||||||
memcpy(digest, _digest, 32);
|
memcpy(digest, _digest, 32);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c2s2::s2_validate(c1s1* c1, bool& is_valid)
|
int c2s2::s2_validate(c1s1* c1, bool& is_valid)
|
||||||
{
|
{
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -655,20 +674,20 @@ int c2s2::s2_validate(c1s1* c1, bool& is_valid)
|
||||||
is_valid = srs_bytes_equals(digest, _digest, 32);
|
is_valid = srs_bytes_equals(digest, _digest, 32);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: move to the right position.
|
// TODO: FIXME: move to the right position.
|
||||||
c1s1::c1s1()
|
c1s1::c1s1()
|
||||||
{
|
{
|
||||||
schema = srs_schema_invalid;
|
schema = srs_schema_invalid;
|
||||||
}
|
}
|
||||||
c1s1::~c1s1()
|
c1s1::~c1s1()
|
||||||
{
|
{
|
||||||
destroy_blocks();
|
destroy_blocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
char* c1s1::get_digest()
|
char* c1s1::get_digest()
|
||||||
{
|
{
|
||||||
srs_assert(schema != srs_schema_invalid);
|
srs_assert(schema != srs_schema_invalid);
|
||||||
|
|
||||||
if (schema == srs_schema0) {
|
if (schema == srs_schema0) {
|
||||||
|
@ -676,10 +695,10 @@ char* c1s1::get_digest()
|
||||||
} else {
|
} else {
|
||||||
return block0.digest.digest;
|
return block0.digest.digest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void c1s1::dump(char* _c1s1)
|
void c1s1::dump(char* _c1s1)
|
||||||
{
|
{
|
||||||
srs_assert(schema != srs_schema_invalid);
|
srs_assert(schema != srs_schema_invalid);
|
||||||
|
|
||||||
if (schema == srs_schema0) {
|
if (schema == srs_schema0) {
|
||||||
|
@ -687,10 +706,10 @@ void c1s1::dump(char* _c1s1)
|
||||||
} else {
|
} else {
|
||||||
srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key);
|
srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::parse(char* _c1s1, srs_schema_type _schema)
|
int c1s1::parse(char* _c1s1, srs_schema_type _schema)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (_schema == srs_schema_invalid) {
|
if (_schema == srs_schema_invalid) {
|
||||||
|
@ -733,10 +752,10 @@ int c1s1::parse(char* _c1s1, srs_schema_type _schema)
|
||||||
schema = _schema;
|
schema = _schema;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::c1_create(srs_schema_type _schema)
|
int c1s1::c1_create(srs_schema_type _schema)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (_schema == srs_schema_invalid) {
|
if (_schema == srs_schema_invalid) {
|
||||||
|
@ -777,10 +796,10 @@ int c1s1::c1_create(srs_schema_type _schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::c1_validate_digest(bool& is_valid)
|
int c1s1::c1_validate_digest(bool& is_valid)
|
||||||
{
|
{
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -801,10 +820,10 @@ int c1s1::c1_validate_digest(bool& is_valid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::s1_validate_digest(bool& is_valid)
|
int c1s1::s1_validate_digest(bool& is_valid)
|
||||||
{
|
{
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -825,10 +844,10 @@ int c1s1::s1_validate_digest(bool& is_valid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::s1_create(c1s1* c1)
|
int c1s1::s1_create(c1s1* c1)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (c1->schema == srs_schema_invalid) {
|
if (c1->schema == srs_schema_invalid) {
|
||||||
|
@ -882,10 +901,10 @@ int c1s1::s1_create(c1s1* c1)
|
||||||
srs_verbose("copy s1 key success.");
|
srs_verbose("copy s1 key success.");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::calc_s1_digest(char*& digest)
|
int c1s1::calc_s1_digest(char*& digest)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(schema == srs_schema0 || schema == srs_schema1);
|
srs_assert(schema == srs_schema0 || schema == srs_schema1);
|
||||||
|
@ -909,10 +928,10 @@ int c1s1::calc_s1_digest(char*& digest)
|
||||||
srs_verbose("digest calculated for s1");
|
srs_verbose("digest calculated for s1");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c1s1::calc_c1_digest(char*& digest)
|
int c1s1::calc_c1_digest(char*& digest)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(schema == srs_schema0 || schema == srs_schema1);
|
srs_assert(schema == srs_schema0 || schema == srs_schema1);
|
||||||
|
@ -936,10 +955,10 @@ int c1s1::calc_c1_digest(char*& digest)
|
||||||
srs_verbose("digest calculated for c1");
|
srs_verbose("digest calculated for c1");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void c1s1::destroy_blocks()
|
void c1s1::destroy_blocks()
|
||||||
{
|
{
|
||||||
if (schema == srs_schema_invalid) {
|
if (schema == srs_schema_invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -951,6 +970,7 @@ void c1s1::destroy_blocks()
|
||||||
srs_digest_block_free(&block0.digest);
|
srs_digest_block_free(&block0.digest);
|
||||||
srs_key_block_free(&block1.key);
|
srs_key_block_free(&block1.key);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1144,13 +1164,10 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
|
||||||
c2s2 c2;
|
c2s2 c2;
|
||||||
c2.parse(hs_bytes->c2);
|
c2.parse(hs_bytes->c2);
|
||||||
srs_verbose("complex handshake read c2 success.");
|
srs_verbose("complex handshake read c2 success.");
|
||||||
|
|
||||||
// verify c2
|
// verify c2
|
||||||
if ((ret = c2.c2_validate(&s1, is_valid)) != ERROR_SUCCESS || !is_valid) {
|
// never verify c2, for ffmpeg will failed.
|
||||||
ret = ERROR_RTMP_HANDSHAKE;
|
// it's ok for flash.
|
||||||
srs_trace("verify c2 failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
srs_verbose("verify c2 success.");
|
|
||||||
|
|
||||||
srs_trace("comple handshake with client success");
|
srs_trace("comple handshake with client success");
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,78 @@ namespace srs
|
||||||
int random1_size;
|
int random1_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// the digest key generate size.
|
||||||
|
#define OpensslHashSize 512
|
||||||
|
extern u_int8_t SrsGenuineFMSKey[];
|
||||||
|
extern u_int8_t SrsGenuineFPKey[];
|
||||||
|
int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest);
|
||||||
|
int openssl_generate_key(char* _private_key, char* _public_key, int32_t size);
|
||||||
|
|
||||||
|
// calc the offset of key,
|
||||||
|
// the key->offset cannot be used as the offset of key.
|
||||||
|
int srs_key_block_get_offset(key_block* key);
|
||||||
|
|
||||||
|
// create new key block data.
|
||||||
|
// if created, user must free it by srs_key_block_free
|
||||||
|
void srs_key_block_init(key_block* key);
|
||||||
|
|
||||||
|
// parse key block from c1s1.
|
||||||
|
// if created, user must free it by srs_key_block_free
|
||||||
|
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
|
||||||
|
int srs_key_block_parse(key_block* key, char* c1s1_key_bytes);
|
||||||
|
|
||||||
|
// free the block data create by
|
||||||
|
// srs_key_block_init or srs_key_block_parse
|
||||||
|
void srs_key_block_free(key_block* key);
|
||||||
|
|
||||||
|
// calc the offset of digest,
|
||||||
|
// the key->offset cannot be used as the offset of digest.
|
||||||
|
int srs_digest_block_get_offset(digest_block* digest);
|
||||||
|
|
||||||
|
// create new digest block data.
|
||||||
|
// if created, user must free it by srs_digest_block_free
|
||||||
|
void srs_digest_block_init(digest_block* digest);
|
||||||
|
|
||||||
|
// parse digest block from c1s1.
|
||||||
|
// if created, user must free it by srs_digest_block_free
|
||||||
|
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
|
||||||
|
int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes);
|
||||||
|
|
||||||
|
// free the block data create by
|
||||||
|
// srs_digest_block_init or srs_digest_block_parse
|
||||||
|
void srs_digest_block_free(digest_block* digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy whole c1s1 to bytes.
|
||||||
|
*/
|
||||||
|
void srs_schema0_copy_to(char* bytes, bool with_digest,
|
||||||
|
int32_t time, int32_t version, key_block* key, digest_block* digest);
|
||||||
|
void srs_schema1_copy_to(char* bytes, bool with_digest,
|
||||||
|
int32_t time, int32_t version, digest_block* digest, key_block* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* c1s1 is splited by digest:
|
||||||
|
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||||
|
* digest-data: 32bytes
|
||||||
|
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||||
|
* @return a new allocated bytes, user must free it.
|
||||||
|
*/
|
||||||
|
char* srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* c1s1 is splited by digest:
|
||||||
|
* c1s1-part1: n bytes (time, version and digest-part1).
|
||||||
|
* digest-data: 32bytes
|
||||||
|
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
|
||||||
|
* @return a new allocated bytes, user must free it.
|
||||||
|
*/
|
||||||
|
char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compare the memory in bytes.
|
||||||
|
*/
|
||||||
|
bool srs_bytes_equals(void* pa, void* pb, int size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* c1s1 schema0
|
* c1s1 schema0
|
||||||
* time: 4bytes
|
* time: 4bytes
|
||||||
|
@ -236,41 +308,14 @@ namespace srs
|
||||||
*/
|
*/
|
||||||
virtual int s2_validate(c1s1* c1, bool& is_valid);
|
virtual int s2_validate(c1s1* c1, bool& is_valid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* compare the memory in bytes.
|
|
||||||
*/
|
|
||||||
bool srs_bytes_equals(void* pa, void* pb, int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* c1s1 is splited by digest:
|
|
||||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
|
||||||
* digest-data: 32bytes
|
|
||||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
|
||||||
* @return a new allocated bytes, user must free it.
|
|
||||||
*/
|
|
||||||
char* srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* c1s1 is splited by digest:
|
|
||||||
* c1s1-part1: n bytes (time, version and digest-part1).
|
|
||||||
* digest-data: 32bytes
|
|
||||||
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
|
|
||||||
* @return a new allocated bytes, user must free it.
|
|
||||||
*/
|
|
||||||
char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
|
|
||||||
|
|
||||||
// the digest key generate size.
|
|
||||||
#define OpensslHashSize 512
|
|
||||||
extern u_int8_t SrsGenuineFMSKey[];
|
|
||||||
extern u_int8_t SrsGenuineFPKey[];
|
|
||||||
int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* try complex handshake, if failed, fallback to simple handshake.
|
* simple handshake.
|
||||||
|
* user can try complex handshake first,
|
||||||
|
* rollback to simple handshake if error ERROR_RTMP_TRY_SIMPLE_HS
|
||||||
*/
|
*/
|
||||||
class SrsSimpleHandshake
|
class SrsSimpleHandshake
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,77 @@ ISrsThreadContext* _srs_context = new ISrsThreadContext();
|
||||||
SrsConfig* _srs_config = NULL;
|
SrsConfig* _srs_config = NULL;
|
||||||
SrsServer* _srs_server = NULL;
|
SrsServer* _srs_server = NULL;
|
||||||
|
|
||||||
|
MockEmptyIO::MockEmptyIO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MockEmptyIO::~MockEmptyIO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockEmptyIO::is_never_timeout(int64_t /*timeout_us*/)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::read_fully(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/)
|
||||||
|
{
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::write(const void* /*buf*/, size_t /*size*/, ssize_t* /*nwrite*/)
|
||||||
|
{
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockEmptyIO::set_recv_timeout(int64_t /*timeout_us*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MockEmptyIO::get_recv_timeout()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MockEmptyIO::get_recv_bytes()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::get_recv_kbps()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockEmptyIO::set_send_timeout(int64_t /*timeout_us*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MockEmptyIO::get_send_timeout()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MockEmptyIO::get_send_bytes()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::get_send_kbps()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::writev(const iovec */*iov*/, int /*iov_size*/, ssize_t* /*nwrite*/)
|
||||||
|
{
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockEmptyIO::read(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/)
|
||||||
|
{
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// basic test and samples.
|
// basic test and samples.
|
||||||
VOID TEST(SampleTest, FastSampleInt64Test)
|
VOID TEST(SampleTest, FastSampleInt64Test)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,4 +34,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// we add an empty macro for upp to show the smart tips.
|
// we add an empty macro for upp to show the smart tips.
|
||||||
#define VOID
|
#define VOID
|
||||||
|
|
||||||
|
#include <srs_protocol_io.hpp>
|
||||||
|
|
||||||
|
class MockEmptyIO : public ISrsProtocolReaderWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockEmptyIO();
|
||||||
|
virtual ~MockEmptyIO();
|
||||||
|
// for protocol
|
||||||
|
public:
|
||||||
|
virtual bool is_never_timeout(int64_t timeout_us);
|
||||||
|
// for handshake.
|
||||||
|
public:
|
||||||
|
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
||||||
|
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
|
||||||
|
// for protocol
|
||||||
|
public:
|
||||||
|
virtual void set_recv_timeout(int64_t timeout_us);
|
||||||
|
virtual int64_t get_recv_timeout();
|
||||||
|
virtual int64_t get_recv_bytes();
|
||||||
|
virtual int get_recv_kbps();
|
||||||
|
// for protocol
|
||||||
|
public:
|
||||||
|
virtual void set_send_timeout(int64_t timeout_us);
|
||||||
|
virtual int64_t get_send_timeout();
|
||||||
|
virtual int64_t get_send_bytes();
|
||||||
|
virtual int get_send_kbps();
|
||||||
|
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
|
||||||
|
// for protocol/amf0/msg-codec
|
||||||
|
public:
|
||||||
|
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,77 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
|
#include <srs_protocol_utility.hpp>
|
||||||
MockEmptyIO::MockEmptyIO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MockEmptyIO::~MockEmptyIO()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MockEmptyIO::is_never_timeout(int64_t /*timeout_us*/)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::read_fully(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/)
|
|
||||||
{
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::write(const void* /*buf*/, size_t /*size*/, ssize_t* /*nwrite*/)
|
|
||||||
{
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MockEmptyIO::set_recv_timeout(int64_t /*timeout_us*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MockEmptyIO::get_recv_timeout()
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MockEmptyIO::get_recv_bytes()
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::get_recv_kbps()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MockEmptyIO::set_send_timeout(int64_t /*timeout_us*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MockEmptyIO::get_send_timeout()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MockEmptyIO::get_send_bytes()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::get_send_kbps()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::writev(const iovec */*iov*/, int /*iov_size*/, ssize_t* /*nwrite*/)
|
|
||||||
{
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MockEmptyIO::read(const void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/)
|
|
||||||
{
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify the sha256
|
// verify the sha256
|
||||||
VOID TEST(HandshakeTest, OpensslSha256)
|
VOID TEST(HandshakeTest, OpensslSha256)
|
||||||
|
@ -124,6 +54,37 @@ VOID TEST(HandshakeTest, OpensslSha256)
|
||||||
EXPECT_TRUE(srs_bytes_equals(digest, expect_digest, 32));
|
EXPECT_TRUE(srs_bytes_equals(digest, expect_digest, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verify the dh key
|
||||||
|
VOID TEST(HandshakeTest, DHKey)
|
||||||
|
{
|
||||||
|
char pri_key[] = {
|
||||||
|
0x6e, 0x65, 0x69, 0x2d, 0x69, 0x2d, 0x69, 0x73,
|
||||||
|
0x6e, 0x69, 0x73, 0x6c, 0x65, 0x72, 0x69, 0x72,
|
||||||
|
0x76, 0x65, 0x72, 0x69, 0x77, 0x74, 0x2e, 0x6e,
|
||||||
|
0x72, 0x76, 0x72, 0x65, 0x72, 0x70, 0x72, 0x69,
|
||||||
|
0x69, 0x70, 0x72, 0x73, 0x6e, 0x65, 0x72, 0x72,
|
||||||
|
0x6e, 0x2d, 0x65, 0x74, 0x72, 0x6c, 0x69, 0x74,
|
||||||
|
0x69, 0x65, 0x40, 0x69, 0x69, 0x76, 0x77, 0x2d,
|
||||||
|
0x73, 0x65, 0x72, 0x72, 0x76, 0x73, 0x72, 0x2e,
|
||||||
|
0x2d, 0x76, 0x65, 0x31, 0x65, 0x6d, 0x6d, 0x73,
|
||||||
|
0x69, 0x73, 0x74, 0x2e, 0x74, 0x72, 0x65, 0x65,
|
||||||
|
0x72, 0x65, 0x2d, 0x74, 0x69, 0x31, 0x65, 0x2d,
|
||||||
|
0x6f, 0x77, 0x2e, 0x76, 0x77, 0x2d, 0x77, 0x72,
|
||||||
|
0x65, 0x65, 0x31, 0x74, 0x73, 0x70, 0x74, 0x6e,
|
||||||
|
0x72, 0x6e, 0x73, 0x6d, 0x2e, 0x69, 0x72, 0x2d,
|
||||||
|
0x65, 0x69, 0x77, 0x69, 0x76, 0x72, 0x77, 0x72,
|
||||||
|
0x32, 0x6e, 0x65, 0x6c, 0x2e, 0x2d, 0x6e, 0x69
|
||||||
|
};
|
||||||
|
|
||||||
|
char pub_key1[128];
|
||||||
|
openssl_generate_key(pri_key, pub_key1, 128);
|
||||||
|
|
||||||
|
char pub_key2[128];
|
||||||
|
openssl_generate_key(pri_key, pub_key2, 128);
|
||||||
|
|
||||||
|
EXPECT_FALSE(srs_bytes_equals(pub_key1, pub_key2, 128));
|
||||||
|
}
|
||||||
|
|
||||||
// flash will sendout a c0c1 encrypt by ssl.
|
// flash will sendout a c0c1 encrypt by ssl.
|
||||||
VOID TEST(HandshakeTest, VerifyFPC0C1)
|
VOID TEST(HandshakeTest, VerifyFPC0C1)
|
||||||
{
|
{
|
||||||
|
@ -260,3 +221,19 @@ VOID TEST(HandshakeTest, ComplexHandshake)
|
||||||
ASSERT_TRUE(is_valid);
|
ASSERT_TRUE(is_valid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID TEST(HandshakeTest, BytesEqual)
|
||||||
|
{
|
||||||
|
char a1[] = { 0x01 };
|
||||||
|
char b1[] = { 0x02 };
|
||||||
|
char a2[] = { 0x01, 0x02 };
|
||||||
|
char b2[] = { 0x02, 0x03 };
|
||||||
|
|
||||||
|
EXPECT_TRUE(srs_bytes_equals(NULL, NULL, 0));
|
||||||
|
EXPECT_FALSE(srs_bytes_equals(a1, NULL, 1));
|
||||||
|
EXPECT_FALSE(srs_bytes_equals(NULL, a1, 1));
|
||||||
|
EXPECT_FALSE(srs_bytes_equals(a1, b1, 1));
|
||||||
|
EXPECT_TRUE(srs_bytes_equals(a1, a1, 1));
|
||||||
|
EXPECT_TRUE(srs_bytes_equals(a1, a2, 1));
|
||||||
|
EXPECT_FALSE(srs_bytes_equals(a1, b2, 1));
|
||||||
|
}
|
||||||
|
|
|
@ -29,39 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include <srs_utest.hpp>
|
#include <srs_utest.hpp>
|
||||||
|
|
||||||
#include <srs_protocol_io.hpp>
|
|
||||||
#include <srs_protocol_rtmp.hpp>
|
#include <srs_protocol_rtmp.hpp>
|
||||||
#include <srs_protocol_handshake.hpp>
|
#include <srs_protocol_handshake.hpp>
|
||||||
using namespace srs;
|
using namespace srs;
|
||||||
|
|
||||||
class MockEmptyIO : public ISrsProtocolReaderWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MockEmptyIO();
|
|
||||||
virtual ~MockEmptyIO();
|
|
||||||
// for protocol
|
|
||||||
public:
|
|
||||||
virtual bool is_never_timeout(int64_t timeout_us);
|
|
||||||
// for handshake.
|
|
||||||
public:
|
|
||||||
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
|
||||||
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
|
|
||||||
// for protocol
|
|
||||||
public:
|
|
||||||
virtual void set_recv_timeout(int64_t timeout_us);
|
|
||||||
virtual int64_t get_recv_timeout();
|
|
||||||
virtual int64_t get_recv_bytes();
|
|
||||||
virtual int get_recv_kbps();
|
|
||||||
// for protocol
|
|
||||||
public:
|
|
||||||
virtual void set_send_timeout(int64_t timeout_us);
|
|
||||||
virtual int64_t get_send_timeout();
|
|
||||||
virtual int64_t get_send_bytes();
|
|
||||||
virtual int get_send_kbps();
|
|
||||||
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
|
|
||||||
// for protocol/amf0/msg-codec
|
|
||||||
public:
|
|
||||||
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue