diff --git a/CMakeLists.txt b/CMakeLists.txt index 8756047..44e5af0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,23 +41,29 @@ include(GenerateExportHeader) # media-server ps dec enc set(MediaServer_Root ${SecMedia_Root}/3rdpart/media-server) -include_directories(${MediaServer_Root}/librtp/include) -include_directories(${MediaServer_Root}/libmpeg/include) -include_directories(${MediaServer_Root}/libmpeg/source) +add_library(rtp STATIC "") aux_source_directory(${MediaServer_Root}/libmpeg/include src_rtp) aux_source_directory(${MediaServer_Root}/libmpeg/source src_rtp) aux_source_directory(${MediaServer_Root}/librtp/include src_rtp) aux_source_directory(${MediaServer_Root}/librtp/source src_rtp) aux_source_directory(${MediaServer_Root}/librtp/payload src_rtp) -add_library(rtp STATIC ${src_rtp}) +target_sources(rtp PRIVATE ${src_rtp}) +foreach(src ${src_rtp}) + message(STATUS "rtp src: ${src}") +endforeach() + +target_include_directories(rtp PUBLIC + ${MediaServer_Root}/librtp/include + ${MediaServer_Root}/libmpeg/include + ${MediaServer_Root}/libmpeg/source) include_directories(${SecMedia_Root}/SVAC/src/svac_src) # 添加svac解密 aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3 src_DEC) aux_source_directory(${SecMedia_Root}/SVAC/src/svac_src src_DEC) add_library(SVAC_DEC STATIC ${src_DEC}) -# 添加svac加密 include_directories(${DEC_ENC_Algorithm}/SVAC/svac_enc) file(GLOB +# 添加svac加密 include_directories(${DEC_ENC_Algoruithm}/SVAC/svac_enc) file(GLOB # src_DEC_ENC ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.c # ${DEC_ENC_Algorithm}/SVAC/svac_enc/*/*.h) aux_source_directory(${SecMedia_Root}/SVAC/src/sm2sm3_enc src_ENC) @@ -76,31 +82,53 @@ include_directories(include src) # file(GLOB SecMedia_src_list ${SecMedia_Root}/SVAC/./*.c # ${SecMedia_Root}/SVAC/./*.h) -file( - GLOB - SecMedia_src_list - ${SecMedia_Root}/*/*.cpp - ${SecMedia_Root}/*/*.h - ${SecMedia_Root}/*/*.c - ${SecMedia_Root}/*/*/*.cpp - ${SecMedia_Root}/*/*/*.h - ${SecMedia_Root}/*/*/*.c -) + +macro(append_srcs out_var root_dir) + file(GLOB_RECURSE srcs ${root_dir}/*.c ${root_dir}/*.cpp) + list(APPEND ${out_var} ${srcs}) +endmacro(append_srcs) + +append_srcs(SecMedia_src_list ${SecMedia_Root}/DecEnc) +append_srcs(SecMedia_src_list ${SecMedia_Root}/Decrypt) +append_srcs(SecMedia_src_list ${SecMedia_Root}/Encrypt) +append_srcs(SecMedia_src_list ${SecMedia_Root}/GB28181) +append_srcs(SecMedia_src_list ${SecMedia_Root}/HuaWei) +# append_srcs(SecMedia_src_list ${SecMedia_Root}/SVAC) +append_srcs(SecMedia_src_list ${SecMedia_Root}/base) + +# message(STATUS "SRCS: ${SecMedia_src_list}") + +# file( +# GLOB +# SecMedia_src_list +# ${SecMedia_Root}/*/*.cpp +# ${SecMedia_Root}/*/*.h +# ${SecMedia_Root}/*/*.c +# ${SecMedia_Root}/*/*/*.cpp +# ${SecMedia_Root}/*/*/*.h +# ${SecMedia_Root}/*/*/*.c +# ) file(GLOB SecMedia_api_list ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h) # # target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden) # list(APPEND LINK_LIB_LIST ${LINK_LIB_SVAC_LIST}) -add_library(${PROJECT_NAME} SHARED -"src/base/util.cpp" -"src/base/rtp_packet.cpp" -"src/SVAC/src/sm2sm3/sm3.c" -"src/SVAC/src/sm2sm3/sm2.c" -${SecMedia_src_list} -) +add_library(${PROJECT_NAME} SHARED ${SecMedia_src_list}) # add_library(${PROJECT_NAME} STATIC ${SecMedia_src_list}) -target_link_libraries(${PROJECT_NAME} ${LINK_LIB_SVAC_LIST} rtp) -target_include_directories(${PROJECT_NAME} PRIVATE ${SecMedia_Root}/.) +target_link_libraries(${PROJECT_NAME} PUBLIC ${LINK_LIB_SVAC_LIST} rtp) +target_include_directories(${PROJECT_NAME} PRIVATE +${SecMedia_Root} +${SecMedia_Root}/3rdpart/media-server/libdash/include +${SecMedia_Root}/3rdpart/media-server/libflv/include +${SecMedia_Root}/3rdpart/media-server/libhls/include +${SecMedia_Root}/3rdpart/media-server/libmov/include +${SecMedia_Root}/3rdpart/media-server/libmpeg/include +${SecMedia_Root}/3rdpart/media-server/librtmp/include +${SecMedia_Root}/3rdpart/media-server/librtp/include +${SecMedia_Root}/3rdpart/media-server/librtsp/include +${SecMedia_Root}/3rdpart/media-server/libsip/include + +) # set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} # SOVERSION 1 PUBLIC_HEADER ${SecMedia_api_list} ) diff --git a/PcapSender/main.cpp b/PcapSender/main.cpp index 1358b0a..5af8a17 100644 --- a/PcapSender/main.cpp +++ b/PcapSender/main.cpp @@ -33,7 +33,7 @@ EncrypInit() { // auto Verify_handle=HWVerify_init(); - auto sign_handle = GB28181_stream_init(&sign_info);//HWSign_init(&sign_info); + auto sign_handle = HK_stream_init(&sign_info);//HWSign_init(&sign_info); return sign_handle; } @@ -68,6 +68,12 @@ template timespec TimeDiff(T &&minu, U &&sub) { + if (minu.tv_sec < sub.tv_sec) { + return {0, 0}; + } else if (minu.tv_sec == sub.tv_sec && minu.tv_nsec < sub.tv_nsec) { + return {0, 0}; + } + timespec deltatime; deltatime.tv_nsec = minu.tv_nsec - sub.tv_nsec; deltatime.tv_sec = minu.tv_sec - sub.tv_sec; @@ -75,7 +81,7 @@ TimeDiff(T &&minu, U &&sub) deltatime.tv_nsec += 1000000000; deltatime.tv_sec--; } - return move(deltatime); + return deltatime; } int @@ -116,9 +122,12 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str if (sign_handle) { output_thread = std::shared_ptr(new std::thread([&] { while (processing.load(std::memory_order_relaxed)) { - int ret = - GB28181_stream_out(sign_handle, sign_out_buf, &sign_out_len, &offset_len, &append_len, ¶m); + auto now = std::chrono::steady_clock::now(); + int ret = HK_stream_out(sign_handle, sign_out_buf, &sign_out_len, &offset_len, &append_len, ¶m); + auto end = std::chrono::steady_clock::now(); if (ret != 1) { continue; } + // WRNGL("HK_stream_out time: %lu ms\n", + // std::chrono::duration_cast(end - now).count()); processing_cnt.fetch_sub(1); if (append_len == 0) { sendto(socket, sign_out_buf, sign_out_len, 0, (const sockaddr *) &addr, sizeof(addr)); @@ -127,8 +136,8 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str sendto(socket, sign_out_buf + offset_len, sign_out_len - offset_len, 0, (const sockaddr *) &addr, sizeof(addr)); } - // GB28181_stream_in(sign_h2,(char*)payload,payload_len,nullptr); - // GB28181_stream_out(sign_h2,sign_out_buf,&sign_out_len,&offset_len,&append_len, ¶m); + // HK_stream_in(sign_h2,(char*)payload,payload_len,nullptr); + // HK_stream_out(sign_h2,sign_out_buf,&sign_out_len,&offset_len,&append_len, ¶m); } })); } @@ -159,7 +168,7 @@ ReadPcapAndSend(int socket, sockaddr_in &addr, const string &filename, const str if (sign_handle) { auto cnt = processing_cnt.fetch_add(1); // printf("frame processing cnt:%d\n", cnt); - GB28181_stream_in(sign_handle, (char *) payload, payload_len, nullptr); + HK_stream_in(sign_handle, (char *) payload, payload_len, nullptr); } else { if (sendto(socket, payload, payload_len, 0, (const sockaddr *) &addr, sizeof(addr)) == -1) { printf("send failed : %s\n", strerror(errno)); diff --git a/src/HuaWei/HWsign.h b/src/HuaWei/HWsign.h index 912e5aa..9fb199b 100644 --- a/src/HuaWei/HWsign.h +++ b/src/HuaWei/HWsign.h @@ -26,7 +26,7 @@ API_EXPORT void *HK_stream_init(struct sec_set_info *sign_info); API_EXPORT int HK_stream_in(void *Handle, const char *buf, const uint32_t len, void *param); API_EXPORT void HK_stream_release(void *Handle); API_EXPORT int -KH_stream_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param); +HK_stream_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param); API_EXPORT void *GB28181_stream_init(struct sec_set_info *sign_info); API_EXPORT int GB28181_stream_in(void *Handle, const char *buf, const uint32_t len, void *param); diff --git a/src/base/frame.cpp b/src/base/frame.cpp index 1b71a7c..95b56e9 100644 --- a/src/base/frame.cpp +++ b/src/base/frame.cpp @@ -9,18 +9,18 @@ static std::atomic g_frame_cnt{0}; Frame::~Frame() { g_frame_cnt.fetch_sub(1); } Frame::Ptr -Frame::CreateUDPFrame(const uint8_t *data, size_t len) +Frame::CreateUDPFrame(const void *data, size_t len) { return std::shared_ptr(new Frame(kUDP, data, len)); } Frame::Ptr -Frame::CreateTCPFrame(const uint8_t *data, size_t len) +Frame::CreateTCPFrame(const void *data, size_t len) { return std::shared_ptr(new Frame(kTCP, data, len)); } -Frame::Frame(Type type, const uint8_t *data, size_t len) : _type(type), _data(data, data + len) +Frame::Frame(Type type, const void *data, size_t len) : _type(type), _data((uint8_t *) data, (uint8_t *) data + len) { auto cur = g_frame_cnt.fetch_add(1); // INFOL("frame count: %d\n", cur); diff --git a/src/base/frame.h b/src/base/frame.h index 1d3e6ae..b3a3190 100644 --- a/src/base/frame.h +++ b/src/base/frame.h @@ -13,8 +13,8 @@ public: enum Type { kTCP, kUDP }; - static Ptr CreateUDPFrame(const uint8_t *data, size_t len); - static Ptr CreateTCPFrame(const uint8_t *data, size_t len); + static Ptr CreateUDPFrame(const void *data, size_t len); + static Ptr CreateTCPFrame(const void *data, size_t len); public: ~Frame(); @@ -40,7 +40,7 @@ public: void Wait() { _event.Wait(); } private: - Frame(Type type, const uint8_t *data, size_t len); + Frame(Type type, const void *data, size_t len); private: Event _event{true}; diff --git a/src/base/frame_manager.cpp b/src/base/frame_manager.cpp index 2b4126d..930750f 100644 --- a/src/base/frame_manager.cpp +++ b/src/base/frame_manager.cpp @@ -7,6 +7,12 @@ FrameManager::FrameManager() { Init(); } FrameManager::~FrameManager() {} +bool +FrameManager::Initialize() +{ + return _rtp_manager.Initialize(); +} + bool FrameManager::Enqueue(Frame::Ptr frame) { @@ -21,6 +27,7 @@ Frame::Ptr FrameManager::Dequeue() { Frame::Ptr frame{nullptr}; + auto start = std::chrono::system_clock::now(); { std::lock_guard _(_frame_queue_lock); if (_frame_queue.empty()) { return nullptr; } @@ -30,6 +37,8 @@ FrameManager::Dequeue() } frame->Wait(); + auto end = std::chrono::system_clock::now(); + // WRNGL("frame wait time: %ld ms\n", std::chrono::duration_cast(end - start).count()); return frame; } diff --git a/src/base/frame_manager.h b/src/base/frame_manager.h index 8131022..2e2d71f 100644 --- a/src/base/frame_manager.h +++ b/src/base/frame_manager.h @@ -18,6 +18,7 @@ public: FrameManager(); ~FrameManager(); + bool Initialize(); bool Enqueue(Frame::Ptr frame); Frame::Ptr Dequeue(); diff --git a/src/base/hk_sign.cpp b/src/base/hk_sign.cpp new file mode 100644 index 0000000..35454ea --- /dev/null +++ b/src/base/hk_sign.cpp @@ -0,0 +1,44 @@ +#include "HuaWei/HWsign.h" +#include "base/frame_manager.h" + +void * +HK_stream_init(struct sec_set_info *sign_info) +{ + sign::FrameManager *fm = new sign::FrameManager(); + fm->SetSecSetInfo(sign_info); + if (!fm->Initialize()) { + delete fm; + return nullptr; + } + return fm; +} + +int +HK_stream_in(void *Handle, const char *buf, const uint32_t len, void *param) +{ + sign::FrameManager *fm = (sign::FrameManager *) Handle; + auto frame = sign::Frame::CreateUDPFrame(buf, len); + fm->Enqueue(frame); + return 1; +} + +void +HK_stream_release(void *Handle) +{ + if (Handle) { delete (sign::FrameManager *) Handle; } +} + +int +HK_stream_out(void *Handle, char *buf, uint32_t *len, uint16_t *sei_end_offset, uint16_t *append_length, void **param) +{ + sign::FrameManager *fm = (sign::FrameManager *) Handle; + auto frame = fm->Dequeue(); + if (!frame) { return -1; } + + *len = frame->size(); + if (buf) { std::copy(frame->data(), frame->data() + frame->size(), buf); } + *sei_end_offset = 0; + *append_length = 0; + + return 1; +} diff --git a/src/base/rtp_decoder.cpp b/src/base/rtp_decoder.cpp index 6354049..855add7 100644 --- a/src/base/rtp_decoder.cpp +++ b/src/base/rtp_decoder.cpp @@ -43,7 +43,9 @@ RTPDecoder::Input(RTPPacket::Ptr packet) const uint16_t seq = GetRTPSequenceNumber(packet->packet_data()); if (_prev_seq == -1) { _prev_seq = seq; + _start_decode_tp = std::chrono::steady_clock::now(); } else if (seq != ((_prev_seq + 1) & 0xFFFF)) { + _start_decode_tp = std::chrono::steady_clock::now(); _ref_rtp_packets.clear(); _prev_seq = -1; return; @@ -87,7 +89,11 @@ RTPDecoder::CreateHandler() DecodedPacket dp{packet, bytes, timestamp, flags}; dp.ref_rtp_packets.swap(self->_ref_rtp_packets); + auto end = std::chrono::steady_clock::now(); + // WRNGL("decode time: %lu ms\n", + // std::chrono::duration_cast(end - self->_start_decode_tp).count()); self->OnDecoded(dp); + self->_start_decode_tp = std::chrono::steady_clock::now(); }; return handler; } diff --git a/src/base/rtp_decoder.h b/src/base/rtp_decoder.h index eab719b..9f672f7 100644 --- a/src/base/rtp_decoder.h +++ b/src/base/rtp_decoder.h @@ -47,6 +47,7 @@ private: std::vector _buffer; std::vector _ref_rtp_packets; + std::chrono::steady_clock::time_point _start_decode_tp; }; }// namespace sign diff --git a/src/base/rtp_manager.cpp b/src/base/rtp_manager.cpp index ce0a327..5e758bc 100644 --- a/src/base/rtp_manager.cpp +++ b/src/base/rtp_manager.cpp @@ -8,6 +8,13 @@ RTPManager::RTPManager() {} RTPManager::~RTPManager() {} +bool +RTPManager::Initialize() +{ + _signer.OnSigned.connect(this, &RTPManager::OnSigned); + return _signer.Start(_sec_set_info); +} + void RTPManager::OnFrameEnqueue(Frame::Ptr frame) { @@ -22,7 +29,46 @@ RTPManager::OnFrameEnqueue(Frame::Ptr frame) void RTPManager::SetSecSetInfo(sec_set_info *info) -{} +{ + _sec_set_info = info; + InitSecSet(info); + InitVerifySet(info); +} + +void +RTPManager::InitSecSet(void *data) +{ + sec_set_info *info = (sec_set_info *) data; + + uint8_t security_set_version[19] = "Ver 0.0.2"; + memset(&_sec_set, 0, sizeof(_sec_set)); + memset(&_sec_set.evek, 0xFF, sizeof(_sec_set.evek)); + memset(&_sec_set.iv, 0xFF, sizeof(_sec_set.iv)); + // Set Flag + _sec_set.Flag.encryption_flag = 0; + _sec_set.Flag.authnetication_flag = 1; + _sec_set.Flag.vek_flag = 0; + _sec_set.Flag.iv_flag = 0; + _sec_set.Flag.hash_discard_p_picture = 1; + _sec_set.Flag.reserved_flag = 0b001; + // set Type + _sec_set.Type.signature_type = (uint8_t) SecMedia::DecryptType::SM2_auth; + _sec_set.Type.hash_type = (uint8_t) SecMedia::DecryptType::SM3; + _sec_set.Type.encryption_type = (uint8_t) SecMedia::DecryptType::NONE; + _sec_set.Type.vek_encryption_type = (uint8_t) SecMedia::DecryptType::NONE; + memcpy(_sec_set.camera_id, info->camera_id, sizeof(_sec_set.camera_id)); + memcpy(_sec_set.vkek_version, info->vkek_version, sizeof(_sec_set.vkek_version)); + _sec_set.vkek_version_length_minus1 = sizeof(_sec_set.vkek_version) - 1; + _sec_set.end_flag = 0x80; +} + +void +RTPManager::InitVerifySet(void *info) +{ + memset(&_verify_set, 0, sizeof(_verify_set)); + memset(&_verify_set.sign, 0xFF, sizeof(_verify_set.sign)); + _verify_set.end_flag = 0x80; +} void RTPManager::ProcessUDPFrame(Frame::Ptr frame) @@ -124,6 +170,95 @@ RTPManager::OnRTPDecoded(RTPDecoder::DecodedPacket packet) auto str = ss.str(); if (!str.empty()) str.pop_back(); INFOL("RTP decoded. type=%2d, size=%5u seq=[%s]\n", h264_type, packet.bytes, str.c_str()); + if (h264_type == H264Nal::NAL_IDR) { + // remove old sign + ResetSignData(); + + Signer::DataPacket::Ptr sign_packet = std::make_shared(); + sign_packet->param.codec_type = h264_type; + sign_packet->param.dts = packet.timestamp; + sign_packet->param.data_len = packet.bytes; + sign_packet->data = std::vector((uint8_t *) packet.packet, (uint8_t *) packet.packet + packet.bytes); + _signer.Enqueue(sign_packet); + } else if (h264_type == H264Nal::NAL_SEI) { + INFOL("origin SEI data: %s\n", ToHex((const uint8_t *) packet.packet, packet.bytes).c_str()); + uint8_t buf[4096]; + uint8_t *ptr = buf; + ptr = SecMedia::appendSEIframe( + ptr, SEC_SET_PT, (uint8_t *) SecMedia::Sec_set_UUID, (uint8_t *) (&_sec_set), sizeof(_sec_set)); + + auto signed_packet = FetchSignData(); + if (!signed_packet || signed_packet->sign_data.empty()) { + + if (_signer.state() == Signer::kSigning) { + WRNGL("Sign data is empty. still signing\n"); + _verify_set.head_frame_type = SecMedia::ERR_incomplete_Sign; + } else if (!signed_packet) { + WRNGL("Sign data is empty. no I-Frame\n"); + _verify_set.head_frame_type = SecMedia::ERR_Without_Frame_Data; + } else { + WRNGL("Sign data is empty. no sign_data\n"); + _verify_set.head_frame_type = SecMedia::ERR_Without_Sign_Data; + } + + ptr = SecMedia::appendSEIframe( + ptr, VER_SET_PT, (uint8_t *) SecMedia::Ver_set_UUID, (uint8_t *) &_verify_set, sizeof(_verify_set)); + } else { + INFOL("Sign data size=%lu\n", signed_packet->sign_data.size()); + INFOL("Sign data: %s\n", ToHex(signed_packet->sign_data).c_str()); + _verify_set.head_frame_type = signed_packet->param.codec_type; + _verify_set.head_frame_dts = signed_packet->param.dts; + _verify_set.total_hash_data_len = signed_packet->param.data_len; + _verify_set.sign_len = signed_packet->sign_data.size(); + memcpy(_verify_set.sign, signed_packet->sign_data.data(), signed_packet->sign_data.size()); + + ptr = SecMedia::appendSEIframe( + ptr, VER_SET_PT, (uint8_t *) SecMedia::Ver_set_UUID, (uint8_t *) &_verify_set, sizeof(_verify_set)); + } + ModifySEIPacket(packet, buf, ptr); + } +} + +void +RTPManager::ModifySEIPacket(RTPDecoder::DecodedPacket packet, void *sei_begin, void *sei_end) +{ + // TODO: @tqcq 增加对padding udp rtp sei包的处理 + auto last_packet = packet.ref_rtp_packets.back(); + auto last_frame = last_packet->ref_frames().back(); + INFOL("Modify SEI packet. seq=%d, size=%lu\n", last_packet->seq(), last_frame->size()); + INFOL("SEI data size=%lu\n", (uint8_t *) sei_end - (uint8_t *) sei_begin); + INFOL("SEI data: %s\n", ToHex((const uint8_t *) sei_begin, (uint8_t *) sei_end - (uint8_t *) sei_begin).c_str()); +} + +void +RTPManager::OnSigned(Signer::SignedPacket::Ptr signed_packet) +{ + INFOL("RTPManager::OnSigned sign data size=%lu\n", signed_packet->sign_data.size()); + INFOL("RTPManager::OnSigned sign data: %s\n", ToHex(signed_packet->sign_data).c_str()); + SetSignData(signed_packet); +} + +void +RTPManager::SetSignData(Signer::SignedPacket::Ptr signed_packet) +{ + std::lock_guard _(_signed_packet_lock); + _signed_packet = signed_packet; +} + +void +RTPManager::ResetSignData() +{ + std::lock_guard _(_signed_packet_lock); + _signed_packet = nullptr; +} + +Signer::SignedPacket::Ptr +RTPManager::FetchSignData() +{ + std::lock_guard _(_signed_packet_lock); + auto res = _signed_packet; + _signed_packet.reset(); + return res; } }// namespace sign diff --git a/src/base/rtp_manager.h b/src/base/rtp_manager.h index 398d3e5..dca2770 100644 --- a/src/base/rtp_manager.h +++ b/src/base/rtp_manager.h @@ -6,6 +6,7 @@ #include "HuaWei/HWsign.h" #include "rtp_decoder.h" #include "rtp_packet.h" +#include "signer.h" #include "sigslot.h" namespace sign { @@ -17,12 +18,16 @@ public: RTPManager(); ~RTPManager(); + bool Initialize(); void OnFrameEnqueue(Frame::Ptr frame); // HACK: void SetSecSetInfo(sec_set_info *info); private: + void InitSecSet(void *info); + void InitVerifySet(void *info); + void ProcessUDPFrame(Frame::Ptr); void ProcessTCPFrame(Frame::Ptr); @@ -37,10 +42,19 @@ private: void IncCurSeq(); uint16_t GetNextSeq(); + void SetSignData(Signer::SignedPacket::Ptr signed_packet); + void ResetSignData(); + Signer::SignedPacket::Ptr FetchSignData(); + + void ModifySEIPacket(RTPDecoder::DecodedPacket packet, void *sei_begin, void *sei_end); + private: - // FOR TEST + // NALU 组包回调 void OnRTPDecoded(RTPDecoder::DecodedPacket packet); + // 签名数据回调 + void OnSigned(Signer::SignedPacket::Ptr signed_packet); + private: /** * Partical RTP packet -> Complete RTP packet -> Decoder -> Signer @@ -50,6 +64,10 @@ private: * 2. Insert SEI **/ + std::mutex _signed_packet_lock; + // std::vector _sign_data; + Signer::SignedPacket::Ptr _signed_packet{nullptr}; + // 当前不完整的RTP包 RTPPacket::Ptr _cur_rtp_packet{nullptr}; int64_t _cur_rtp_seq{-1}; @@ -59,6 +77,14 @@ private: uint16_t _insert_packet_num{0}; RTPDecoder::Ptr _decoder; + + void *_sec_set_info{nullptr}; + Signer _signer; + + // 安全相关的辅助信息 + SecMedia::NALUdecodeInfo _sec_set; + // 签名验证信息集合 + SecMedia::VerificationSet _verify_set; }; }// namespace sign diff --git a/src/base/rtp_packet.cpp b/src/base/rtp_packet.cpp index 2f278b9..2371a51 100644 --- a/src/base/rtp_packet.cpp +++ b/src/base/rtp_packet.cpp @@ -5,6 +5,10 @@ #include #include +extern "C" { +#include "rtp-packet.h" +} + namespace sign { static std::atomic g_rtp_packet_cnt{0}; @@ -126,7 +130,17 @@ RTPPacket::RTPPacket(RTPManager *owner, Frame::Ptr udp_frame) _rtp_ptr = udp_frame->data(); _state = IsRTPHeader(udp_frame->data(), udp_frame->size()) ? kComplete : kError; - udp_frame->set_paused(true); + udp_frame->set_paused(false); + if (_state == kComplete) { + rtp_packet_t pkt; + if (rtp_packet_deserialize(&pkt, udp_frame->data(), udp_frame->size()) == 0) { + _state = kComplete; + uint8_t h264_type = ((uint8_t *) pkt.payload)[0] & 0x1F; + if (h264_type == H264Nal::NAL_SEI) { udp_frame->set_paused(true); } + } else { + _state = kError; + } + } } RTPPacket::RTPPacket(RTPManager *owner) : _owner(owner), _frame_type(Frame::kTCP) { IncRTPPacketCnt(); } diff --git a/src/base/rtp_packet.h b/src/base/rtp_packet.h index 2eb8076..07b677b 100644 --- a/src/base/rtp_packet.h +++ b/src/base/rtp_packet.h @@ -50,6 +50,8 @@ public: bool paused() const; void set_paused(bool paused); + std::vector ref_frames() const { return _ref_frames; } + private: RTPPacket(RTPManager *owner, Frame::Ptr udp_frame); RTPPacket(RTPManager *owner); diff --git a/src/base/signer.cpp b/src/base/signer.cpp index 7d277ae..83dd0f4 100644 --- a/src/base/signer.cpp +++ b/src/base/signer.cpp @@ -1 +1,117 @@ #include "signer.h" +#include "HuaWei/HWcommon.h" +#include "HuaWei/HWsign.h" +#include "util.h" + +#include +#include +#include + +namespace sign { +Signer::Signer() {} + +Signer::~Signer() +{ + Stop(); + Join(); +} + +bool +Signer::Start(void *param) +{ + _param = param; + if (_sign_thread) { + ERROL("sign thread already running\n"); + assert(false); + return true; + } + if (!_param) { + WRNGL("sec_set_info param is null\n"); + return false; + } + // 初始化安全相关的辅助信息 + _sign_thread = std::unique_ptr(new std::thread(&Signer::WorkProc, this)); + + return true; +} + +void +Signer::Enqueue(DataPacket::Ptr packet) +{ + std::unique_lock _(_sign_lock); + _data_queue.push(packet); + _cv.notify_one(); +} + +void +Signer::WorkProc() +{ + sec_set_info *info = reinterpret_cast(_param); + if (info) { + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(info->cpu_core, &mask); + if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) { + ERROL("set thread affinity failed, target_cpu = %d\n", info->cpu_core); + } + } + + DataPacket::Ptr data_packet; + while (!_stopped.load(std::memory_order_relaxed)) { + { + std::unique_lock _(_sign_lock); + _cv.wait(_, [this] { return !_data_queue.empty() || _stopped; }); + if (_stopped) { return; } + + _state = kSigning; + data_packet.swap(_data_queue.front()); + _data_queue.pop(); + } + std::vector sign; + if (!Sign(data_packet->data, &sign)) { + // do nothing + ERROL("sign failed\n"); + } else { + auto signed_packet = std::make_shared(); + signed_packet->param = data_packet->param; + signed_packet->sign_data = sign; + OnSigned(signed_packet); + } + _state = kIdle; + } +} + +bool +Signer::Sign(const std::vector &data, std::vector *sign) +{ + // 1. sm3 hash + std::vector sm3_hash = SM3Hash(data.data(), data.size()); + if (sm3_hash.empty() || sm3_hash.size() < 32) { + ERROL("sm3 hash failed\n"); + return false; + } + + sec_set_info *info = reinterpret_cast(_param); + uint8_t sm2_sign[128]; + + do_sm2_sign((char *) info->prikey, (char *) info->pubkey, (char *) sm3_hash.data(), 32, (char *) sm2_sign); + sign->assign(sm2_sign, sm2_sign + 64); + return true; +} + +void +Signer::Stop() +{ + _stopped.store(true); +} + +void +Signer::Join() +{ + if (_sign_thread && _sign_thread->joinable()) { + _sign_thread->joinable(); + _sign_thread.reset(); + } +} + +}// namespace sign diff --git a/src/base/signer.h b/src/base/signer.h index b99ca71..e078c8d 100644 --- a/src/base/signer.h +++ b/src/base/signer.h @@ -3,12 +3,73 @@ #pragma once +#include "DecEnc/NALUdecode.h" +#include "sigslot.h" +#include +#include #include +#include #include namespace sign { class Signer { public: + enum State { + kIdle, + kSigning, + }; + + struct SignParam { + uint64_t data_len; + uint32_t dts; + uint8_t codec_type; + }; + + // 待签名数据包 + struct DataPacket { + SignParam param; + std::vector data; + using Ptr = std::shared_ptr; + }; + + // 签名数据包 + struct SignedPacket { + SignParam param; + std::vector sign_data; + using Ptr = std::shared_ptr; + }; + + sigslot::signal1 OnSigned; + +public: + Signer(); + virtual ~Signer(); + + void Enqueue(DataPacket::Ptr packet); + + bool Start(void *param); + void Stop(); + void Join(); + + State state() const { return _state; } + +private: + void WorkProc(); + + bool Sign(const std::vector &data, std::vector *sign); + +private: + State _state{kIdle}; + void *_param{nullptr}; + + std::atomic _stopped{false}; + + std::unique_ptr _sign_thread{nullptr}; + + std::mutex _sign_lock; + std::condition_variable _cv; + // 存放待签名数据 + std::queue _data_queue; }; }// namespace sign diff --git a/src/base/util.cpp b/src/base/util.cpp index 44fb903..1f91b0c 100644 --- a/src/base/util.cpp +++ b/src/base/util.cpp @@ -82,6 +82,12 @@ IsParticalRTPHeader(const uint8_t *data, size_t len) } } +std::string +ToHex(std::vector data) +{ + return ToHex(data.data(), data.size()); +} + std::string ToHex(const void *data, size_t len) { diff --git a/src/base/util.h b/src/base/util.h index 28abbe4..4bfb326 100644 --- a/src/base/util.h +++ b/src/base/util.h @@ -22,6 +22,7 @@ bool IsRTPHeader(const uint8_t *data, size_t len); bool IsParticalRTPHeader(const uint8_t *data, size_t len); std::string ToHex(const void *data, size_t len); +std::string ToHex(std::vector data); std::vector SM3Hash(const void *data, size_t len);