winlin

for bug #235, use strategy to implements the schema0 and schema1.

@@ -638,6 +638,385 @@ namespace _srs_internal @@ -638,6 +638,385 @@ namespace _srs_internal
638 return bytes; 638 return bytes;
639 } 639 }
640 640
  641 + c1s1_strategy::c1s1_strategy()
  642 + {
  643 + }
  644 +
  645 + c1s1_strategy::~c1s1_strategy()
  646 + {
  647 + }
  648 +
  649 + c1s1_strategy_schema0::c1s1_strategy_schema0()
  650 + {
  651 + key.init();
  652 + digest.init();
  653 + }
  654 +
  655 + c1s1_strategy_schema0::~c1s1_strategy_schema0()
  656 + {
  657 + key.free();
  658 + digest.free();
  659 + }
  660 +
  661 + srs_schema_type c1s1_strategy_schema0::schema()
  662 + {
  663 + return srs_schema0;
  664 + }
  665 +
  666 + char* c1s1_strategy_schema0::get_digest()
  667 + {
  668 + return digest.digest;
  669 + }
  670 +
  671 + void c1s1_strategy_schema0::dump(c1s1* owner, char* _c1s1)
  672 + {
  673 + srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest);
  674 + }
  675 +
  676 + int c1s1_strategy_schema0::parse(char* _c1s1)
  677 + {
  678 + int ret = ERROR_SUCCESS;
  679 +
  680 + if ((ret = key.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
  681 + srs_error("parse the c1 key failed. ret=%d", ret);
  682 + return ret;
  683 + }
  684 +
  685 + if ((ret = digest.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {
  686 + srs_error("parse the c1 digest failed. ret=%d", ret);
  687 + return ret;
  688 + }
  689 +
  690 + srs_verbose("parse c1 key-digest success");
  691 +
  692 + return ret;
  693 + }
  694 +
  695 + int c1s1_strategy_schema0::c1_create(c1s1* owner)
  696 + {
  697 + int ret = ERROR_SUCCESS;
  698 +
  699 + // generate digest
  700 + char* c1_digest = NULL;
  701 +
  702 + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
  703 + srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
  704 + return ret;
  705 + }
  706 +
  707 + srs_assert(c1_digest != NULL);
  708 + SrsAutoFree(char, c1_digest);
  709 +
  710 + memcpy(digest.digest, c1_digest, 32);
  711 +
  712 + return ret;
  713 + }
  714 +
  715 + int c1s1_strategy_schema0::c1_validate_digest(c1s1* owner, bool& is_valid)
  716 + {
  717 + int ret = ERROR_SUCCESS;
  718 +
  719 + char* c1_digest = NULL;
  720 +
  721 + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
  722 + srs_error("validate c1 error, failed to calc digest. ret=%d", ret);
  723 + return ret;
  724 + }
  725 +
  726 + srs_assert(c1_digest != NULL);
  727 + SrsAutoFree(char, c1_digest);
  728 +
  729 + is_valid = srs_bytes_equals(digest.digest, c1_digest, 32);
  730 +
  731 + return ret;
  732 + }
  733 +
  734 + int c1s1_strategy_schema0::s1_create(c1s1* owner)
  735 + {
  736 + int ret = ERROR_SUCCESS;
  737 +
  738 + SrsDH dh;
  739 +
  740 + // ensure generate 128bytes public key.
  741 + if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {
  742 + return ret;
  743 + }
  744 +
  745 + // directly generate the public key.
  746 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
  747 + int pkey_size = 128;
  748 + // TODO: FIXME: use c1 public key to calc the shared key.
  749 + if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) {
  750 + srs_error("calc s1 key failed. ret=%d", ret);
  751 + return ret;
  752 + }
  753 + srs_assert(pkey_size == 128);
  754 + srs_verbose("calc s1 key success.");
  755 +
  756 + char* s1_digest = NULL;
  757 + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {
  758 + srs_error("calc s1 digest failed. ret=%d", ret);
  759 + return ret;
  760 + }
  761 + srs_verbose("calc s1 digest success.");
  762 +
  763 + srs_assert(s1_digest != NULL);
  764 + SrsAutoFree(char, s1_digest);
  765 +
  766 + memcpy(digest.digest, s1_digest, 32);
  767 + srs_verbose("copy s1 key success.");
  768 +
  769 + return ret;
  770 + }
  771 +
  772 + int c1s1_strategy_schema0::s1_validate_digest(c1s1* owner, bool& is_valid)
  773 + {
  774 + int ret = ERROR_SUCCESS;
  775 +
  776 + char* s1_digest = NULL;
  777 +
  778 + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {
  779 + srs_error("validate s1 error, failed to calc digest. ret=%d", ret);
  780 + return ret;
  781 + }
  782 +
  783 + srs_assert(s1_digest != NULL);
  784 + SrsAutoFree(char, s1_digest);
  785 +
  786 + is_valid = srs_bytes_equals(digest.digest, s1_digest, 32);
  787 +
  788 + return ret;
  789 + }
  790 +
  791 + int c1s1_strategy_schema0::calc_c1_digest(c1s1* owner, char*& c1_digest)
  792 + {
  793 + int ret = ERROR_SUCCESS;
  794 +
  795 + char* c1s1_joined_bytes = NULL;
  796 +
  797 + c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest);
  798 +
  799 + srs_assert(c1s1_joined_bytes != NULL);
  800 + SrsAutoFree(char, c1s1_joined_bytes);
  801 +
  802 + c1_digest = new char[__SRS_OpensslHashSize];
  803 + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) {
  804 + srs_freep(c1_digest);
  805 + srs_error("calc digest for c1 failed. ret=%d", ret);
  806 + return ret;
  807 + }
  808 + srs_verbose("digest calculated for c1");
  809 +
  810 + return ret;
  811 + }
  812 +
  813 + int c1s1_strategy_schema0::calc_s1_digest(c1s1* owner, char*& s1_digest)
  814 + {
  815 + int ret = ERROR_SUCCESS;
  816 +
  817 + char* c1s1_joined_bytes = NULL;
  818 +
  819 + c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest);
  820 +
  821 + srs_assert(c1s1_joined_bytes != NULL);
  822 + SrsAutoFree(char, c1s1_joined_bytes);
  823 +
  824 + s1_digest = new char[__SRS_OpensslHashSize];
  825 + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) {
  826 + srs_freep(s1_digest);
  827 + srs_error("calc digest for s1 failed. ret=%d", ret);
  828 + return ret;
  829 + }
  830 + srs_verbose("digest calculated for s1");
  831 +
  832 + return ret;
  833 + }
  834 +
  835 + c1s1_strategy_schema1::c1s1_strategy_schema1()
  836 + {
  837 + key.init();
  838 + digest.init();
  839 + }
  840 +
  841 + c1s1_strategy_schema1::~c1s1_strategy_schema1()
  842 + {
  843 + key.free();
  844 + digest.free();
  845 + }
  846 +
  847 + srs_schema_type c1s1_strategy_schema1::schema()
  848 + {
  849 + return srs_schema1;
  850 + }
  851 +
  852 + char* c1s1_strategy_schema1::get_digest()
  853 + {
  854 + return digest.digest;
  855 + }
  856 +
  857 + void c1s1_strategy_schema1::dump(c1s1* owner, char* _c1s1)
  858 + {
  859 + srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest);
  860 + }
  861 +
  862 + int c1s1_strategy_schema1::parse(char* _c1s1)
  863 + {
  864 + int ret = ERROR_SUCCESS;
  865 +
  866 + if ((ret = digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
  867 + srs_error("parse the c1 digest failed. ret=%d", ret);
  868 + return ret;
  869 + }
  870 +
  871 + if ((ret = key.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {
  872 + srs_error("parse the c1 key failed. ret=%d", ret);
  873 + return ret;
  874 + }
  875 +
  876 + srs_verbose("parse c1 digest-key success");
  877 +
  878 + return ret;
  879 + }
  880 +
  881 + int c1s1_strategy_schema1::c1_create(c1s1* owner)
  882 + {
  883 + int ret = ERROR_SUCCESS;
  884 +
  885 + // generate digest
  886 + char* c1_digest = NULL;
  887 +
  888 + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
  889 + srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
  890 + return ret;
  891 + }
  892 +
  893 + srs_assert(c1_digest != NULL);
  894 + SrsAutoFree(char, c1_digest);
  895 +
  896 + memcpy(digest.digest, c1_digest, 32);
  897 +
  898 + return ret;
  899 + }
  900 +
  901 + int c1s1_strategy_schema1::c1_validate_digest(c1s1* owner, bool& is_valid)
  902 + {
  903 + int ret = ERROR_SUCCESS;
  904 +
  905 + char* c1_digest = NULL;
  906 +
  907 + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
  908 + srs_error("validate c1 error, failed to calc digest. ret=%d", ret);
  909 + return ret;
  910 + }
  911 +
  912 + srs_assert(c1_digest != NULL);
  913 + SrsAutoFree(char, c1_digest);
  914 +
  915 + is_valid = srs_bytes_equals(digest.digest, c1_digest, 32);
  916 +
  917 + return ret;
  918 + }
  919 +
  920 + int c1s1_strategy_schema1::s1_create(c1s1* owner)
  921 + {
  922 + int ret = ERROR_SUCCESS;
  923 +
  924 + SrsDH dh;
  925 +
  926 + // ensure generate 128bytes public key.
  927 + if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {
  928 + return ret;
  929 + }
  930 +
  931 + // directly generate the public key.
  932 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
  933 + int pkey_size = 128;
  934 + if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) {
  935 + srs_error("calc s1 key failed. ret=%d", ret);
  936 + return ret;
  937 + }
  938 + srs_assert(pkey_size == 128);
  939 + srs_verbose("calc s1 key success.");
  940 +
  941 + char* s1_digest = NULL;
  942 + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {
  943 + srs_error("calc s1 digest failed. ret=%d", ret);
  944 + return ret;
  945 + }
  946 + srs_verbose("calc s1 digest success.");
  947 +
  948 + srs_assert(s1_digest != NULL);
  949 + SrsAutoFree(char, s1_digest);
  950 +
  951 + memcpy(digest.digest, s1_digest, 32);
  952 + srs_verbose("copy s1 key success.");
  953 +
  954 + return ret;
  955 + }
  956 +
  957 + int c1s1_strategy_schema1::s1_validate_digest(c1s1* owner, bool& is_valid)
  958 + {
  959 + int ret = ERROR_SUCCESS;
  960 +
  961 + char* s1_digest = NULL;
  962 +
  963 + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {
  964 + srs_error("validate s1 error, failed to calc digest. ret=%d", ret);
  965 + return ret;
  966 + }
  967 +
  968 + srs_assert(s1_digest != NULL);
  969 + SrsAutoFree(char, s1_digest);
  970 +
  971 + is_valid = srs_bytes_equals(digest.digest, s1_digest, 32);
  972 +
  973 + return ret;
  974 + }
  975 +
  976 + int c1s1_strategy_schema1::calc_c1_digest(c1s1* owner, char*& c1_digest)
  977 + {
  978 + int ret = ERROR_SUCCESS;
  979 +
  980 + char* c1s1_joined_bytes = NULL;
  981 +
  982 + c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key);
  983 +
  984 + srs_assert(c1s1_joined_bytes != NULL);
  985 + SrsAutoFree(char, c1s1_joined_bytes);
  986 +
  987 + c1_digest = new char[__SRS_OpensslHashSize];
  988 + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) {
  989 + srs_freep(c1_digest);
  990 + srs_error("calc digest for c1 failed. ret=%d", ret);
  991 + return ret;
  992 + }
  993 + srs_verbose("digest calculated for c1");
  994 +
  995 + return ret;
  996 + }
  997 +
  998 + int c1s1_strategy_schema1::calc_s1_digest(c1s1* owner, char*& s1_digest)
  999 + {
  1000 + int ret = ERROR_SUCCESS;
  1001 +
  1002 + char* c1s1_joined_bytes = NULL;
  1003 +
  1004 + c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key);
  1005 +
  1006 + srs_assert(c1s1_joined_bytes != NULL);
  1007 + SrsAutoFree(char, c1s1_joined_bytes);
  1008 +
  1009 + s1_digest = new char[__SRS_OpensslHashSize];
  1010 + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) {
  1011 + srs_freep(s1_digest);
  1012 + srs_error("calc digest for s1 failed. ret=%d", ret);
  1013 + return ret;
  1014 + }
  1015 + srs_verbose("digest calculated for s1");
  1016 +
  1017 + return ret;
  1018 + }
  1019 +
641 c2s2::c2s2() 1020 c2s2::c2s2()
642 { 1021 {
643 srs_random_generate(random, 1504); 1022 srs_random_generate(random, 1504);
@@ -762,314 +1141,129 @@ namespace _srs_internal @@ -762,314 +1141,129 @@ namespace _srs_internal
762 // TODO: FIXME: move to the right position. 1141 // TODO: FIXME: move to the right position.
763 c1s1::c1s1() 1142 c1s1::c1s1()
764 { 1143 {
765 - schema = srs_schema_invalid; 1144 + payload = NULL;
766 } 1145 }
767 c1s1::~c1s1() 1146 c1s1::~c1s1()
768 { 1147 {
769 - destroy_blocks(); 1148 + srs_freep(payload);
  1149 + /*
  1150 + void c1s1::destroy_blocks()
  1151 + {
  1152 + if (schema == srs_schema_invalid) {
  1153 + return;
  1154 + }
  1155 +
  1156 + if (schema == srs_schema0) {
  1157 + block0.key.free();
  1158 + block1.digest.free();
  1159 + } else {
  1160 + block0.digest.free();
  1161 + block1.key.free();
  1162 + }
  1163 + }*/
  1164 + }
  1165 +
  1166 + srs_schema_type c1s1::schema()
  1167 + {
  1168 + srs_assert(payload != NULL);
  1169 + return payload->schema();
770 } 1170 }
771 1171
772 char* c1s1::get_digest() 1172 char* c1s1::get_digest()
773 { 1173 {
774 - srs_assert(schema != srs_schema_invalid);  
775 -  
776 - if (schema == srs_schema0) {  
777 - return block1.digest.digest;  
778 - } else {  
779 - return block0.digest.digest;  
780 - } 1174 + srs_assert(payload != NULL);
  1175 + return payload->get_digest();
781 } 1176 }
782 1177
783 void c1s1::dump(char* _c1s1) 1178 void c1s1::dump(char* _c1s1)
784 { 1179 {
785 - srs_assert(schema != srs_schema_invalid);  
786 -  
787 - if (schema == srs_schema0) {  
788 - srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest);  
789 - } else {  
790 - srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key);  
791 - } 1180 + srs_assert(payload != NULL);
  1181 + return payload->dump(this, _c1s1);
792 } 1182 }
793 1183
794 - int c1s1::parse(char* _c1s1, srs_schema_type _schema) 1184 + int c1s1::parse(char* _c1s1, srs_schema_type schema)
795 { 1185 {
796 int ret = ERROR_SUCCESS; 1186 int ret = ERROR_SUCCESS;
797 1187
798 - if (_schema == srs_schema_invalid) { 1188 + if (schema != srs_schema0 && schema != srs_schema1) {
799 ret = ERROR_RTMP_CH_SCHEMA; 1189 ret = ERROR_RTMP_CH_SCHEMA;
800 - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); 1190 + srs_error("parse c1 failed. invalid schema=%d, ret=%d", schema, ret);
801 return ret; 1191 return ret;
802 } 1192 }
803 1193
804 - destroy_blocks();  
805 -  
806 -  
807 time = __srs_stream_read_4bytes(_c1s1); 1194 time = __srs_stream_read_4bytes(_c1s1);
808 version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version 1195 version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version
809 1196
810 - if (_schema == srs_schema0) {  
811 - if ((ret = block0.key.parse(_c1s1 + 8)) != ERROR_SUCCESS) {  
812 - srs_error("parse the c1 key failed. ret=%d", ret);  
813 - return ret;  
814 - }  
815 - if ((ret = block1.digest.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {  
816 - srs_error("parse the c1 digest failed. ret=%d", ret);  
817 - return ret;  
818 - }  
819 - srs_verbose("parse c1 key-digest success");  
820 - } else if (_schema == srs_schema1) {  
821 - if ((ret = block0.digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) {  
822 - srs_error("parse the c1 key failed. ret=%d", ret);  
823 - return ret;  
824 - }  
825 - if ((ret = block1.key.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {  
826 - srs_error("parse the c1 digest failed. ret=%d", ret);  
827 - return ret;  
828 - }  
829 - srs_verbose("parse c1 digest-key success"); 1197 + srs_freep(payload);
  1198 + if (schema == srs_schema0) {
  1199 + payload = new c1s1_strategy_schema0();
830 } else { 1200 } else {
831 - ret = ERROR_RTMP_CH_SCHEMA;  
832 - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);  
833 - return ret; 1201 + payload = new c1s1_strategy_schema1();
834 } 1202 }
835 -  
836 - schema = _schema;  
837 -  
838 - return ret; 1203 +
  1204 + return payload->parse(_c1s1);
839 } 1205 }
840 1206
841 - int c1s1::c1_create(srs_schema_type _schema) 1207 + int c1s1::c1_create(srs_schema_type schema)
842 { 1208 {
843 int ret = ERROR_SUCCESS; 1209 int ret = ERROR_SUCCESS;
844 1210
845 - if (_schema == srs_schema_invalid) { 1211 + if (schema != srs_schema0 && schema != srs_schema1) {
846 ret = ERROR_RTMP_CH_SCHEMA; 1212 ret = ERROR_RTMP_CH_SCHEMA;
847 - srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret); 1213 + srs_error("create c1 failed. invalid schema=%d, ret=%d", schema, ret);
848 return ret; 1214 return ret;
849 } 1215 }
850 1216
851 - destroy_blocks();  
852 -  
853 // client c1 time and version 1217 // client c1 time and version
854 time = ::time(NULL); 1218 time = ::time(NULL);
855 version = 0x80000702; // client c1 version 1219 version = 0x80000702; // client c1 version
856 - 1220 +
857 // generate signature by schema 1221 // generate signature by schema
858 - if (_schema == srs_schema0) {  
859 - block0.key.init();  
860 - block1.digest.init();  
861 - } else {  
862 - block0.digest.init();  
863 - block1.key.init();  
864 - }  
865 -  
866 - schema = _schema;  
867 -  
868 - // generate digest  
869 - char* digest = NULL;  
870 -  
871 - if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) {  
872 - srs_error("sign c1 error, failed to calc digest. ret=%d", ret);  
873 - return ret;  
874 - }  
875 -  
876 - srs_assert(digest != NULL);  
877 - SrsAutoFree(char, digest);  
878 - 1222 + srs_freep(payload);
879 if (schema == srs_schema0) { 1223 if (schema == srs_schema0) {
880 - memcpy(block1.digest.digest, digest, 32); 1224 + payload = new c1s1_strategy_schema0();
881 } else { 1225 } else {
882 - memcpy(block0.digest.digest, digest, 32); 1226 + payload = new c1s1_strategy_schema1();
883 } 1227 }
884 1228
885 - return ret; 1229 + return payload->c1_create(this);
886 } 1230 }
887 1231
888 int c1s1::c1_validate_digest(bool& is_valid) 1232 int c1s1::c1_validate_digest(bool& is_valid)
889 { 1233 {
890 is_valid = false; 1234 is_valid = false;
891 - int ret = ERROR_SUCCESS;  
892 -  
893 - char* c1_digest = NULL;  
894 -  
895 - if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) {  
896 - srs_error("validate c1 error, failed to calc digest. ret=%d", ret);  
897 - return ret;  
898 - }  
899 -  
900 - srs_assert(c1_digest != NULL);  
901 - SrsAutoFree(char, c1_digest);  
902 -  
903 - if (schema == srs_schema0) {  
904 - is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32);  
905 - } else {  
906 - is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32);  
907 - }  
908 -  
909 - return ret; 1235 + srs_assert(payload);
  1236 + return payload->c1_validate_digest(this, is_valid);
910 } 1237 }
911 1238
912 int c1s1::s1_validate_digest(bool& is_valid) 1239 int c1s1::s1_validate_digest(bool& is_valid)
913 { 1240 {
914 is_valid = false; 1241 is_valid = false;
915 - int ret = ERROR_SUCCESS;  
916 -  
917 - char* s1_digest = NULL;  
918 -  
919 - if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {  
920 - srs_error("validate s1 error, failed to calc digest. ret=%d", ret);  
921 - return ret;  
922 - }  
923 -  
924 - srs_assert(s1_digest != NULL);  
925 - SrsAutoFree(char, s1_digest);  
926 -  
927 - if (schema == srs_schema0) {  
928 - is_valid = srs_bytes_equals(block1.digest.digest, s1_digest, 32);  
929 - } else {  
930 - is_valid = srs_bytes_equals(block0.digest.digest, s1_digest, 32);  
931 - }  
932 -  
933 - return ret; 1242 + srs_assert(payload);
  1243 + return payload->s1_validate_digest(this, is_valid);
934 } 1244 }
935 1245
936 int c1s1::s1_create(c1s1* c1) 1246 int c1s1::s1_create(c1s1* c1)
937 { 1247 {
938 int ret = ERROR_SUCCESS; 1248 int ret = ERROR_SUCCESS;
939 1249
940 - if (c1->schema == srs_schema_invalid) { 1250 + if (c1->schema() != srs_schema0 && c1->schema() != srs_schema1) {
941 ret = ERROR_RTMP_CH_SCHEMA; 1251 ret = ERROR_RTMP_CH_SCHEMA;
942 - srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret); 1252 + srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema(), ret);
943 return ret; 1253 return ret;
944 } 1254 }
945 1255
946 - destroy_blocks();  
947 - schema = c1->schema;  
948 -  
949 time = ::time(NULL); 1256 time = ::time(NULL);
950 version = 0x01000504; // server s1 version 1257 version = 0x01000504; // server s1 version
951 1258
952 - SrsDH dh;  
953 -  
954 - // ensure generate 128bytes public key.  
955 - if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {  
956 - return ret;  
957 - }  
958 -  
959 - if (schema == srs_schema0) {  
960 - block0.key.init();  
961 - block1.digest.init();  
962 -  
963 - // directly generate the public key.  
964 - // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148  
965 - int pkey_size = 128;  
966 - if ((ret = dh.copy_public_key(block0.key.key, pkey_size)) != ERROR_SUCCESS) {  
967 - srs_error("calc s1 key failed. ret=%d", ret);  
968 - return ret;  
969 - }  
970 - srs_assert(pkey_size == 128);  
971 - } else {  
972 - block0.digest.init();  
973 - block1.key.init();  
974 -  
975 - // directly generate the public key.  
976 - // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148  
977 - int pkey_size = 128;  
978 - if ((ret = dh.copy_public_key(block1.key.key, pkey_size)) != ERROR_SUCCESS) {  
979 - srs_error("calc s1 key failed. ret=%d", ret);  
980 - return ret;  
981 - }  
982 - srs_assert(pkey_size == 128);  
983 - }  
984 - srs_verbose("calc s1 key success.");  
985 -  
986 - char* s1_digest = NULL;  
987 - if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) {  
988 - srs_error("calc s1 digest failed. ret=%d", ret);  
989 - return ret;  
990 - }  
991 - srs_verbose("calc s1 digest success.");  
992 -  
993 - srs_assert(s1_digest != NULL);  
994 - SrsAutoFree(char, s1_digest);  
995 -  
996 - if (schema == srs_schema0) {  
997 - memcpy(block1.digest.digest, s1_digest, 32);  
998 - } else {  
999 - memcpy(block0.digest.digest, s1_digest, 32);  
1000 - }  
1001 - srs_verbose("copy s1 key success.");  
1002 -  
1003 - return ret;  
1004 - }  
1005 -  
1006 - int c1s1::calc_s1_digest(char*& digest)  
1007 - {  
1008 - int ret = ERROR_SUCCESS;  
1009 -  
1010 - srs_assert(schema == srs_schema0 || schema == srs_schema1);  
1011 -  
1012 - char* c1s1_joined_bytes = NULL;  
1013 -  
1014 - if (schema == srs_schema0) {  
1015 - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); 1259 + srs_freep(payload);
  1260 + if (c1->schema() == srs_schema0) {
  1261 + payload = new c1s1_strategy_schema0();
1016 } else { 1262 } else {
1017 - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);  
1018 - }  
1019 -  
1020 - srs_assert(c1s1_joined_bytes != NULL);  
1021 - SrsAutoFree(char, c1s1_joined_bytes);  
1022 -  
1023 - digest = new char[__SRS_OpensslHashSize];  
1024 - if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) {  
1025 - srs_error("calc digest for s1 failed. ret=%d", ret);  
1026 - return ret; 1263 + payload = new c1s1_strategy_schema1();
1027 } 1264 }
1028 - srs_verbose("digest calculated for s1");  
1029 1265
1030 - return ret;  
1031 - }  
1032 -  
1033 - int c1s1::calc_c1_digest(char*& digest)  
1034 - {  
1035 - int ret = ERROR_SUCCESS;  
1036 -  
1037 - srs_assert(schema == srs_schema0 || schema == srs_schema1);  
1038 -  
1039 - char* c1s1_joined_bytes = NULL;  
1040 -  
1041 - if (schema == srs_schema0) {  
1042 - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest);  
1043 - } else {  
1044 - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key);  
1045 - }  
1046 -  
1047 - srs_assert(c1s1_joined_bytes != NULL);  
1048 - SrsAutoFree(char, c1s1_joined_bytes);  
1049 -  
1050 - digest = new char[__SRS_OpensslHashSize];  
1051 - if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) {  
1052 - srs_error("calc digest for c1 failed. ret=%d", ret);  
1053 - return ret;  
1054 - }  
1055 - srs_verbose("digest calculated for c1");  
1056 -  
1057 - return ret;  
1058 - }  
1059 -  
1060 - void c1s1::destroy_blocks()  
1061 - {  
1062 - if (schema == srs_schema_invalid) {  
1063 - return;  
1064 - }  
1065 -  
1066 - if (schema == srs_schema0) {  
1067 - block0.key.free();  
1068 - block1.digest.free();  
1069 - } else {  
1070 - block0.digest.free();  
1071 - block1.key.free();  
1072 - } 1266 + return payload->s1_create(this);
1073 } 1267 }
1074 } 1268 }
1075 1269
@@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs @@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
1190 // decode c1 1384 // decode c1
1191 c1s1 c1; 1385 c1s1 c1;
1192 // try schema0. 1386 // try schema0.
  1387 + // @remark, use schema0 to make flash player happy.
1193 if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) { 1388 if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) {
1194 srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); 1389 srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret);
1195 return ret; 1390 return ret;
@@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs @@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
1197 // try schema1 1392 // try schema1
1198 bool is_valid = false; 1393 bool is_valid = false;
1199 if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { 1394 if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
  1395 + srs_info("schema0 failed, try schema1.");
1200 if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) { 1396 if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) {
1201 srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); 1397 srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret);
1202 return ret; 1398 return ret;
@@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs @@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
1207 srs_info("all schema valid failed, try simple handshake. ret=%d", ret); 1403 srs_info("all schema valid failed, try simple handshake. ret=%d", ret);
1208 return ret; 1404 return ret;
1209 } 1405 }
  1406 + } else {
  1407 + srs_info("schema0 is ok.");
1210 } 1408 }
1211 srs_verbose("decode c1 success."); 1409 srs_verbose("decode c1 success.");
1212 1410
@@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs @@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs
1321 1519
1322 // verify s1s2 1520 // verify s1s2
1323 c1s1 s1; 1521 c1s1 s1;
1324 - if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema)) != ERROR_SUCCESS) { 1522 + if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema())) != ERROR_SUCCESS) {
1325 return ret; 1523 return ret;
1326 } 1524 }
1327 1525
@@ -219,6 +219,121 @@ namespace _srs_internal @@ -219,6 +219,121 @@ namespace _srs_internal
219 */ 219 */
220 char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key); 220 char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
221 221
  222 + class c1s1;
  223 +
  224 + /**
  225 + * the c1s1 strategy, use schema0 or schema1.
  226 + * the template method class to defines common behaviors,
  227 + * while the concrete class to implements in schema0 or schema1.
  228 + */
  229 + class c1s1_strategy
  230 + {
  231 + public:
  232 + c1s1_strategy();
  233 + virtual ~c1s1_strategy();
  234 + public:
  235 + /**
  236 + * get the scema.
  237 + */
  238 + virtual srs_schema_type schema() = 0;
  239 + /**
  240 + * get the digest key.
  241 + */
  242 + virtual char* get_digest() = 0;
  243 + /**
  244 + * copy to bytes.
  245 + */
  246 + virtual void dump(c1s1* owner, char* _c1s1) = 0;
  247 + /**
  248 + * server: parse the c1s1, discovery the key and digest by schema.
  249 + * use the c1_validate_digest() to valid the digest of c1.
  250 + */
  251 + virtual int parse(char* _c1s1) = 0;
  252 + public:
  253 + /**
  254 + * client: create and sign c1 by schema.
  255 + * sign the c1, generate the digest.
  256 + * calc_c1_digest(c1, schema) {
  257 + * get c1s1-joined from c1 by specified schema
  258 + * digest-data = HMACsha256(c1s1-joined, FPKey, 30)
  259 + * return digest-data;
  260 + * }
  261 + * random fill 1536bytes c1 // also fill the c1-128bytes-key
  262 + * time = time() // c1[0-3]
  263 + * version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
  264 + * schema = choose schema0 or schema1
  265 + * digest-data = calc_c1_digest(c1, schema)
  266 + * copy digest-data to c1
  267 + */
  268 + virtual int c1_create(c1s1* owner) = 0;
  269 + /**
  270 + * server: validate the parsed c1 schema
  271 + */
  272 + virtual int c1_validate_digest(c1s1* owner, bool& is_valid) = 0;
  273 + /**
  274 + * server: create and sign the s1 from c1.
  275 + */
  276 + virtual int s1_create(c1s1* owner) = 0;
  277 + /**
  278 + * server: validate the parsed s1 schema
  279 + */
  280 + virtual int s1_validate_digest(c1s1* owner, bool& is_valid) = 0;
  281 + };
  282 +
  283 + /**
  284 + * c1s1 schema0
  285 + * key: 764bytes
  286 + * digest: 764bytes
  287 + */
  288 + class c1s1_strategy_schema0 : public c1s1_strategy
  289 + {
  290 + private:
  291 + key_block key;
  292 + digest_block digest;
  293 + public:
  294 + c1s1_strategy_schema0();
  295 + virtual ~c1s1_strategy_schema0();
  296 + public:
  297 + virtual srs_schema_type schema();
  298 + virtual char* get_digest();
  299 + virtual void dump(c1s1* owner, char* _c1s1);
  300 + virtual int parse(char* _c1s1);
  301 + virtual int c1_create(c1s1* owner);
  302 + virtual int c1_validate_digest(c1s1* owner, bool& is_valid);
  303 + virtual int s1_create(c1s1* owner);
  304 + virtual int s1_validate_digest(c1s1* owner, bool& is_valid);
  305 + private:
  306 + virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);
  307 + virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);
  308 + };
  309 +
  310 + /**
  311 + * c1s1 schema1
  312 + * digest: 764bytes
  313 + * key: 764bytes
  314 + */
  315 + class c1s1_strategy_schema1 : public c1s1_strategy
  316 + {
  317 + private:
  318 + digest_block digest;
  319 + key_block key;
  320 + public:
  321 + c1s1_strategy_schema1();
  322 + virtual ~c1s1_strategy_schema1();
  323 + public:
  324 + virtual srs_schema_type schema();
  325 + virtual char* get_digest();
  326 + virtual void dump(c1s1* owner, char* _c1s1);
  327 + virtual int parse(char* _c1s1);
  328 + virtual int c1_create(c1s1* owner);
  329 + virtual int c1_validate_digest(c1s1* owner, bool& is_valid);
  330 + virtual int s1_create(c1s1* owner);
  331 + virtual int s1_validate_digest(c1s1* owner, bool& is_valid);
  332 + private:
  333 + virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);
  334 + virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);
  335 + };
  336 +
222 /** 337 /**
223 * c1s1 schema0 338 * c1s1 schema0
224 * time: 4bytes 339 * time: 4bytes
@@ -235,30 +350,20 @@ namespace _srs_internal @@ -235,30 +350,20 @@ namespace _srs_internal
235 class c1s1 350 class c1s1
236 { 351 {
237 public: 352 public:
238 - union block {  
239 - key_block key;  
240 - digest_block digest;  
241 - };  
242 -  
243 // 4bytes 353 // 4bytes
244 int32_t time; 354 int32_t time;
245 // 4bytes 355 // 4bytes
246 int32_t version; 356 int32_t version;
247 - // 764bytes  
248 - // if schema0, use key  
249 - // if schema1, use digest  
250 - block block0;  
251 - // 764bytes  
252 - // if schema0, use digest  
253 - // if schema1, use key  
254 - block block1;  
255 -  
256 - // the logic schema  
257 - srs_schema_type schema; 357 + // 764bytes+764bytes
  358 + c1s1_strategy* payload;
258 359
259 c1s1(); 360 c1s1();
260 virtual ~c1s1(); 361 virtual ~c1s1();
261 /** 362 /**
  363 + * get the scema.
  364 + */
  365 + virtual srs_schema_type schema();
  366 + /**
262 * get the digest key. 367 * get the digest key.
263 */ 368 */
264 virtual char* get_digest(); 369 virtual char* get_digest();
@@ -269,6 +374,7 @@ namespace _srs_internal @@ -269,6 +374,7 @@ namespace _srs_internal
269 /** 374 /**
270 * server: parse the c1s1, discovery the key and digest by schema. 375 * server: parse the c1s1, discovery the key and digest by schema.
271 * use the c1_validate_digest() to valid the digest of c1. 376 * use the c1_validate_digest() to valid the digest of c1.
  377 + * use the s1_validate_digest() to valid the digest of s1.
272 */ 378 */
273 virtual int parse(char* _c1s1, srs_schema_type _schema); 379 virtual int parse(char* _c1s1, srs_schema_type _schema);
274 380
@@ -294,16 +400,35 @@ namespace _srs_internal @@ -294,16 +400,35 @@ namespace _srs_internal
294 virtual int c1_validate_digest(bool& is_valid); 400 virtual int c1_validate_digest(bool& is_valid);
295 /** 401 /**
296 * server: create and sign the s1 from c1. 402 * server: create and sign the s1 from c1.
  403 + * // decode c1 try schema0 then schema1
  404 + * c1-digest-data = get-c1-digest-data(schema0)
  405 + * if c1-digest-data equals to calc_c1_digest(c1, schema0) {
  406 + * c1-key-data = get-c1-key-data(schema0)
  407 + * schema = schema0
  408 + * } else {
  409 + * c1-digest-data = get-c1-digest-data(schema1)
  410 + * if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
  411 + * switch to simple handshake.
  412 + * return
  413 + * }
  414 + * c1-key-data = get-c1-key-data(schema1)
  415 + * schema = schema1
  416 + * }
  417 + *
  418 + * // generate s1
  419 + * random fill 1536bytes s1
  420 + * time = time() // c1[0-3]
  421 + * version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
  422 + * s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
  423 + * get c1s1-joined by specified schema
  424 + * s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
  425 + * copy s1-digest-data and s1-key-data to s1.
297 */ 426 */
298 virtual int s1_create(c1s1* c1); 427 virtual int s1_create(c1s1* c1);
299 /** 428 /**
300 * server: validate the parsed s1 schema 429 * server: validate the parsed s1 schema
301 */ 430 */
302 virtual int s1_validate_digest(bool& is_valid); 431 virtual int s1_validate_digest(bool& is_valid);
303 - private:  
304 - virtual int calc_s1_digest(char*& digest);  
305 - virtual int calc_c1_digest(char*& digest);  
306 - virtual void destroy_blocks();  
307 }; 432 };
308 433
309 /** 434 /**