for bug #235, use strategy to implements the schema0 and schema1.
正在显示
2 个修改的文件
包含
584 行增加
和
261 行删除
| @@ -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 | /** |
-
请 注册 或 登录 后发表评论