diff --git a/README.md b/README.md
index 6aef9bece..c6b2d8455 100755
--- a/README.md
+++ b/README.md
@@ -167,6 +167,8 @@ See also: [Performance Test Guide](https://github.com/winlinvip/simple-rtmp-serv
* nginx v1.5.0: 139524 lines
### 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-12, finish utest for amf0 codec.
* v1.0, 2014-03-06, add gperftools for mem leak detect, mem/cpu profile.
diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf
old mode 100644
new mode 100755
index dbd22386f..c35c21b26
--- a/trunk/conf/full.conf
+++ b/trunk/conf/full.conf
@@ -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).
# copy the video and audio to a new stream.
vhost copy.transcode.vhost.com {
@@ -333,6 +352,7 @@ vhost all.transcode.vhost.com {
# video encoder name. can be:
# libx264: use h.264(libx264) video encoder.
# copy: donot encoder the video stream, copy it.
+ # vn: disable video output.
vcodec libx264;
# video bitrate, in kbps
vbitrate 1500;
@@ -364,6 +384,7 @@ vhost all.transcode.vhost.com {
# audio encoder name. can be:
# libaacplus: use aac(libaacplus) audio encoder.
# copy: donot encoder the audio stream, copy it.
+ # an: disable audio output.
acodec libaacplus;
# audio bitrate, in kbps. [16, 72] for libaacplus.
abitrate 70;
diff --git a/trunk/conf/srs.conf b/trunk/conf/srs.conf
old mode 100644
new mode 100755
diff --git a/trunk/src/app/srs_app_encoder.cpp b/trunk/src/app/srs_app_encoder.cpp
index 9524b0772..3fbc79787 100644
--- a/trunk/src/app/srs_app_encoder.cpp
+++ b/trunk/src/app/srs_app_encoder.cpp
@@ -42,6 +42,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_FFMPEG
#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_ACODEC "libaacplus"
@@ -138,7 +140,13 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
}
_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) {
ret = ERROR_ENCODER_VCODEC;
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) {
ret = ERROR_ENCODER_ACODEC;
srs_error("invalid acodec, must be %s, actual %s, ret=%d",
@@ -254,11 +262,15 @@ int SrsFFMPEG::start()
}
// video specified.
- params.push_back("-vcodec");
- params.push_back(vcodec);
+ if (vcodec != SRS_ENCODER_NO_VIDEO) {
+ params.push_back("-vcodec");
+ params.push_back(vcodec);
+ } else {
+ params.push_back("-vn");
+ }
// 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");
snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000);
params.push_back(tmp);
@@ -299,11 +311,15 @@ int SrsFFMPEG::start()
}
// audio specified.
- params.push_back("-acodec");
- params.push_back(acodec);
+ if (acodec != SRS_ENCODER_NO_AUDIO) {
+ params.push_back("-acodec");
+ params.push_back(acodec);
+ } else {
+ params.push_back("-an");
+ }
// 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");
snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000);
params.push_back(tmp);
diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp
index 0d5f62ebe..a64bc09eb 100644
--- a/trunk/src/core/srs_core.hpp
+++ b/trunk/src/core/srs_core.hpp
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
-#define VERSION_REVISION "21"
+#define VERSION_REVISION "22"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
diff --git a/trunk/src/rtmp/srs_protocol_handshake.cpp b/trunk/src/rtmp/srs_protocol_handshake.cpp
index bd167cfad..2048a5d39 100644
--- a/trunk/src/rtmp/srs_protocol_handshake.cpp
+++ b/trunk/src/rtmp/srs_protocol_handshake.cpp
@@ -32,924 +32,944 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include
#include
-using namespace srs;
-
#ifdef SRS_SSL
-// 68bytes FMS key which is used to sign the sever packet.
-u_int8_t srs::SrsGenuineFMSKey[] = {
- 0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,
- 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,
- 0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,
- 0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001
- 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8,
- 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,
- 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
- 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
-}; // 68
-
-// 62bytes FP key which is used to sign the client packet.
-u_int8_t srs::SrsGenuineFPKey[] = {
- 0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,
- 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,
- 0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,
- 0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001
- 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8,
- 0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,
- 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
- 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
-}; // 62
+using namespace srs;
+// for openssl_HMACsha256
#include
#include
-int srs::openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest)
-{
- HMAC_CTX ctx;
-
- HMAC_CTX_init(&ctx);
- HMAC_Init_ex(&ctx, (unsigned char*) key, key_size, EVP_sha256(), NULL);
- HMAC_Update(&ctx, (unsigned char *) data, data_size);
-
- unsigned int digest_size;
- HMAC_Final(&ctx, (unsigned char *) digest, &digest_size);
-
- HMAC_CTX_cleanup(&ctx);
-
- if (digest_size != 32) {
- return ERROR_OpenSslSha256DigestSize;
- }
-
- return ERROR_SUCCESS;
-}
-
+// for __openssl_generate_key
#include
-#define RFC2409_PRIME_1024 \
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
- "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
- "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
- "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
- "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
- "FFFFFFFFFFFFFFFF"
-int __openssl_generate_key(
- 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
-){
- int ret = ERROR_SUCCESS;
- //1. Create the DH
- if ((pdh = DH_new()) == NULL) {
- ret = ERROR_OpenSslCreateDH;
- return ret;
- }
-
- //2. Create his internal p and g
- if ((pdh->p = BN_new()) == NULL) {
- ret = ERROR_OpenSslCreateP;
- return ret;
- }
- if ((pdh->g = BN_new()) == NULL) {
- ret = ERROR_OpenSslCreateG;
- return ret;
- }
-
- //3. initialize p, g and key length
- if (BN_hex2bn(&pdh->p, RFC2409_PRIME_1024) == 0) {
- ret = ERROR_OpenSslParseP1024;
- return ret;
- }
- if (BN_set_word(pdh->g, 2) != 1) {
- ret = ERROR_OpenSslSetG;
- return ret;
- }
-
- //4. Set the key length
- pdh->length = bits_count;
-
- //5. Generate private and public key
- if (DH_generate_key(pdh) != 1) {
- ret = ERROR_OpenSslGenerateDHKeys;
- return ret;
- }
-
- // CreateSharedKey
- if (pdh == NULL) {
- ret = ERROR_OpenSslGenerateDHKeys;
- return ret;
- }
-
- if (shared_key_length != 0 || shared_key != NULL) {
- ret = ERROR_OpenSslShareKeyComputed;
- return ret;
- }
-
- shared_key_length = DH_size(pdh);
- if (shared_key_length <= 0 || shared_key_length > 1024) {
- ret = ERROR_OpenSslGetSharedKeySize;
- return ret;
- }
- shared_key = new u_int8_t[shared_key_length];
- memset(shared_key, 0, shared_key_length);
-
- peer_public_key = BN_bin2bn(_private_key, size, 0);
- if (peer_public_key == NULL) {
- ret = ERROR_OpenSslGetPeerPublicKey;
- return ret;
- }
-
- if (DH_compute_key(shared_key, peer_public_key, pdh) == -1) {
- ret = ERROR_OpenSslComputeSharedKey;
- return ret;
- }
-
- // CopyPublicKey
- if (pdh == NULL) {
- ret = ERROR_OpenSslComputeSharedKey;
- return ret;
- }
-
- int32_t keySize = BN_num_bytes(pdh->pub_key);
- if ((keySize <= 0) || (size <= 0) || (keySize > size)) {
- //("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret;
- ret = ERROR_OpenSslInvalidDHState;
- return ret;
- }
-
- if (BN_bn2bin(pdh->pub_key, _public_key) != keySize) {
- //("Unable to copy key"); return ret;
- ret = ERROR_OpenSslCopyKey;
- return ret;
- }
-
- return ret;
-}
-int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
+namespace srs
{
- int ret = ERROR_SUCCESS;
-
- // Initialize
- DH* pdh = NULL;
- int32_t bits_count = 1024;
- u_int8_t* shared_key = NULL;
- int32_t shared_key_length = 0;
- BIGNUM* peer_public_key = NULL;
+ // 68bytes FMS key which is used to sign the sever packet.
+ u_int8_t SrsGenuineFMSKey[] = {
+ 0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,
+ 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,
+ 0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,
+ 0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001
+ 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8,
+ 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,
+ 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
+ 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
+ }; // 68
- ret = __openssl_generate_key(
- (u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size,
- pdh, bits_count, shared_key, shared_key_length, peer_public_key
- );
+ // 62bytes FP key which is used to sign the client packet.
+ u_int8_t SrsGenuineFPKey[] = {
+ 0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,
+ 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,
+ 0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,
+ 0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001
+ 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8,
+ 0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,
+ 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
+ 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
+ }; // 62
- if (pdh != NULL) {
- if (pdh->p != NULL) {
- BN_free(pdh->p);
- pdh->p = NULL;
+ int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest)
+ {
+ HMAC_CTX ctx;
+
+ HMAC_CTX_init(&ctx);
+ HMAC_Init_ex(&ctx, (unsigned char*) key, key_size, EVP_sha256(), NULL);
+ HMAC_Update(&ctx, (unsigned char *) data, data_size);
+
+ unsigned int digest_size;
+ HMAC_Final(&ctx, (unsigned char *) digest, &digest_size);
+
+ HMAC_CTX_cleanup(&ctx);
+
+ if (digest_size != 32) {
+ return ERROR_OpenSslSha256DigestSize;
}
- if (pdh->g != NULL) {
- BN_free(pdh->g);
- pdh->g = NULL;
+
+ return ERROR_SUCCESS;
+ }
+
+ #define RFC2409_PRIME_1024 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+ "FFFFFFFFFFFFFFFF"
+ int __openssl_generate_key(
+ 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
+ ){
+ int ret = ERROR_SUCCESS;
+
+ //1. Create the DH
+ if ((pdh = DH_new()) == NULL) {
+ ret = ERROR_OpenSslCreateDH;
+ return ret;
+ }
+
+ //2. Create his internal p and g
+ if ((pdh->p = BN_new()) == NULL) {
+ ret = ERROR_OpenSslCreateP;
+ return ret;
+ }
+ if ((pdh->g = BN_new()) == NULL) {
+ ret = ERROR_OpenSslCreateG;
+ return ret;
+ }
+
+ //3. initialize p, g and key length
+ if (BN_hex2bn(&pdh->p, RFC2409_PRIME_1024) == 0) {
+ ret = ERROR_OpenSslParseP1024;
+ return ret;
+ }
+ if (BN_set_word(pdh->g, 2) != 1) {
+ ret = ERROR_OpenSslSetG;
+ return ret;
+ }
+
+ //4. Set the key length
+ pdh->length = bits_count;
+
+ //5. Generate private and public key
+ if (DH_generate_key(pdh) != 1) {
+ ret = ERROR_OpenSslGenerateDHKeys;
+ return ret;
+ }
+
+ // CreateSharedKey
+ if (pdh == NULL) {
+ ret = ERROR_OpenSslGenerateDHKeys;
+ return ret;
+ }
+
+ if (shared_key_length != 0 || shared_key != NULL) {
+ ret = ERROR_OpenSslShareKeyComputed;
+ return ret;
+ }
+
+ shared_key_length = DH_size(pdh);
+ if (shared_key_length <= 0 || shared_key_length > 1024) {
+ ret = ERROR_OpenSslGetSharedKeySize;
+ return ret;
+ }
+ shared_key = new u_int8_t[shared_key_length];
+ memset(shared_key, 0, shared_key_length);
+
+ peer_public_key = BN_bin2bn(_private_key, size, 0);
+ if (peer_public_key == NULL) {
+ ret = ERROR_OpenSslGetPeerPublicKey;
+ return ret;
+ }
+
+ if (DH_compute_key(shared_key, peer_public_key, pdh) == -1) {
+ ret = ERROR_OpenSslComputeSharedKey;
+ return ret;
+ }
+
+ // CopyPublicKey
+ if (pdh == NULL) {
+ ret = ERROR_OpenSslComputeSharedKey;
+ return ret;
+ }
+
+ int32_t keySize = BN_num_bytes(pdh->pub_key);
+ if ((keySize <= 0) || (size <= 0) || (keySize > size)) {
+ //("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret;
+ ret = ERROR_OpenSslInvalidDHState;
+ return ret;
+ }
+
+ if (BN_bn2bin(pdh->pub_key, _public_key) != keySize) {
+ //("Unable to copy key"); return ret;
+ ret = ERROR_OpenSslCopyKey;
+ return ret;
+ }
+
+ return ret;
+ }
+ int openssl_generate_key(char* _private_key, char* _public_key, int32_t size)
+ {
+ int ret = ERROR_SUCCESS;
+
+ // Initialize
+ DH* pdh = NULL;
+ int32_t bits_count = 1024;
+ u_int8_t* shared_key = NULL;
+ int32_t shared_key_length = 0;
+ BIGNUM* peer_public_key = NULL;
+
+ ret = __openssl_generate_key(
+ (u_int8_t*)_private_key, (u_int8_t*)_public_key, size,
+ pdh, bits_count, shared_key, shared_key_length, peer_public_key
+ );
+
+ if (pdh != NULL) {
+ if (pdh->p != NULL) {
+ BN_free(pdh->p);
+ pdh->p = NULL;
+ }
+ if (pdh->g != NULL) {
+ BN_free(pdh->g);
+ pdh->g = NULL;
+ }
+ DH_free(pdh);
+ pdh = NULL;
+ }
+
+ if (shared_key != NULL) {
+ delete[] shared_key;
+ shared_key = NULL;
+ }
+
+ if (peer_public_key != NULL) {
+ BN_free(peer_public_key);
+ peer_public_key = NULL;
+ }
+
+ return ret;
+ }
+
+ // 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)
+ {
+ int max_offset_size = 764 - 128 - 4;
+
+ int offset = 0;
+ u_int8_t* pp = (u_int8_t*)&key->offset;
+ offset += *pp++;
+ offset += *pp++;
+ offset += *pp++;
+ offset += *pp++;
+
+ return offset % max_offset_size;
+ }
+
+ // create new key block data.
+ // 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->random0 = NULL;
+ key->random1 = NULL;
+
+ int offset = srs_key_block_get_offset(key);
+ srs_assert(offset >= 0);
+
+ key->random0_size = offset;
+ if (key->random0_size > 0) {
+ key->random0 = new char[key->random0_size];
+ srs_random_generate(key->random0, key->random0_size);
+ }
+
+ srs_random_generate(key->key, sizeof(key->key));
+
+ key->random1_size = 764 - offset - 128 - 4;
+ if (key->random1_size > 0) {
+ key->random1 = new char[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
+ // @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;
+
+ char* pp = c1s1_key_bytes + 764;
+
+ pp -= sizeof(int32_t);
+ key->offset = *(int32_t*)pp;
+
+ key->random0 = NULL;
+ key->random1 = NULL;
+
+ int offset = srs_key_block_get_offset(key);
+ srs_assert(offset >= 0);
+
+ pp = c1s1_key_bytes;
+ key->random0_size = offset;
+ if (key->random0_size > 0) {
+ key->random0 = new char[key->random0_size];
+ memcpy(key->random0, pp, key->random0_size);
+ }
+ pp += key->random0_size;
+
+ memcpy(key->key, pp, sizeof(key->key));
+ pp += sizeof(key->key);
+
+ key->random1_size = 764 - offset - 128 - 4;
+ if (key->random1_size > 0) {
+ key->random1 = new char[key->random1_size];
+ memcpy(key->random1, pp, key->random1_size);
+ }
+
+ return ret;
+ }
+
+ // free the block data create by
+ // srs_key_block_init or srs_key_block_parse
+ void srs_key_block_free(key_block* key)
+ {
+ if (key->random0) {
+ srs_freepa(key->random0);
+ }
+ if (key->random1) {
+ srs_freepa(key->random1);
+ }
+ }
+
+ // 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)
+ {
+ int max_offset_size = 764 - 32 - 4;
+
+ int offset = 0;
+ u_int8_t* pp = (u_int8_t*)&digest->offset;
+ offset += *pp++;
+ offset += *pp++;
+ offset += *pp++;
+ offset += *pp++;
+
+ return offset % max_offset_size;
+ }
+
+ // create new digest block data.
+ // 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->random0 = NULL;
+ digest->random1 = NULL;
+
+ int offset = srs_digest_block_get_offset(digest);
+ srs_assert(offset >= 0);
+
+ digest->random0_size = offset;
+ if (digest->random0_size > 0) {
+ digest->random0 = new char[digest->random0_size];
+ srs_random_generate(digest->random0, digest->random0_size);
+ }
+
+ srs_random_generate(digest->digest, sizeof(digest->digest));
+
+ digest->random1_size = 764 - 4 - offset - 32;
+ if (digest->random1_size > 0) {
+ digest->random1 = new char[digest->random1_size];
+ srs_random_generate(digest->random1, digest->random1_size);
}
- DH_free(pdh);
- pdh = NULL;
}
- if (shared_key != NULL) {
- delete[] shared_key;
- shared_key = NULL;
- }
-
- if (peer_public_key != NULL) {
- BN_free(peer_public_key);
- peer_public_key = NULL;
- }
-
- return ret;
-}
-
-// 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)
-{
- int max_offset_size = 764 - 128 - 4;
+ // 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)
+ {
+ int ret = ERROR_SUCCESS;
- int offset = 0;
- u_int8_t* pp = (u_int8_t*)&key->offset;
- offset += *pp++;
- offset += *pp++;
- offset += *pp++;
- offset += *pp++;
-
- return offset % max_offset_size;
-}
-// create new key block data.
-// 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->random0 = NULL;
- key->random1 = NULL;
-
- int offset = srs_key_block_get_offset(key);
- srs_assert(offset >= 0);
-
- key->random0_size = offset;
- if (key->random0_size > 0) {
- key->random0 = new char[key->random0_size];
- srs_random_generate(key->random0, key->random0_size);
+ char* pp = c1s1_digest_bytes;
+
+ digest->offset = *(int32_t*)pp;
+ pp += sizeof(int32_t);
+
+ digest->random0 = NULL;
+ digest->random1 = NULL;
+
+ int offset = srs_digest_block_get_offset(digest);
+ srs_assert(offset >= 0);
+
+ digest->random0_size = offset;
+ if (digest->random0_size > 0) {
+ digest->random0 = new char[digest->random0_size];
+ memcpy(digest->random0, pp, digest->random0_size);
+ }
+ pp += digest->random0_size;
+
+ memcpy(digest->digest, pp, sizeof(digest->digest));
+ pp += sizeof(digest->digest);
+
+ digest->random1_size = 764 - 4 - offset - 32;
+ if (digest->random1_size > 0) {
+ digest->random1 = new char[digest->random1_size];
+ memcpy(digest->random1, pp, digest->random1_size);
+ }
+
+ return ret;
}
- srs_random_generate(key->key, sizeof(key->key));
-
- key->random1_size = 764 - offset - 128 - 4;
- if (key->random1_size > 0) {
- key->random1 = new char[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
-// @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;
-
- char* pp = c1s1_key_bytes + 764;
-
- pp -= sizeof(int32_t);
- key->offset = *(int32_t*)pp;
-
- key->random0 = NULL;
- key->random1 = NULL;
-
- int offset = srs_key_block_get_offset(key);
- srs_assert(offset >= 0);
-
- pp = c1s1_key_bytes;
- key->random0_size = offset;
- if (key->random0_size > 0) {
- key->random0 = new char[key->random0_size];
- memcpy(key->random0, pp, key->random0_size);
- }
- pp += key->random0_size;
-
- memcpy(key->key, pp, sizeof(key->key));
- pp += sizeof(key->key);
-
- key->random1_size = 764 - offset - 128 - 4;
- if (key->random1_size > 0) {
- key->random1 = new char[key->random1_size];
- memcpy(key->random1, pp, key->random1_size);
+ // free the block data create by
+ // srs_digest_block_init or srs_digest_block_parse
+ void srs_digest_block_free(digest_block* digest)
+ {
+ if (digest->random0) {
+ srs_freepa(digest->random0);
+ }
+ if (digest->random1) {
+ srs_freepa(digest->random1);
+ }
}
- return ret;
-}
-// free the block data create by
-// srs_key_block_init or srs_key_block_parse
-void srs_key_block_free(key_block* key)
-{
- if (key->random0) {
- srs_freepa(key->random0);
+ void __srs_time_copy_to(char*& pp, int32_t time)
+ {
+ // 4bytes time
+ *(int32_t*)pp = time;
+ pp += 4;
}
- if (key->random1) {
- srs_freepa(key->random1);
+ void __srs_version_copy_to(char*& pp, int32_t version)
+ {
+ // 4bytes version
+ *(int32_t*)pp = version;
+ pp += 4;
}
-}
-
-// 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)
-{
- int max_offset_size = 764 - 32 - 4;
-
- int offset = 0;
- u_int8_t* pp = (u_int8_t*)&digest->offset;
- offset += *pp++;
- offset += *pp++;
- offset += *pp++;
- offset += *pp++;
-
- return offset % max_offset_size;
-}
-// create new digest block data.
-// 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->random0 = NULL;
- digest->random1 = NULL;
-
- int offset = srs_digest_block_get_offset(digest);
- srs_assert(offset >= 0);
-
- digest->random0_size = offset;
- if (digest->random0_size > 0) {
- digest->random0 = new char[digest->random0_size];
- srs_random_generate(digest->random0, digest->random0_size);
+ void __srs_key_copy_to(char*& pp, key_block* key)
+ {
+ // 764bytes key block
+ if (key->random0_size > 0) {
+ memcpy(pp, key->random0, key->random0_size);
+ }
+ pp += key->random0_size;
+
+ memcpy(pp, key->key, sizeof(key->key));
+ pp += sizeof(key->key);
+
+ if (key->random1_size > 0) {
+ memcpy(pp, key->random1, key->random1_size);
+ }
+ pp += key->random1_size;
+
+ *(int32_t*)pp = key->offset;
+ pp += 4;
+ }
+ void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
+ {
+ // 732bytes digest block without the 32bytes digest-data
+ // nbytes digest block part1
+ *(int32_t*)pp = digest->offset;
+ pp += 4;
+
+ if (digest->random0_size > 0) {
+ memcpy(pp, digest->random0, digest->random0_size);
+ }
+ pp += digest->random0_size;
+
+ // digest
+ if (with_digest) {
+ memcpy(pp, digest->digest, 32);
+ pp += 32;
+ }
+
+ // nbytes digest block part2
+ if (digest->random1_size > 0) {
+ memcpy(pp, digest->random1, digest->random1_size);
+ }
+ pp += digest->random1_size;
}
- srs_random_generate(digest->digest, sizeof(digest->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)
+ {
+ char* pp = bytes;
- digest->random1_size = 764 - 4 - offset - 32;
- if (digest->random1_size > 0) {
- digest->random1 = new char[digest->random1_size];
- srs_random_generate(digest->random1, digest->random1_size);
+ __srs_time_copy_to(pp, time);
+ __srs_version_copy_to(pp, version);
+ __srs_key_copy_to(pp, key);
+ __srs_digest_copy_to(pp, digest, with_digest);
+
+ if (with_digest) {
+ srs_assert(pp - bytes == 1536);
+ } else {
+ srs_assert(pp - bytes == 1536 - 32);
+ }
}
-}
-// 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)
-{
- int ret = ERROR_SUCCESS;
-
- char* pp = c1s1_digest_bytes;
+ void srs_schema1_copy_to(char* bytes, bool with_digest,
+ int32_t time, int32_t version, digest_block* digest, key_block* key)
+ {
+ char* pp = bytes;
- digest->offset = *(int32_t*)pp;
- pp += sizeof(int32_t);
-
- digest->random0 = NULL;
- digest->random1 = NULL;
-
- int offset = srs_digest_block_get_offset(digest);
- srs_assert(offset >= 0);
-
- digest->random0_size = offset;
- if (digest->random0_size > 0) {
- digest->random0 = new char[digest->random0_size];
- memcpy(digest->random0, pp, digest->random0_size);
- }
- pp += digest->random0_size;
-
- memcpy(digest->digest, pp, sizeof(digest->digest));
- pp += sizeof(digest->digest);
-
- digest->random1_size = 764 - 4 - offset - 32;
- if (digest->random1_size > 0) {
- digest->random1 = new char[digest->random1_size];
- memcpy(digest->random1, pp, digest->random1_size);
+ __srs_time_copy_to(pp, time);
+ __srs_version_copy_to(pp, version);
+ __srs_digest_copy_to(pp, digest, with_digest);
+ __srs_key_copy_to(pp, key);
+
+ if (with_digest) {
+ srs_assert(pp - bytes == 1536);
+ } else {
+ srs_assert(pp - bytes == 1536 - 32);
+ }
}
- return ret;
-}
-// free the block data create by
-// srs_digest_block_init or srs_digest_block_parse
-void srs_digest_block_free(digest_block* digest)
-{
- if (digest->random0) {
- srs_freepa(digest->random0);
- }
- if (digest->random1) {
- srs_freepa(digest->random1);
- }
-}
-
-void __srs_time_copy_to(char*& pp, int32_t time)
-{
- // 4bytes time
- *(int32_t*)pp = time;
- pp += 4;
-}
-void __srs_version_copy_to(char*& pp, int32_t version)
-{
- // 4bytes version
- *(int32_t*)pp = version;
- pp += 4;
-}
-void __srs_key_copy_to(char*& pp, key_block* key)
-{
- // 764bytes key block
- if (key->random0_size > 0) {
- memcpy(pp, key->random0, key->random0_size);
- }
- pp += key->random0_size;
-
- memcpy(pp, key->key, sizeof(key->key));
- pp += sizeof(key->key);
-
- if (key->random1_size > 0) {
- memcpy(pp, key->random1, key->random1_size);
- }
- pp += key->random1_size;
-
- *(int32_t*)pp = key->offset;
- pp += 4;
-}
-void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
-{
- // 732bytes digest block without the 32bytes digest-data
- // nbytes digest block part1
- *(int32_t*)pp = digest->offset;
- pp += 4;
-
- if (digest->random0_size > 0) {
- memcpy(pp, digest->random0, digest->random0_size);
- }
- pp += digest->random0_size;
-
- // digest
- if (with_digest) {
- memcpy(pp, digest->digest, 32);
- pp += 32;
+ /**
+ * 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)
+ */
+ char* srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest)
+ {
+ char* bytes = new char[1536 -32];
+
+ srs_schema0_copy_to(bytes, false, time, version, key, digest);
+
+ return bytes;
}
- // nbytes digest block part2
- if (digest->random1_size > 0) {
- memcpy(pp, digest->random1, digest->random1_size);
+ /**
+ * 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)
+ */
+ char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key)
+ {
+ char* bytes = new char[1536 -32];
+
+ srs_schema1_copy_to(bytes, false, time, version, digest, key);
+
+ return bytes;
}
- pp += digest->random1_size;
-}
-
-/**
-* 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)
-{
- char* pp = bytes;
-
- __srs_time_copy_to(pp, time);
- __srs_version_copy_to(pp, version);
- __srs_key_copy_to(pp, key);
- __srs_digest_copy_to(pp, digest, with_digest);
- if (with_digest) {
- srs_assert(pp - bytes == 1536);
- } else {
- srs_assert(pp - bytes == 1536 - 32);
- }
-}
-void srs_schema1_copy_to(char* bytes, bool with_digest,
- int32_t time, int32_t version, digest_block* digest, key_block* key)
-{
- char* pp = bytes;
-
- __srs_time_copy_to(pp, time);
- __srs_version_copy_to(pp, version);
- __srs_digest_copy_to(pp, digest, with_digest);
- __srs_key_copy_to(pp, key);
-
- if (with_digest) {
- srs_assert(pp - bytes == 1536);
- } else {
- srs_assert(pp - bytes == 1536 - 32);
- }
-}
-
-/**
-* 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)
-*/
-char* srs::srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest)
-{
- char* bytes = new char[1536 -32];
-
- srs_schema0_copy_to(bytes, false, time, version, key, digest);
-
- return bytes;
-}
-
-/**
-* 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)
-*/
-char* srs::srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key)
-{
- char* bytes = new char[1536 -32];
-
- srs_schema1_copy_to(bytes, false, time, version, digest, key);
-
- return bytes;
-}
-
-/**
-* compare the memory in bytes.
-*/
-bool srs::srs_bytes_equals(void* pa, void* pb, int size)
-{
- u_int8_t* a = (u_int8_t*)pa;
- u_int8_t* b = (u_int8_t*)pb;
-
- for(int i = 0; i < size; i++){
- if(a[i] != b[i]){
+ /**
+ * compare the memory in bytes.
+ */
+ bool srs_bytes_equals(void* pa, void* pb, int size)
+ {
+ u_int8_t* a = (u_int8_t*)pa;
+ u_int8_t* b = (u_int8_t*)pb;
+
+ if (!a && !b) {
+ return true;
+ }
+
+ if (!a || !b) {
return false;
}
- }
-
- return true;
-}
-
-c2s2::c2s2()
-{
- srs_random_generate(random, 1504);
- srs_random_generate(digest, 32);
-}
-
-c2s2::~c2s2()
-{
-}
-
-void c2s2::dump(char* _c2s2)
-{
- memcpy(_c2s2, random, 1504);
- 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;
-
- 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.");
-
- memcpy(digest, _digest, 32);
-
- 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;
-
- 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.");
-
- memcpy(digest, _digest, 32);
-
- 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;
-}
-
-// TODO: FIXME: move to the right position.
-c1s1::c1s1()
-{
- schema = srs_schema_invalid;
-}
-c1s1::~c1s1()
-{
- destroy_blocks();
-}
-
-char* c1s1::get_digest()
-{
- srs_assert(schema != srs_schema_invalid);
-
- if (schema == srs_schema0) {
- return block1.digest.digest;
- } else {
- return block0.digest.digest;
- }
-}
-
-void c1s1::dump(char* _c1s1)
-{
- srs_assert(schema != srs_schema_invalid);
-
- if (schema == srs_schema0) {
- srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest);
- } else {
- srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key);
- }
-}
-
-int c1s1::parse(char* _c1s1, srs_schema_type _schema)
-{
- int ret = ERROR_SUCCESS;
-
- if (_schema == srs_schema_invalid) {
- ret = ERROR_RTMP_CH_SCHEMA;
- srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
- return ret;
- }
-
- destroy_blocks();
-
- time = *(int32_t*)_c1s1;
- version = *(int32_t*)(_c1s1 + 4); // client c1 version
-
- if (_schema == srs_schema0) {
- if ((ret = srs_key_block_parse(&block0.key, _c1s1 + 8)) != ERROR_SUCCESS) {
- srs_error("parse the c1 key failed. ret=%d", ret);
- return ret;
- }
- if ((ret = srs_digest_block_parse(&block1.digest, _c1s1 + 8 + 764)) != ERROR_SUCCESS) {
- srs_error("parse the c1 digest failed. ret=%d", ret);
- return ret;
- }
- srs_verbose("parse c1 key-digest success");
- } else if (_schema == srs_schema1) {
- if ((ret = srs_digest_block_parse(&block0.digest, _c1s1 + 8)) != ERROR_SUCCESS) {
- srs_error("parse the c1 key failed. ret=%d", ret);
- return ret;
- }
- if ((ret = srs_key_block_parse(&block1.key, _c1s1 + 8 + 764)) != ERROR_SUCCESS) {
- srs_error("parse the c1 digest failed. ret=%d", ret);
- return ret;
- }
- srs_verbose("parse c1 digest-key success");
- } else {
- ret = ERROR_RTMP_CH_SCHEMA;
- srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
- return ret;
- }
-
- schema = _schema;
-
- return ret;
-}
-
-int c1s1::c1_create(srs_schema_type _schema)
-{
- int ret = ERROR_SUCCESS;
-
- if (_schema == srs_schema_invalid) {
- ret = ERROR_RTMP_CH_SCHEMA;
- srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret);
- return ret;
- }
-
- destroy_blocks();
-
- time = ::time(NULL);
- version = 0x02070080; // client c1 version
-
- if (_schema == srs_schema0) {
- srs_key_block_init(&block0.key);
- srs_digest_block_init(&block1.digest);
- } else {
- srs_digest_block_init(&block0.digest);
- srs_key_block_init(&block1.key);
- }
-
- schema = _schema;
-
- char* digest = NULL;
-
- if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) {
- srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
- return ret;
- }
-
- srs_assert(digest != NULL);
- SrsAutoFree(char, digest, true);
-
- if (schema == srs_schema0) {
- memcpy(block1.digest.digest, digest, 32);
- } else {
- memcpy(block0.digest.digest, digest, 32);
- }
-
- return ret;
-}
-
-int c1s1::c1_validate_digest(bool& is_valid)
-{
- is_valid = false;
- int ret = ERROR_SUCCESS;
-
- char* c1_digest = NULL;
-
- if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) {
- srs_error("validate c1 error, failed to calc digest. ret=%d", ret);
- return ret;
- }
-
- srs_assert(c1_digest != NULL);
- SrsAutoFree(char, c1_digest, true);
-
- if (schema == srs_schema0) {
- is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32);
- } else {
- is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32);
- }
-
- return ret;
-}
-
-int c1s1::s1_validate_digest(bool& is_valid)
-{
- is_valid = false;
- int ret = ERROR_SUCCESS;
-
- char* s1_digest = NULL;
-
- if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {
- srs_error("validate s1 error, failed to calc digest. ret=%d", ret);
- return ret;
- }
-
- srs_assert(s1_digest != NULL);
- SrsAutoFree(char, s1_digest, true);
-
- if (schema == srs_schema0) {
- is_valid = srs_bytes_equals(block1.digest.digest, s1_digest, 32);
- } else {
- is_valid = srs_bytes_equals(block0.digest.digest, s1_digest, 32);
- }
-
- return ret;
-}
-
-int c1s1::s1_create(c1s1* c1)
-{
- int ret = ERROR_SUCCESS;
-
- if (c1->schema == srs_schema_invalid) {
- ret = ERROR_RTMP_CH_SCHEMA;
- srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret);
- return ret;
- }
-
- destroy_blocks();
- schema = c1->schema;
-
- time = ::time(NULL);
- version = 0x01000504; // server s1 version
-
- if (schema == srs_schema0) {
- srs_key_block_init(&block0.key);
- srs_digest_block_init(&block1.digest);
- } else {
- srs_digest_block_init(&block0.digest);
- srs_key_block_init(&block1.key);
- }
-
- if (schema == srs_schema0) {
- if ((ret = openssl_generate_key(c1->block0.key.key, block0.key.key, 128)) != ERROR_SUCCESS) {
- srs_error("calc s1 key failed. ret=%d", ret);
- return ret;
- }
- } else {
- if ((ret = openssl_generate_key(c1->block1.key.key, block1.key.key, 128)) != ERROR_SUCCESS) {
- srs_error("calc s1 key failed. ret=%d", ret);
- return ret;
- }
- }
- srs_verbose("calc s1 key success.");
- char* s1_digest = NULL;
- if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {
- srs_error("calc s1 digest failed. ret=%d", ret);
+ for(int i = 0; i < size; i++){
+ if(a[i] != b[i]){
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ c2s2::c2s2()
+ {
+ srs_random_generate(random, 1504);
+ srs_random_generate(digest, 32);
+ }
+
+ c2s2::~c2s2()
+ {
+ }
+
+ void c2s2::dump(char* _c2s2)
+ {
+ memcpy(_c2s2, random, 1504);
+ 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;
+
+ 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.");
+
+ memcpy(digest, _digest, 32);
+
return ret;
}
- srs_verbose("calc s1 digest success.");
- srs_assert(s1_digest != NULL);
- SrsAutoFree(char, s1_digest, true);
-
- if (schema == srs_schema0) {
- memcpy(block1.digest.digest, s1_digest, 32);
- } else {
- memcpy(block0.digest.digest, s1_digest, 32);
- }
- srs_verbose("copy s1 key success.");
-
- return ret;
-}
-
-int c1s1::calc_s1_digest(char*& digest)
-{
- int ret = ERROR_SUCCESS;
-
- srs_assert(schema == srs_schema0 || schema == srs_schema1);
-
- char* c1s1_joined_bytes = NULL;
-
- if (schema == srs_schema0) {
- c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest);
- } else {
- c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);
- }
-
- srs_assert(c1s1_joined_bytes != NULL);
- SrsAutoFree(char, c1s1_joined_bytes, true);
-
- digest = new char[OpensslHashSize];
- if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFMSKey, 36, digest)) != ERROR_SUCCESS) {
- srs_error("calc digest for s1 failed. ret=%d", 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;
}
- srs_verbose("digest calculated for s1");
- return ret;
-}
-
-int c1s1::calc_c1_digest(char*& digest)
-{
- int ret = ERROR_SUCCESS;
-
- srs_assert(schema == srs_schema0 || schema == srs_schema1);
-
- char* c1s1_joined_bytes = NULL;
-
- if (schema == srs_schema0) {
- c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest);
- } else {
- c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);
- }
-
- srs_assert(c1s1_joined_bytes != NULL);
- SrsAutoFree(char, c1s1_joined_bytes, true);
-
- digest = new char[OpensslHashSize];
- if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFPKey, 30, digest)) != ERROR_SUCCESS) {
- srs_error("calc digest for c1 failed. ret=%d", ret);
+ int c2s2::s2_create(c1s1* c1)
+ {
+ 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.");
+
+ memcpy(digest, _digest, 32);
+
return ret;
}
- srs_verbose("digest calculated for c1");
- return ret;
-}
-
-void c1s1::destroy_blocks()
-{
- if (schema == srs_schema_invalid) {
- return;
+ 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;
}
- if (schema == srs_schema0) {
- srs_key_block_free(&block0.key);
- srs_digest_block_free(&block1.digest);
- } else {
- srs_digest_block_free(&block0.digest);
- srs_key_block_free(&block1.key);
+ // TODO: FIXME: move to the right position.
+ c1s1::c1s1()
+ {
+ schema = srs_schema_invalid;
+ }
+ c1s1::~c1s1()
+ {
+ destroy_blocks();
+ }
+
+ char* c1s1::get_digest()
+ {
+ srs_assert(schema != srs_schema_invalid);
+
+ if (schema == srs_schema0) {
+ return block1.digest.digest;
+ } else {
+ return block0.digest.digest;
+ }
+ }
+
+ void c1s1::dump(char* _c1s1)
+ {
+ srs_assert(schema != srs_schema_invalid);
+
+ if (schema == srs_schema0) {
+ srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest);
+ } else {
+ srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key);
+ }
+ }
+
+ int c1s1::parse(char* _c1s1, srs_schema_type _schema)
+ {
+ int ret = ERROR_SUCCESS;
+
+ if (_schema == srs_schema_invalid) {
+ ret = ERROR_RTMP_CH_SCHEMA;
+ srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
+ return ret;
+ }
+
+ destroy_blocks();
+
+ time = *(int32_t*)_c1s1;
+ version = *(int32_t*)(_c1s1 + 4); // client c1 version
+
+ if (_schema == srs_schema0) {
+ if ((ret = srs_key_block_parse(&block0.key, _c1s1 + 8)) != ERROR_SUCCESS) {
+ srs_error("parse the c1 key failed. ret=%d", ret);
+ return ret;
+ }
+ if ((ret = srs_digest_block_parse(&block1.digest, _c1s1 + 8 + 764)) != ERROR_SUCCESS) {
+ srs_error("parse the c1 digest failed. ret=%d", ret);
+ return ret;
+ }
+ srs_verbose("parse c1 key-digest success");
+ } else if (_schema == srs_schema1) {
+ if ((ret = srs_digest_block_parse(&block0.digest, _c1s1 + 8)) != ERROR_SUCCESS) {
+ srs_error("parse the c1 key failed. ret=%d", ret);
+ return ret;
+ }
+ if ((ret = srs_key_block_parse(&block1.key, _c1s1 + 8 + 764)) != ERROR_SUCCESS) {
+ srs_error("parse the c1 digest failed. ret=%d", ret);
+ return ret;
+ }
+ srs_verbose("parse c1 digest-key success");
+ } else {
+ ret = ERROR_RTMP_CH_SCHEMA;
+ srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
+ return ret;
+ }
+
+ schema = _schema;
+
+ return ret;
+ }
+
+ int c1s1::c1_create(srs_schema_type _schema)
+ {
+ int ret = ERROR_SUCCESS;
+
+ if (_schema == srs_schema_invalid) {
+ ret = ERROR_RTMP_CH_SCHEMA;
+ srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret);
+ return ret;
+ }
+
+ destroy_blocks();
+
+ time = ::time(NULL);
+ version = 0x02070080; // client c1 version
+
+ if (_schema == srs_schema0) {
+ srs_key_block_init(&block0.key);
+ srs_digest_block_init(&block1.digest);
+ } else {
+ srs_digest_block_init(&block0.digest);
+ srs_key_block_init(&block1.key);
+ }
+
+ schema = _schema;
+
+ char* digest = NULL;
+
+ if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) {
+ srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
+ return ret;
+ }
+
+ srs_assert(digest != NULL);
+ SrsAutoFree(char, digest, true);
+
+ if (schema == srs_schema0) {
+ memcpy(block1.digest.digest, digest, 32);
+ } else {
+ memcpy(block0.digest.digest, digest, 32);
+ }
+
+ return ret;
+ }
+
+ int c1s1::c1_validate_digest(bool& is_valid)
+ {
+ is_valid = false;
+ int ret = ERROR_SUCCESS;
+
+ char* c1_digest = NULL;
+
+ if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) {
+ srs_error("validate c1 error, failed to calc digest. ret=%d", ret);
+ return ret;
+ }
+
+ srs_assert(c1_digest != NULL);
+ SrsAutoFree(char, c1_digest, true);
+
+ if (schema == srs_schema0) {
+ is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32);
+ } else {
+ is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32);
+ }
+
+ return ret;
+ }
+
+ int c1s1::s1_validate_digest(bool& is_valid)
+ {
+ is_valid = false;
+ int ret = ERROR_SUCCESS;
+
+ char* s1_digest = NULL;
+
+ if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {
+ srs_error("validate s1 error, failed to calc digest. ret=%d", ret);
+ return ret;
+ }
+
+ srs_assert(s1_digest != NULL);
+ SrsAutoFree(char, s1_digest, true);
+
+ if (schema == srs_schema0) {
+ is_valid = srs_bytes_equals(block1.digest.digest, s1_digest, 32);
+ } else {
+ is_valid = srs_bytes_equals(block0.digest.digest, s1_digest, 32);
+ }
+
+ return ret;
+ }
+
+ int c1s1::s1_create(c1s1* c1)
+ {
+ int ret = ERROR_SUCCESS;
+
+ if (c1->schema == srs_schema_invalid) {
+ ret = ERROR_RTMP_CH_SCHEMA;
+ srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret);
+ return ret;
+ }
+
+ destroy_blocks();
+ schema = c1->schema;
+
+ time = ::time(NULL);
+ version = 0x01000504; // server s1 version
+
+ if (schema == srs_schema0) {
+ srs_key_block_init(&block0.key);
+ srs_digest_block_init(&block1.digest);
+ } else {
+ srs_digest_block_init(&block0.digest);
+ srs_key_block_init(&block1.key);
+ }
+
+ if (schema == srs_schema0) {
+ if ((ret = openssl_generate_key(c1->block0.key.key, block0.key.key, 128)) != ERROR_SUCCESS) {
+ srs_error("calc s1 key failed. ret=%d", ret);
+ return ret;
+ }
+ } else {
+ if ((ret = openssl_generate_key(c1->block1.key.key, block1.key.key, 128)) != ERROR_SUCCESS) {
+ srs_error("calc s1 key failed. ret=%d", ret);
+ return ret;
+ }
+ }
+ srs_verbose("calc s1 key success.");
+
+ char* s1_digest = NULL;
+ if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {
+ srs_error("calc s1 digest failed. ret=%d", ret);
+ return ret;
+ }
+ srs_verbose("calc s1 digest success.");
+
+ srs_assert(s1_digest != NULL);
+ SrsAutoFree(char, s1_digest, true);
+
+ if (schema == srs_schema0) {
+ memcpy(block1.digest.digest, s1_digest, 32);
+ } else {
+ memcpy(block0.digest.digest, s1_digest, 32);
+ }
+ srs_verbose("copy s1 key success.");
+
+ return ret;
+ }
+
+ int c1s1::calc_s1_digest(char*& digest)
+ {
+ int ret = ERROR_SUCCESS;
+
+ srs_assert(schema == srs_schema0 || schema == srs_schema1);
+
+ char* c1s1_joined_bytes = NULL;
+
+ if (schema == srs_schema0) {
+ c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest);
+ } else {
+ c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);
+ }
+
+ srs_assert(c1s1_joined_bytes != NULL);
+ SrsAutoFree(char, c1s1_joined_bytes, true);
+
+ digest = new char[OpensslHashSize];
+ if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFMSKey, 36, digest)) != ERROR_SUCCESS) {
+ srs_error("calc digest for s1 failed. ret=%d", ret);
+ return ret;
+ }
+ srs_verbose("digest calculated for s1");
+
+ return ret;
+ }
+
+ int c1s1::calc_c1_digest(char*& digest)
+ {
+ int ret = ERROR_SUCCESS;
+
+ srs_assert(schema == srs_schema0 || schema == srs_schema1);
+
+ char* c1s1_joined_bytes = NULL;
+
+ if (schema == srs_schema0) {
+ c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest);
+ } else {
+ c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);
+ }
+
+ srs_assert(c1s1_joined_bytes != NULL);
+ SrsAutoFree(char, c1s1_joined_bytes, true);
+
+ digest = new char[OpensslHashSize];
+ if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFPKey, 30, digest)) != ERROR_SUCCESS) {
+ srs_error("calc digest for c1 failed. ret=%d", ret);
+ return ret;
+ }
+ srs_verbose("digest calculated for c1");
+
+ return ret;
+ }
+
+ void c1s1::destroy_blocks()
+ {
+ if (schema == srs_schema_invalid) {
+ return;
+ }
+
+ if (schema == srs_schema0) {
+ srs_key_block_free(&block0.key);
+ srs_digest_block_free(&block1.digest);
+ } else {
+ srs_digest_block_free(&block0.digest);
+ srs_key_block_free(&block1.key);
+ }
}
}
@@ -1144,13 +1164,10 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
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.");
+ // never verify c2, for ffmpeg will failed.
+ // it's ok for flash.
srs_trace("comple handshake with client success");
diff --git a/trunk/src/rtmp/srs_protocol_handshake.hpp b/trunk/src/rtmp/srs_protocol_handshake.hpp
index 4ac93e624..05b29482f 100644
--- a/trunk/src/rtmp/srs_protocol_handshake.hpp
+++ b/trunk/src/rtmp/srs_protocol_handshake.hpp
@@ -97,6 +97,78 @@ namespace srs
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
* time: 4bytes
@@ -236,41 +308,14 @@ namespace srs
*/
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
/**
-* 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
{
diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp
index 1a223dedd..6171a1bd5 100644
--- a/trunk/src/utest/srs_utest.cpp
+++ b/trunk/src/utest/srs_utest.cpp
@@ -36,6 +36,77 @@ ISrsThreadContext* _srs_context = new ISrsThreadContext();
SrsConfig* _srs_config = 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.
VOID TEST(SampleTest, FastSampleInt64Test)
{
diff --git a/trunk/src/utest/srs_utest.hpp b/trunk/src/utest/srs_utest.hpp
index c36add338..6b1ccf87d 100644
--- a/trunk/src/utest/srs_utest.hpp
+++ b/trunk/src/utest/srs_utest.hpp
@@ -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.
#define VOID
+#include
+
+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
diff --git a/trunk/src/utest/srs_utest_handshake.cpp b/trunk/src/utest/srs_utest_handshake.cpp
index 2e005b512..e14016911 100644
--- a/trunk/src/utest/srs_utest_handshake.cpp
+++ b/trunk/src/utest/srs_utest_handshake.cpp
@@ -24,77 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include
#include
-
-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;
-}
+#include
// verify the sha256
VOID TEST(HandshakeTest, OpensslSha256)
@@ -124,6 +54,37 @@ VOID TEST(HandshakeTest, OpensslSha256)
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.
VOID TEST(HandshakeTest, VerifyFPC0C1)
{
@@ -172,7 +133,7 @@ VOID TEST(HandshakeTest, VerifyFPC0C1)
0xb1, 0xb5, 0xbc, 0xa6, 0xd6, 0xd6, 0x1d, 0xce, 0x93, 0x78, 0xb3, 0xec, 0xa8, 0x64, 0x19, 0x13
};
EXPECT_TRUE(srs_bytes_equals(c1.block1.digest.digest, digest, 32));
-}
+}
VOID TEST(HandshakeTest, SimpleHandshake)
{
@@ -260,3 +221,19 @@ VOID TEST(HandshakeTest, ComplexHandshake)
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));
+}
diff --git a/trunk/src/utest/srs_utest_handshake.hpp b/trunk/src/utest/srs_utest_handshake.hpp
index d45e9337d..81e46dd97 100644
--- a/trunk/src/utest/srs_utest_handshake.hpp
+++ b/trunk/src/utest/srs_utest_handshake.hpp
@@ -29,39 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include
-#include
#include
#include
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