From 79a6907a65f3d804d6a4f889f490f1cf417e752c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 7 Feb 2021 12:44:00 +0800 Subject: [PATCH] RTC: Parse PT fast and refine udp handler. 4.0.69 --- README.md | 1 + trunk/src/app/srs_app_listener.cpp | 12 +++++++++ trunk/src/app/srs_app_listener.hpp | 3 +++ trunk/src/app/srs_app_rtc_conn.cpp | 29 ++++++++++---------- trunk/src/app/srs_app_rtc_server.cpp | 14 +++++----- trunk/src/core/srs_core_version4.hpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 35 +++++++++++++++---------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 1 + 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 105e483f39..4f340b6c27 100755 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2021-02-07, RTC: Parse PT fast and refine udp handler. 4.0.69 * v4.0, 2021-02-05, RTC: Refine UDP packet peer fast id. 4.0.68 * v4.0, 2021-02-04, RTC: Reuse UDP socket to receive packet. 4.0.67 * v4.0, 2021-02-04, At least wait 1ms when <1ms, to avoid epoll_wait spin loop. 4.0.66 diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index e2b1d4c13b..25573561ed 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -41,6 +41,7 @@ using namespace std; #include #include #include +#include // set the max packet size. #define SRS_UDP_MAX_PACKET_SIZE 65535 @@ -295,11 +296,13 @@ SrsUdpMuxSocket::SrsUdpMuxSocket(srs_netfd_t fd) peer_port = 0; fast_id_ = 0; + cache_buffer_ = new SrsBuffer(buf, nb_buf); } SrsUdpMuxSocket::~SrsUdpMuxSocket() { srs_freepa(buf); + srs_freep(cache_buffer_); } int SrsUdpMuxSocket::recvfrom(srs_utime_t timeout) @@ -307,6 +310,10 @@ int SrsUdpMuxSocket::recvfrom(srs_utime_t timeout) fromlen = sizeof(from); nread = srs_recvfrom(lfd, buf, nb_buf, (sockaddr*)&from, &fromlen, timeout); + // Reset the fast cache buffer size. + cache_buffer_->set_size(nread); + cache_buffer_->skip(-1 * cache_buffer_->pos()); + // Drop UDP health check packet of Aliyun SLB. // Healthcheck udp check // @see https://help.aliyun.com/document_detail/27595.html @@ -420,6 +427,11 @@ uint64_t SrsUdpMuxSocket::fast_id() return fast_id_; } +SrsBuffer* SrsUdpMuxSocket::buffer() +{ + return cache_buffer_; +} + SrsUdpMuxSocket* SrsUdpMuxSocket::copy_sendonly() { SrsUdpMuxSocket* sendonly = new SrsUdpMuxSocket(lfd); diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 6d4a5dabd0..66ad2dbad2 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -36,6 +36,7 @@ struct sockaddr; +class SrsBuffer; class SrsUdpMuxSocket; // The udp packet handler. @@ -138,6 +139,7 @@ class SrsUdpMuxSocket { private: std::map cache_; + SrsBuffer* cache_buffer_; private: char* buf; int nb_buf; @@ -168,6 +170,7 @@ class SrsUdpMuxSocket int get_peer_port() const; std::string peer_id(); uint64_t fast_id(); + SrsBuffer* buffer(); SrsUdpMuxSocket* copy_sendonly(); }; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 78cf2bc3bc..103a53319e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1122,8 +1122,16 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) return err; } + // If payload type is configed to drop, ignore this packet. + if (pt_to_drop_) { + uint8_t pt = srs_rtp_fast_parse_pt(data, nb_data); + if (pt_to_drop_ == pt) { + return err; + } + } + // Decode the header first. - if (pt_to_drop_ || twcc_id_) { + if (twcc_id_) { SrsRtpHeader h; SrsBuffer b(data, nb_data); h.ignore_padding(true); h.set_extensions(&extension_types_); @@ -1135,20 +1143,13 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) // 1. Client may send some padding packets with invalid SequenceNumber, which causes the SRTP fail. // 2. Server may send multiple duplicated NACK to client, and got more than one ARQ packet, which also fail SRTP. // so, we must parse the header before SRTP unprotect(which may fail and drop packet). - if (twcc_id_) { - uint16_t twcc_sn = 0; - if ((err = h.get_twcc_sequence_number(twcc_sn)) == srs_success) { - if((err = on_twcc(twcc_sn)) != srs_success) { - return srs_error_wrap(err, "on twcc"); - } - } else { - srs_error_reset(err); + uint16_t twcc_sn = 0; + if ((err = h.get_twcc_sequence_number(twcc_sn)) == srs_success) { + if((err = on_twcc(twcc_sn)) != srs_success) { + return srs_error_wrap(err, "on twcc"); } - } - - // If payload type is configed to drop, ignore this packet. - if (pt_to_drop_ && pt_to_drop_ == h.get_payload_type()) { - return err; + } else { + srs_error_reset(err); } } diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 322547bba5..3f1b225c90 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -302,6 +302,8 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) SrsRtcConnection* session = NULL; char* data = skt->data(); int size = skt->size(); + bool is_rtp_or_rtcp = srs_is_rtp_or_rtcp((uint8_t*)data, size); + bool is_rtcp = srs_is_rtcp((uint8_t*)data, size); uint64_t fast_id = skt->fast_id(); // Try fast id first, if not found, search by long peer id. @@ -322,7 +324,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) } // Notify hijack to handle the UDP packet. - if (hijacker) { + if (hijacker && is_rtp_or_rtcp && is_rtcp) { bool consumed = false; if ((err = hijacker->on_udp_packet(skt, session, &consumed)) != srs_success) { return srs_error_wrap(err, "hijack consumed=%u", consumed); @@ -334,7 +336,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) } // For STUN, the peer address may change. - if (srs_is_stun((uint8_t*)data, size)) { + if (!is_rtp_or_rtcp && srs_is_stun((uint8_t*)data, size)) { string peer_id = skt->peer_id(); SrsStunPacket ping; @@ -368,13 +370,13 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) return srs_error_new(ERROR_RTC_STUN, "no session, peer_id=%s, fast=%" PRId64, peer_id.c_str(), fast_id); } - if (srs_is_dtls((uint8_t*)data, size)) { - return session->on_dtls(data, size); - } else if (srs_is_rtp_or_rtcp((uint8_t*)data, size)) { - if (srs_is_rtcp((uint8_t*)data, size)) { + if (is_rtp_or_rtcp) { + if (is_rtcp) { return session->on_rtcp(data, size); } return session->on_rtp(data, size); + } else if (srs_is_dtls((uint8_t*)data, size)) { + return session->on_dtls(data, size); } return srs_error_new(ERROR_RTC_UDP, "unknown packet"); diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 72b58e4310..b349db047c 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION4_HPP #define SRS_CORE_VERSION4_HPP -#define SRS_VERSION4_REVISION 68 +#define SRS_VERSION4_REVISION 69 #endif diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 8a201dd6fc..355b02c615 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -33,22 +33,22 @@ using namespace std; #include #include +/* @see https://tools.ietf.org/html/rfc1889#section-5.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size) { - /* @see https://tools.ietf.org/html/rfc1889#section-5.1 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |V=2|P|X| CC |M| PT | sequence number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | timestamp | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | synchronization source (SSRC) identifier | - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - | contributing source (CSRC) identifiers | - | .... | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ if (size < 12) { return 0; } @@ -63,6 +63,13 @@ uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size) pp[0] = *p++; return value; } +uint8_t srs_rtp_fast_parse_pt(char* buf, int size) +{ + if (size < 12) { + return 0; + } + return buf[1] & 0x7f; +} // If value is newer than pre_value,return true; otherwise false bool srs_seq_is_newer(uint16_t value, uint16_t pre_value) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index efce04ed3c..4b5761b4ab 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -60,6 +60,7 @@ class SrsSharedPtrMessage; // Fast parse the SSRC from RTP packet. Return 0 if invalid. uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size); +uint8_t srs_rtp_fast_parse_pt(char* buf, int size); // The "distance" between two uint16 number, for example: // distance(prev_value=3, value=5) === (int16_t)(uint16_t)((uint16_t)3-(uint16_t)5) === -2