From 133e07e670657fa1398a762a86e2ec5a3d00366c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 26 Jul 2020 21:23:58 +0800 Subject: [PATCH 01/36] RTC: Refine stat code --- trunk/src/app/srs_app_rtc_conn.cpp | 15 ++++++++++----- trunk/src/app/srs_app_rtc_conn.hpp | 3 +-- trunk/src/app/srs_app_rtc_source.cpp | 14 +++++++++----- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 5ba8d2a91..537cbf689 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -483,8 +483,10 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u if (true) { std::map::iterator it; for (it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { - if (it->second->has_ssrc(ssrc)) { - SrsRtpPacket2* pkt = it->second->fetch_rtp_packet(seq); + SrsRtcAudioSendTrack* track = it->second; + + if (track->has_ssrc(ssrc)) { + SrsRtpPacket2* pkt = track->fetch_rtp_packet(seq); if (pkt != NULL) { pkts.push_back(pkt); } @@ -496,8 +498,10 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u if (true) { std::map::iterator it; for (it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { - if (it->second->has_ssrc(ssrc)) { - SrsRtpPacket2* pkt = it->second->fetch_rtp_packet(seq); + SrsRtcVideoSendTrack* track = it->second; + + if (track->has_ssrc(ssrc)) { + SrsRtpPacket2* pkt = track->fetch_rtp_packet(seq); if (pkt != NULL) { pkts.push_back(pkt); } @@ -1951,7 +1955,7 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) sendonly_skt = addr_cache; } -void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc) +void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks) { // If DTLS is not OK, drop all messages. if (!transport_) { @@ -1996,6 +2000,7 @@ void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ss } ++iter; + ++sent_nacks; } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 3ede887a6..6745d5bf7 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -253,7 +253,6 @@ public: srs_error_t initialize(SrsRequest* req, SrsRtcStreamDescription* stream_desc); srs_error_t start(); private: - void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc); srs_error_t send_rtcp_rr(); srs_error_t send_rtcp_xr_rrtr(); public: @@ -390,7 +389,7 @@ public: void update_sendonly_socket(SrsUdpMuxSocket* skt); public: // send rtcp - void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc); + void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks); srs_error_t send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_queue, const uint64_t& last_send_systime, const SrsNtp& last_send_ntp); srs_error_t send_rtcp_xr_rrtr(uint32_t ssrc); srs_error_t send_rtcp_fb_pli(uint32_t ssrc); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index e8798b7be..11845c63f 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1597,8 +1597,10 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) // insert into video_queue and audio_queue rtp_queue_->set(seq, pkt->copy()); + // send_nack - session_->check_send_nacks(nack_receiver_, ssrc); + uint32_t sent_nacks = 0; + session_->check_send_nacks(nack_receiver_, ssrc, sent_nacks); return err; } @@ -1621,6 +1623,9 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk { srs_error_t err = srs_success; + // connection level statistic + session_->stat_->nn_in_audios++; + if (source) { if ((err = source->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "source on rtp"); @@ -1632,8 +1637,6 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk return srs_error_wrap(err, "on nack"); } - session_->stat_->nn_in_audios++; - return err; } @@ -1651,6 +1654,9 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk { srs_error_t err = srs_success; + // connection level statistic + session_->stat_->nn_in_videos++; + pkt->frame_type = SrsFrameTypeVideo; if (source) { @@ -1672,8 +1678,6 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk return srs_error_wrap(err, "on nack"); } - session_->stat_->nn_in_videos++; - return err; } From 5f7de580958352e0825a43b4b9481cd07450839c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 26 Jul 2020 22:58:22 +0800 Subject: [PATCH 02/36] RTC: Add stat for track. --- trunk/src/app/srs_app_rtc_source.cpp | 62 +++++++++++++++++++++++----- trunk/src/app/srs_app_rtc_source.hpp | 44 ++++++++++++++++++++ 2 files changed, 96 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 11845c63f..7d45163e0 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1504,10 +1504,31 @@ SrsRtcTrackDescription* SrsRtcStreamDescription::find_track_description_by_ssrc( return NULL; } +SrsRtcTrackStatistic::SrsRtcTrackStatistic() +{ + last_written = 0; + packets = 0; + last_packets = 0; + bytes = 0; + last_bytes = 0; + nacks = 0; + last_nacks = 0; + padding_packets = 0; + last_padding_packets = 0; + padding_bytes = 0; + last_padding_bytes = 0; + replay_packets = 0; + last_replay_packets = 0; + replay_bytes = 0; + last_replay_bytes = 0; +} + SrsRtcRecvTrack::SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc, bool is_audio) { session_ = session; track_desc_ = track_desc->copy(); + statistic_ = new SrsRtcTrackStatistic(); + if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); nack_receiver_ = new SrsRtpNackForReceiver(rtp_queue_, 100 * 2 / 3); @@ -1522,6 +1543,7 @@ SrsRtcRecvTrack::~SrsRtcRecvTrack() srs_freep(rtp_queue_); srs_freep(nack_receiver_); srs_freep(track_desc_); + srs_freep(statistic_); } bool SrsRtcRecvTrack::has_ssrc(uint32_t ssrc) @@ -1601,6 +1623,7 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) // send_nack uint32_t sent_nacks = 0; session_->check_send_nacks(nack_receiver_, ssrc, sent_nacks); + statistic_->nacks += sent_nacks; return err; } @@ -1691,16 +1714,20 @@ SrsRtcSendTrack::SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescripti { session_ = session; track_desc_ = track_desc->copy(); + statistic_ = new SrsRtcTrackStatistic(); + if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); } else { rtp_queue_ = new SrsRtpRingBuffer(1000); } } + SrsRtcSendTrack::~SrsRtcSendTrack() { srs_freep(rtp_queue_); srs_freep(track_desc_); + srs_freep(statistic_); } bool SrsRtcSendTrack::has_ssrc(uint32_t ssrc) @@ -1759,7 +1786,6 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta return err; } - std::vector pkts; pkt->header.set_ssrc(track_desc_->ssrc_); // Put rtp packet to NACK/ARQ queue @@ -1768,15 +1794,22 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta rtp_queue_->set(nack->header.get_sequence(), nack); } - pkts.push_back(pkt); - // Update stats. info.nn_bytes += pkt->nb_bytes(); info.nn_audios++; session_->stat_->nn_out_audios++; - if ((err = session_->do_send_packets(pkts, info)) != srs_success) { - return srs_error_wrap(err, "raw send"); + // track level statistic + statistic_->packets++; + statistic_->bytes += pkt->nb_bytes(); + + if (true) { + std::vector pkts; + pkts.push_back(pkt); + + if ((err = session_->do_send_packets(pkts, info)) != srs_success) { + return srs_error_wrap(err, "raw send"); + } } return err; @@ -1805,24 +1838,33 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta if (!track_desc_->is_active_) { return err; } - - std::vector pkts; + + SrsRtcTrackStatistic* statistic = statistic_; pkt->header.set_ssrc(track_desc_->ssrc_); + // Put rtp packet to NACK/ARQ queue if (true) { SrsRtpPacket2* nack = pkt->copy(); rtp_queue_->set(nack->header.get_sequence(), nack); } - pkts.push_back(pkt); // Update stats. info.nn_bytes += pkt->nb_bytes(); info.nn_videos++; session_->stat_->nn_out_videos++; - if ((err = session_->do_send_packets(pkts, info)) != srs_success) { - return srs_error_wrap(err, "raw send"); + // track level statistic + statistic->packets++; + statistic->bytes += pkt->nb_bytes(); + + if (true) { + std::vector pkts; + pkts.push_back(pkt); + + if ((err = session_->do_send_packets(pkts, info)) != srs_success) { + return srs_error_wrap(err, "raw send"); + } } return err; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 0ae81a817..fcdcf699c 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -404,10 +404,52 @@ public: SrsRtcTrackDescription* find_track_description_by_ssrc(uint32_t ssrc); }; +class SrsRtcTrackStatistic +{ +public: + srs_utime_t last_written; + + // packets received or sent. + uint32_t packets; + // packets received or sent at last statistic time. + uint32_t last_packets; + // bytes received or sent. + uint64_t bytes; + // bytes received or sent at last statistic time. + uint32_t last_bytes; + + // nacks received or sent. + uint32_t nacks; + // nacks received or sent at last statistic time. + uint32_t last_nacks; + + // padding packets received or sent. + uint32_t padding_packets; + // padding packets received or sent at last statistic time. + uint32_t last_padding_packets; + // padding bytes received or sent. + uint32_t padding_bytes; + // padding bytes received or sent at last statistic time. + uint32_t last_padding_bytes; + + // replay packets received or sent. + uint32_t replay_packets; + // replay packets received or sent at last statistic time. + uint32_t last_replay_packets; + // replay bytes received or sent. + uint64_t replay_bytes; + // replay bytes received or sent at last statistic time. + uint64_t last_replay_bytes; + +public: + SrsRtcTrackStatistic(); +}; + class SrsRtcRecvTrack { protected: SrsRtcTrackDescription* track_desc_; + SrsRtcTrackStatistic* statistic_; SrsRtcConnection* session_; SrsRtpRingBuffer* rtp_queue_; @@ -458,7 +500,9 @@ class SrsRtcSendTrack protected: // send track description SrsRtcTrackDescription* track_desc_; + SrsRtcTrackStatistic* statistic_; + // The owner connection for this track. SrsRtcConnection* session_; // NACK ARQ ring buffer. SrsRtpRingBuffer* rtp_queue_; From b3212a12de0ad6fa677ec9dd60ffc961e267e2a4 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 26 Jul 2020 23:18:56 +0800 Subject: [PATCH 03/36] RTC: Update nack stat --- trunk/src/app/srs_app_rtc_conn.cpp | 6 ++++++ trunk/src/app/srs_app_rtc_source.cpp | 7 +++++++ trunk/src/app/srs_app_rtc_source.hpp | 1 + 3 files changed, 14 insertions(+) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 537cbf689..093394d2c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -486,6 +486,9 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u SrsRtcAudioSendTrack* track = it->second; if (track->has_ssrc(ssrc)) { + // update recv nack statistic + track->on_recv_nack(); + SrsRtpPacket2* pkt = track->fetch_rtp_packet(seq); if (pkt != NULL) { pkts.push_back(pkt); @@ -501,6 +504,9 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u SrsRtcVideoSendTrack* track = it->second; if (track->has_ssrc(ssrc)) { + // update recv nack statistic + track->on_recv_nack(); + SrsRtpPacket2* pkt = track->fetch_rtp_packet(seq); if (pkt != NULL) { pkts.push_back(pkt); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 7d45163e0..4e1e55755 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1769,6 +1769,13 @@ srs_error_t SrsRtcSendTrack::on_rtcp(SrsRtpPacket2* pkt) return srs_success; } +void SrsRtcSendTrack::on_recv_nack() +{ + SrsRtcTrackStatistic* statistic = statistic_; + + statistic->nacks++; +} + SrsRtcAudioSendTrack::SrsRtcAudioSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc) : SrsRtcSendTrack(session, track_desc, true) { diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index fcdcf699c..dcca61f61 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -517,6 +517,7 @@ public: public: virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info); virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt); + virtual void on_recv_nack(); }; class SrsRtcAudioSendTrack : public SrsRtcSendTrack From a035d312f977ab1983e5702aee7b794c0a2acd90 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 26 Jul 2020 23:28:03 +0800 Subject: [PATCH 04/36] RTC: Update stat for recv track --- trunk/src/app/srs_app_rtc_source.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 4e1e55755..6e97fde24 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1649,6 +1649,10 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk // connection level statistic session_->stat_->nn_in_audios++; + // track level statistic + statistic_->packets++; + statistic_->bytes += pkt->nb_bytes(); + if (source) { if ((err = source->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "source on rtp"); @@ -1680,6 +1684,10 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk // connection level statistic session_->stat_->nn_in_videos++; + // track level statistic + statistic_->packets++; + statistic_->bytes += pkt->nb_bytes(); + pkt->frame_type = SrsFrameTypeVideo; if (source) { From 5f7d1e2c5b698dd1f41efb9326d841abebf4586a Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 27 Jul 2020 12:28:15 +0800 Subject: [PATCH 05/36] RTC: Pithy print the address change --- trunk/src/app/srs_app_pithy_print.cpp | 4 ++++ trunk/src/app/srs_app_pithy_print.hpp | 2 ++ trunk/src/app/srs_app_rtc_conn.cpp | 19 +++++++++++-------- trunk/src/app/srs_app_rtc_conn.hpp | 3 +++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index 9494c13e9..e3f9e7e89 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -125,7 +125,11 @@ SrsErrorPithyPrint::~SrsErrorPithyPrint() bool SrsErrorPithyPrint::can_print(srs_error_t err) { int error_code = srs_error_code(err); + return can_print(error_code); +} +bool SrsErrorPithyPrint::can_print(int error_code) +{ bool new_stage = false; SrsStageInfo* stage = stages.fetch_or_create(error_code, &new_stage); diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index ac985fdb5..cabd6d7ff 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -77,6 +77,8 @@ public: public: // Whether specified stage is ready for print. bool can_print(srs_error_t err); + // We also support int error code. + bool can_print(int err); }; // The stage is used for a collection of object to do print, diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 093394d2c..9291f5346 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1580,6 +1580,7 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id) twcc_id_ = 0; nn_simulate_player_nack_drop = 0; + pp_address_change = new SrsErrorPithyPrint(); } SrsRtcConnection::~SrsRtcConnection() @@ -1597,6 +1598,8 @@ SrsRtcConnection::~SrsRtcConnection() SrsUdpMuxSocket* addr = it->second; srs_freep(addr); } + + srs_freep(pp_address_change); } SrsSdp* SrsRtcConnection::get_local_sdp() @@ -1934,14 +1937,6 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) return; } - // Detect address change. - if (prev_peer_id.empty()) { - srs_trace("RTC: session address init %s", peer_id.c_str()); - } else { - srs_trace("RTC: session address changed, update %s -> %s, total %u", prev_peer_id.c_str(), - peer_id.c_str(), peer_addresses_.size()); - } - // Find object from cache. SrsUdpMuxSocket* addr_cache = NULL; if (true) { @@ -1957,6 +1952,14 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) server_->insert_into_id_sessions(peer_id, this); } + // Detect address change. + if (prev_peer_id.empty()) { + srs_trace("RTC: session address init %s", peer_id.c_str()); + } else if (pp_address_change->can_print(skt->get_peer_port())) { + srs_trace("RTC: session address changed, update %s -> %s, cached=%d, total=%u", prev_peer_id.c_str(), + peer_id.c_str(), (addr_cache? 1:0), peer_addresses_.size()); + } + // Update the transport. sendonly_skt = addr_cache; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 6745d5bf7..0a5820dca 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -59,6 +59,7 @@ class SrsRtpRingBuffer; class SrsRtcConsumer; class SrsRtcAudioSendTrack; class SrsRtcVideoSendTrack; +class SrsErrorPithyPrint; const uint8_t kSR = 200; const uint8_t kRR = 201; @@ -347,6 +348,8 @@ private: int twcc_id_; // Simulators. int nn_simulate_player_nack_drop; + // Pithy print for address change, use port as error code. + SrsErrorPithyPrint* pp_address_change; public: SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id); virtual ~SrsRtcConnection(); From ca004fe33f9fac30782d5aa8e36441b09f150e2d Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 27 Jul 2020 12:44:29 +0800 Subject: [PATCH 06/36] RTC: Refine log for error pithy print --- trunk/src/app/srs_app_listener.cpp | 8 ++++---- trunk/src/app/srs_app_pithy_print.cpp | 3 +++ trunk/src/app/srs_app_pithy_print.hpp | 3 +++ trunk/src/app/srs_app_rtc_conn.cpp | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index eaa14b0be..0c4386d59 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -506,8 +506,8 @@ srs_error_t SrsUdpMuxListener::cycle() uint64_t nn_loop = 0; srs_utime_t time_last = srs_get_system_time(); - SrsErrorPithyPrint* epp = new SrsErrorPithyPrint(); - SrsAutoFree(SrsErrorPithyPrint, epp); + SrsErrorPithyPrint* pp_pkt_handler_err = new SrsErrorPithyPrint(); + SrsAutoFree(SrsErrorPithyPrint, pp_pkt_handler_err); set_socket_buffer(); @@ -542,8 +542,8 @@ srs_error_t SrsUdpMuxListener::cycle() err = handler->on_udp_packet(&skt); } if (err != srs_success) { - if (epp->can_print(err)) { - srs_warn("handle udp pkt err: %s", srs_error_desc(err).c_str()); + if (pp_pkt_handler_err->can_print(err)) { + srs_warn("handle udp pkt, count=%u, err: %s", pp_pkt_handler_err->nn_count, srs_error_desc(err).c_str()); } srs_freep(err); } diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index e3f9e7e89..3f5ca5fc8 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -116,6 +116,7 @@ SrsStageInfo* SrsStageManager::fetch_or_create(int stage_id, bool* pnew) SrsErrorPithyPrint::SrsErrorPithyPrint() { + nn_count = 0; } SrsErrorPithyPrint::~SrsErrorPithyPrint() @@ -130,6 +131,8 @@ bool SrsErrorPithyPrint::can_print(srs_error_t err) bool SrsErrorPithyPrint::can_print(int error_code) { + nn_count++; + bool new_stage = false; SrsStageInfo* stage = stages.fetch_or_create(error_code, &new_stage); diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index cabd6d7ff..970810340 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -68,6 +68,9 @@ public: // For example, we use it for error pithy print for each UDP packet processing. class SrsErrorPithyPrint { +public: + // The number of call of can_print(). + uint32_t nn_count; private: SrsStageManager stages; std::map ticks; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 9291f5346..131746a94 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1956,8 +1956,8 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) if (prev_peer_id.empty()) { srs_trace("RTC: session address init %s", peer_id.c_str()); } else if (pp_address_change->can_print(skt->get_peer_port())) { - srs_trace("RTC: session address changed, update %s -> %s, cached=%d, total=%u", prev_peer_id.c_str(), - peer_id.c_str(), (addr_cache? 1:0), peer_addresses_.size()); + srs_trace("RTC: session address change %s -> %s, cached=%d, nn_change=%u, nn_address=%u", prev_peer_id.c_str(), + peer_id.c_str(), (addr_cache? 1:0), pp_address_change->nn_count, peer_addresses_.size()); } // Update the transport. From 063c06680284725aae1f6c1094cf35a4dd2f6193 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 27 Jul 2020 12:52:46 +0800 Subject: [PATCH 07/36] RTC: Refine log --- trunk/src/app/srs_app_rtc_conn.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 131746a94..ed0341edf 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1946,13 +1946,7 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) } } - // If no cache, build cache and setup the relations in connection. - if (!addr_cache) { - peer_addresses_[peer_id] = addr_cache = skt->copy_sendonly(); - server_->insert_into_id_sessions(peer_id, this); - } - - // Detect address change. + // Show address change log. if (prev_peer_id.empty()) { srs_trace("RTC: session address init %s", peer_id.c_str()); } else if (pp_address_change->can_print(skt->get_peer_port())) { @@ -1960,6 +1954,12 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) peer_id.c_str(), (addr_cache? 1:0), pp_address_change->nn_count, peer_addresses_.size()); } + // If no cache, build cache and setup the relations in connection. + if (!addr_cache) { + peer_addresses_[peer_id] = addr_cache = skt->copy_sendonly(); + server_->insert_into_id_sessions(peer_id, this); + } + // Update the transport. sendonly_skt = addr_cache; } From 975c24b24f7ebd174ded9b15ae4c7304f13c3315 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 27 Jul 2020 16:52:44 +0800 Subject: [PATCH 08/36] RTC: Fix warnings --- trunk/src/app/srs_app_rtc_conn.cpp | 28 ++++++++++++------------ trunk/src/protocol/srs_protocol_json.cpp | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ed0341edf..0a4115764 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -805,7 +805,7 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescripti req = r->copy(); audio_tracks_.push_back(new SrsRtcAudioRecvTrack(session_, stream_desc->audio_track_desc_)); - for (int i = 0; i < stream_desc->video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)stream_desc->video_track_descs_.size(); ++i) { SrsRtcTrackDescription* desc = stream_desc->video_track_descs_.at(i); video_tracks_.push_back(new SrsRtcVideoRecvTrack(session_, desc)); } @@ -814,7 +814,7 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescripti uint32_t media_ssrc = 0; // because audio_track_desc have not twcc id, for example, h5demo // fetch twcc_id from video track description, - for (int i = 0; i < stream_desc->video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)stream_desc->video_track_descs_.size(); ++i) { SrsRtcTrackDescription* desc = stream_desc->video_track_descs_.at(i); twcc_id = desc->get_rtp_extension_id(kTWCCExt); media_ssrc = desc->ssrc_; @@ -879,12 +879,12 @@ srs_error_t SrsRtcPublishStream::send_rtcp_rr() { srs_error_t err = srs_success; - for (int i = 0; i < video_tracks_.size(); ++i) { + for (int i = 0; i < (int)video_tracks_.size(); ++i) { SrsRtcVideoRecvTrack* track = video_tracks_.at(i); track->send_rtcp_rr(); } - for (int i = 0; i < audio_tracks_.size(); ++i) { + for (int i = 0; i < (int)audio_tracks_.size(); ++i) { SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); track->send_rtcp_rr(); } @@ -898,12 +898,12 @@ srs_error_t SrsRtcPublishStream::send_rtcp_xr_rrtr() { srs_error_t err = srs_success; - for (int i = 0; i < video_tracks_.size(); ++i) { + for (int i = 0; i < (int)video_tracks_.size(); ++i) { SrsRtcVideoRecvTrack* track = video_tracks_.at(i); track->send_rtcp_xr_rrtr(); } - for (int i = 0; i < audio_tracks_.size(); ++i) { + for (int i = 0; i < (int)audio_tracks_.size(); ++i) { SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); track->send_rtcp_xr_rrtr(); } @@ -1465,7 +1465,7 @@ void SrsRtcPublishStream::simulate_drop_packet(SrsRtpHeader* h, int nn_bytes) SrsRtcVideoRecvTrack* SrsRtcPublishStream::get_video_track(uint32_t ssrc) { - for (int i = 0; i < video_tracks_.size(); ++i) { + for (int i = 0; i < (int)video_tracks_.size(); ++i) { SrsRtcVideoRecvTrack* track = video_tracks_.at(i); if (track->has_ssrc(ssrc)) { return track; @@ -1477,7 +1477,7 @@ SrsRtcVideoRecvTrack* SrsRtcPublishStream::get_video_track(uint32_t ssrc) SrsRtcAudioRecvTrack* SrsRtcPublishStream::get_audio_track(uint32_t ssrc) { - for (int i = 0; i < audio_tracks_.size(); ++i) { + for (int i = 0; i < (int)audio_tracks_.size(); ++i) { SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); if (track->has_ssrc(ssrc)) { return track; @@ -2444,7 +2444,7 @@ srs_error_t SrsRtcConnection::negotiate_publish_capability(SrsRequest* req, cons track_desc->create_auxiliary_payload(remote_media_desc.find_media_with_encoding_name("ulpfec")); std::string track_id; - for (int i = 0; i < remote_media_desc.ssrc_infos_.size(); ++i) { + for (int i = 0; i < (int)remote_media_desc.ssrc_infos_.size(); ++i) { SrsSSRCInfo ssrc_info = remote_media_desc.ssrc_infos_.at(i); // ssrc have same track id, will be description in the same track description. if(track_id != ssrc_info.msid_tracker_) { @@ -2463,7 +2463,7 @@ srs_error_t SrsRtcConnection::negotiate_publish_capability(SrsRequest* req, cons } // set track fec_ssrc and rtx_ssrc - for (int i = 0; i < remote_media_desc.ssrc_groups_.size(); ++i) { + for (int i = 0; i < (int)remote_media_desc.ssrc_groups_.size(); ++i) { SrsSSRCGroup ssrc_group = remote_media_desc.ssrc_groups_.at(i); SrsRtcTrackDescription* track_desc = stream_desc->find_track_description_by_ssrc(ssrc_group.ssrcs_[0]); if (!track_desc) { @@ -2540,7 +2540,7 @@ srs_error_t SrsRtcConnection::generate_publish_local_sdp(SrsRequest* req, SrsSdp local_media_desc.payload_types_.push_back(payload->generate_media_payload_type()); } - for (int i = 0; i < stream_desc->video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)stream_desc->video_track_descs_.size(); ++i) { SrsRtcTrackDescription* video_track = stream_desc->video_track_descs_.at(i); local_sdp.media_descs_.push_back(SrsMediaDesc("video")); @@ -2636,7 +2636,7 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S track_descs = source->get_track_desc("video", "H264"); } - for (int i = 0; i < track_descs.size(); ++i) { + for (int i = 0; i < (int)track_descs.size(); ++i) { SrsRtcTrackDescription* track = track_descs[i]->copy(); track->mid_ = remote_media_desc.mid_; uint32_t publish_ssrc = track->ssrc_; @@ -2692,7 +2692,7 @@ srs_error_t SrsRtcConnection::fetch_source_capability(SrsRequest* req, std::map< std::vector video_track_desc = source->get_track_desc("video", "H264"); track_descs.insert(track_descs.end(), video_track_desc.begin(), video_track_desc.end()); - for (int i = 0; i < track_descs.size(); ++i) { + for (int i = 0; i < (int)track_descs.size(); ++i) { SrsRtcTrackDescription* track = track_descs[i]->copy(); uint32_t publish_ssrc = track->ssrc_; @@ -2816,7 +2816,7 @@ srs_error_t SrsRtcConnection::generate_play_local_sdp(SrsRequest* req, SrsSdp& l } } - for (int i = 0; i < stream_desc->video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)stream_desc->video_track_descs_.size(); ++i) { SrsRtcTrackDescription* track = stream_desc->video_track_descs_[i]; // for plan b, we only add one m= diff --git a/trunk/src/protocol/srs_protocol_json.cpp b/trunk/src/protocol/srs_protocol_json.cpp index 0d0e1aea5..2a2117c0c 100644 --- a/trunk/src/protocol/srs_protocol_json.cpp +++ b/trunk/src/protocol/srs_protocol_json.cpp @@ -1576,7 +1576,7 @@ string escape(string v) { stringstream ss; - for (int i = 0; i < v.length(); i++) { + for (int i = 0; i < (int)v.length(); i++) { if (v.at(i) == '"') { ss << '\\'; } From 58702086cc769ed995ca9f19bd63f45ed914d549 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 27 Jul 2020 18:33:49 +0800 Subject: [PATCH 09/36] RTC: Refine code --- trunk/src/app/srs_app_rtc_conn.cpp | 52 ++++++++++++++++++++-------- trunk/src/app/srs_app_rtc_conn.hpp | 10 ++++-- trunk/src/app/srs_app_rtc_source.cpp | 1 - trunk/src/app/srs_app_rtc_source.hpp | 2 -- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 0a4115764..ec475d335 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -58,6 +58,8 @@ using namespace std; #include #include +#define SRS_TICKID_RTCP 0 + SrsSecurityTransport::SrsSecurityTransport(SrsRtcConnection* s) { session_ = s; @@ -227,6 +229,7 @@ SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, SrsContextId parent_cid) nack_enabled_ = false; _srs_config->subscribe(this); + timer_ = new SrsHourGlass(this, 1000 * SRS_UTIME_MILLISECONDS); } SrsRtcPlayStream::~SrsRtcPlayStream() @@ -234,6 +237,7 @@ SrsRtcPlayStream::~SrsRtcPlayStream() _srs_config->unsubscribe(this); srs_freep(trd); + srs_freep(timer_); if (true) { std::map::iterator it; @@ -321,6 +325,10 @@ srs_error_t SrsRtcPlayStream::start() return srs_error_wrap(err, "rtc_sender"); } + if ((err = timer_->start()) != srs_success) { + return srs_error_wrap(err, "start timer"); + } + if (_srs_rtc_hijacker) { if ((err = _srs_rtc_hijacker->on_start_play(session_, this, session_->req)) != srs_success) { return srs_error_wrap(err, "on start play"); @@ -517,6 +525,17 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u } } +srs_error_t SrsRtcPlayStream::notify(int type, srs_utime_t interval, srs_utime_t tick) +{ + srs_error_t err = srs_success; + + if (!is_started) { + return err; + } + + return err; +} + srs_error_t SrsRtcPlayStream::on_rtcp(char* data, int nb_data) { srs_error_t err = srs_success; @@ -770,7 +789,7 @@ uint32_t SrsRtcPlayStream::get_video_publish_ssrc(uint32_t play_ssrc) SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session) { - report_timer = new SrsHourGlass(this, 200 * SRS_UTIME_MILLISECONDS); + timer_ = new SrsHourGlass(this, 200 * SRS_UTIME_MILLISECONDS); session_ = session; request_keyframe_ = false; @@ -795,7 +814,7 @@ SrsRtcPublishStream::~SrsRtcPublishStream() } srs_freep(req); - srs_freep(report_timer); + srs_freep(timer_); } srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescription* stream_desc) @@ -841,17 +860,16 @@ srs_error_t SrsRtcPublishStream::start() { srs_error_t err = srs_success; - // If report_timer started, we think the publisher is started. if (is_started) { return err; } - if ((err = report_timer->tick(0 * SRS_UTIME_MILLISECONDS)) != srs_success) { - return srs_error_wrap(err, "hourglass tick"); + if ((err = timer_->tick(SRS_TICKID_RTCP, 200 * SRS_UTIME_MILLISECONDS)) != srs_success) { + return srs_error_wrap(err, "rtcp tick"); } - if ((err = report_timer->start()) != srs_success) { - return srs_error_wrap(err, "start report_timer"); + if ((err = timer_->start()) != srs_success) { + return srs_error_wrap(err, "start timer"); } if ((err = _srs_rtc_sources->fetch_or_create(req, &source)) != srs_success) { @@ -1437,14 +1455,20 @@ srs_error_t SrsRtcPublishStream::notify(int type, srs_utime_t interval, srs_utim { srs_error_t err = srs_success; - // TODO: FIXME: Check error. - send_rtcp_rr(); - send_rtcp_xr_rrtr(); + if (!is_started) { + return err; + } - // TODO: FIXME: Check error. - // We should not depends on the received packet, - // instead we should send feedback every Nms. - send_periodic_twcc(); + if (type == SRS_TICKID_RTCP) { + // TODO: FIXME: Check error. + send_rtcp_rr(); + send_rtcp_xr_rrtr(); + + // TODO: FIXME: Check error. + // We should not depends on the received packet, + // instead we should send feedback every Nms. + send_periodic_twcc(); + } return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 0a5820dca..baadfd347 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -166,13 +166,14 @@ public: }; // A RTC play stream, client pull and play stream from SRS. -class SrsRtcPlayStream : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler +class SrsRtcPlayStream : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler, virtual public ISrsHourGlass { -protected: +private: SrsContextId _parent_cid; SrsCoroutine* trd; SrsRtcConnection* session_; private: + SrsHourGlass* timer_; // key: publish_ssrc, value: send track to process rtp/rtcp std::map audio_tracks_; std::map video_tracks_; @@ -207,6 +208,9 @@ private: srs_error_t send_packets(SrsRtcStream* source, const std::vector& pkts, SrsRtcPlayStreamStatistic& info); public: void nack_fetch(std::vector& pkts, uint32_t ssrc, uint16_t seq); +// interface ISrsHourGlass +public: + virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); public: srs_error_t on_rtcp(char* data, int nb_data); private: @@ -222,7 +226,7 @@ private: class SrsRtcPublishStream : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler, virtual public ISrsRtcPublishStream { private: - SrsHourGlass* report_timer; + SrsHourGlass* timer_; uint64_t nn_audio_frames; private: SrsRtcConnection* session_; diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 6e97fde24..779473fcb 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1506,7 +1506,6 @@ SrsRtcTrackDescription* SrsRtcStreamDescription::find_track_description_by_ssrc( SrsRtcTrackStatistic::SrsRtcTrackStatistic() { - last_written = 0; packets = 0; last_packets = 0; bytes = 0; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index dcca61f61..459b38d82 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -407,8 +407,6 @@ public: class SrsRtcTrackStatistic { public: - srs_utime_t last_written; - // packets received or sent. uint32_t packets; // packets received or sent at last statistic time. From d90d42e7bfb71c134d36a6191bbff4de6a639f3e Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 28 Jul 2020 11:11:16 +0800 Subject: [PATCH 10/36] RTC: Fix warnings --- trunk/src/app/srs_app_rtc_source.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 779473fcb..f9ae9155f 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1468,7 +1468,7 @@ SrsRtcStreamDescription::~SrsRtcStreamDescription() { srs_freep(audio_track_desc_); - for (int i = 0; i < video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)video_track_descs_.size(); ++i) { srs_freep(video_track_descs_.at(i)); } video_track_descs_.clear(); @@ -1482,7 +1482,7 @@ SrsRtcStreamDescription* SrsRtcStreamDescription::copy() stream_desc->audio_track_desc_ = audio_track_desc_->copy(); } - for (int i = 0; i < video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)video_track_descs_.size(); ++i) { stream_desc->video_track_descs_.push_back(video_track_descs_.at(i)->copy()); } @@ -1495,7 +1495,7 @@ SrsRtcTrackDescription* SrsRtcStreamDescription::find_track_description_by_ssrc( return audio_track_desc_; } - for (int i = 0; i < video_track_descs_.size(); ++i) { + for (int i = 0; i < (int)video_track_descs_.size(); ++i) { if (video_track_descs_.at(i)->has_ssrc(ssrc)) { return video_track_descs_.at(i); } From 3a13d8c38098151ec7fc8e0a624e44354eab48c1 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 28 Jul 2020 17:48:19 +0800 Subject: [PATCH 11/36] RTC: Add timer for connection --- trunk/src/app/srs_app_rtc_conn.cpp | 12 ++++++++++++ trunk/src/app/srs_app_rtc_conn.hpp | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ec475d335..1c2c8c199 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1589,6 +1589,7 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id) encrypt = true; cid = context_id; stat_ = new SrsRtcConnectionStatistic(); + timer_ = new SrsHourGlass(this, 1000 * SRS_UTIME_MILLISECONDS); source_ = NULL; publisher_ = NULL; @@ -1609,6 +1610,7 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id) SrsRtcConnection::~SrsRtcConnection() { + srs_freep(timer_); srs_freep(player_); srs_freep(publisher_); srs_freep(transport_); @@ -1812,6 +1814,10 @@ srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bo return srs_error_wrap(err, "init"); } + if ((err = timer_->start()) != srs_success) { + return srs_error_wrap(err, "start timer"); + } + // TODO: FIXME: Support reload. session_timeout = _srs_config->get_rtc_stun_timeout(req->vhost); last_stun_time = srs_get_system_time(); @@ -1988,6 +1994,12 @@ void SrsRtcConnection::update_sendonly_socket(SrsUdpMuxSocket* skt) sendonly_skt = addr_cache; } +srs_error_t SrsRtcConnection::notify(int type, srs_utime_t interval, srs_utime_t tick) +{ + srs_error_t err = srs_success; + return err; +} + void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks) { // If DTLS is not OK, drop all messages. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index baadfd347..f90ae8721 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -309,7 +309,7 @@ public: }; // A RTC Peer Connection, SDP level object. -class SrsRtcConnection +class SrsRtcConnection : virtual public ISrsHourGlass { friend class SrsSecurityTransport; friend class SrsRtcPlayStream; @@ -324,6 +324,7 @@ private: SrsRtcPlayStream* player_; SrsRtcPublishStream* publisher_; bool is_publisher_; + SrsHourGlass* timer_; private: // The local:remote username, such as m5x0n128:jvOm where local name is m5x0n128. std::string username_; @@ -394,6 +395,9 @@ public: srs_error_t start_publish(); bool is_stun_timeout(); void update_sendonly_socket(SrsUdpMuxSocket* skt); +// interface ISrsHourGlass +public: + virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); public: // send rtcp void check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks); From 2dc311fbd9d7d50e867d4357d68be3c910c0c37b Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 29 Jul 2020 22:12:42 +0800 Subject: [PATCH 12/36] Refine code --- trunk/src/app/srs_app_rtc_source.cpp | 5 +++++ trunk/src/app/srs_app_rtc_source.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index f9ae9155f..f08f2b142 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1761,6 +1761,11 @@ void SrsRtcSendTrack::set_track_status(bool active) track_desc_->is_active_ = active; } +bool SrsRtcSendTrack::get_track_status() +{ + return track_desc_->is_active_; +} + std::string SrsRtcSendTrack::get_track_id() { return track_desc_->id_; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 459b38d82..a4ba09973 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -511,6 +511,7 @@ public: bool has_ssrc(uint32_t ssrc); SrsRtpPacket2* fetch_rtp_packet(uint16_t seq); void set_track_status(bool active); + bool get_track_status(); std::string get_track_id(); public: virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info); From 8e22508057419659325a4c14cef3126e7f3a31e7 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 30 Jul 2020 18:54:16 +0800 Subject: [PATCH 13/36] Refine utest --- trunk/src/kernel/srs_kernel_rtc_rtcp.cpp | 60 ++++++++++++------------ trunk/src/kernel/srs_kernel_rtc_rtcp.hpp | 60 ++++++++++++------------ trunk/src/utest/srs_utest.cpp | 2 +- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp index d6aa1eee4..ef51e4ff3 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp @@ -37,7 +37,7 @@ SrsRtcpCommon::~SrsRtcpCommon() { } -const uint8_t SrsRtcpCommon::type() const +uint8_t SrsRtcpCommon::type() const { return header_.type; } @@ -90,27 +90,27 @@ SrsRtcpApp::~SrsRtcpApp() { } -const uint8_t SrsRtcpApp::type() const +uint8_t SrsRtcpApp::type() const { return SrsRtcpType_app; } -const uint32_t SrsRtcpApp::get_ssrc() const +uint32_t SrsRtcpApp::get_ssrc() const { return ssrc_; } -const uint8_t SrsRtcpApp::get_subtype() const +uint8_t SrsRtcpApp::get_subtype() const { return header_.rc; } -const string SrsRtcpApp::get_name() const +string SrsRtcpApp::get_name() const { return string((char*)name_); } -const srs_error_t SrsRtcpApp::get_payload(uint8_t*& payload, int& len) +srs_error_t SrsRtcpApp::get_payload(uint8_t*& payload, int& len) { len = payload_len_; payload = payload_; @@ -213,37 +213,37 @@ SrsRtcpSR::~SrsRtcpSR() { } -const uint8_t SrsRtcpSR::get_rc() const +uint8_t SrsRtcpSR::get_rc() const { return header_.rc; } -const uint8_t SrsRtcpSR::type() const +uint8_t SrsRtcpSR::type() const { return SrsRtcpType_sr; } -const uint32_t SrsRtcpSR::get_sender_ssrc() const +uint32_t SrsRtcpSR::get_sender_ssrc() const { return sender_ssrc_; } -const uint64_t SrsRtcpSR::get_ntp() const +uint64_t SrsRtcpSR::get_ntp() const { return ntp_; } -const uint32_t SrsRtcpSR::get_rtp_ts() const +uint32_t SrsRtcpSR::get_rtp_ts() const { return rtp_ts_; } -const uint32_t SrsRtcpSR::get_rtp_send_packets() const +uint32_t SrsRtcpSR::get_rtp_send_packets() const { return send_rtp_packets_; } -const uint32_t SrsRtcpSR::get_rtp_send_bytes() const +uint32_t SrsRtcpSR::get_rtp_send_bytes() const { return send_rtp_bytes_; } @@ -334,42 +334,42 @@ SrsRtcpRR::~SrsRtcpRR() { } -const uint8_t SrsRtcpRR::type() const +uint8_t SrsRtcpRR::type() const { return SrsRtcpType_rr; } -const uint32_t SrsRtcpRR::get_rb_ssrc() const +uint32_t SrsRtcpRR::get_rb_ssrc() const { return rb_.ssrc; } -const float SrsRtcpRR::get_lost_rate() const +float SrsRtcpRR::get_lost_rate() const { return rb_.fraction_lost / 256; } -const uint32_t SrsRtcpRR::get_lost_packets() const +uint32_t SrsRtcpRR::get_lost_packets() const { return rb_.lost_packets; } -const uint32_t SrsRtcpRR::get_highest_sn() const +uint32_t SrsRtcpRR::get_highest_sn() const { return rb_.highest_sn; } -const uint32_t SrsRtcpRR::get_jitter() const +uint32_t SrsRtcpRR::get_jitter() const { return rb_.jitter; } -const uint32_t SrsRtcpRR::get_lsr() const +uint32_t SrsRtcpRR::get_lsr() const { return rb_.lsr; } -const uint32_t SrsRtcpRR::get_dlsr() const +uint32_t SrsRtcpRR::get_dlsr() const { return rb_.dlsr; } @@ -493,36 +493,36 @@ void SrsRtcpTWCC::clear() recv_sns_.clear(); } -const uint32_t SrsRtcpTWCC::get_media_ssrc() const +uint32_t SrsRtcpTWCC::get_media_ssrc() const { return media_ssrc_; } -const uint16_t SrsRtcpTWCC::get_base_sn() const +uint16_t SrsRtcpTWCC::get_base_sn() const { return base_sn_; } -const uint32_t SrsRtcpTWCC::get_reference_time() const +uint32_t SrsRtcpTWCC::get_reference_time() const { return reference_time_; } -const uint8_t SrsRtcpTWCC::get_feedback_count() const +uint8_t SrsRtcpTWCC::get_feedback_count() const { return fb_pkt_count_; } -const uint16_t SrsRtcpTWCC::get_packet_status_count() const +uint16_t SrsRtcpTWCC::get_packet_status_count() const { return packet_count_; } -const vector SrsRtcpTWCC::get_packet_chucks() const +vector SrsRtcpTWCC::get_packet_chucks() const { return encoded_chucks_; } -const vector SrsRtcpTWCC::get_recv_deltas() const +vector SrsRtcpTWCC::get_recv_deltas() const { return pkt_deltas_; } @@ -887,12 +887,12 @@ SrsRtcpNack::~SrsRtcpNack() { } -const uint32_t SrsRtcpNack::get_media_ssrc() const +uint32_t SrsRtcpNack::get_media_ssrc() const { return media_ssrc_; } -const vector SrsRtcpNack::get_lost_sns() const +vector SrsRtcpNack::get_lost_sns() const { vector sn; for(set::iterator it = lost_sns_.begin(); it != lost_sns_.end(); ++it) { diff --git a/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp index acb04ec24..de311305b 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp @@ -73,7 +73,7 @@ protected: public: SrsRtcpCommon(); virtual ~SrsRtcpCommon(); - virtual const uint8_t type() const; + virtual uint8_t type() const; // interface ISrsCodec public: virtual srs_error_t decode(SrsBuffer *buffer); @@ -93,12 +93,12 @@ public: SrsRtcpApp(); virtual ~SrsRtcpApp(); - virtual const uint8_t type() const; + virtual uint8_t type() const; - const uint32_t get_ssrc() const; - const uint8_t get_subtype() const; - const std::string get_name() const; - const srs_error_t get_payload(uint8_t*& payload, int& len); + uint32_t get_ssrc() const; + uint8_t get_subtype() const; + std::string get_name() const; + srs_error_t get_payload(uint8_t*& payload, int& len); void set_ssrc(uint32_t ssrc); srs_error_t set_subtype(uint8_t type); @@ -134,14 +134,14 @@ public: SrsRtcpSR(); virtual ~SrsRtcpSR(); - const uint8_t get_rc() const; + uint8_t get_rc() const; // overload SrsRtcpCommon - virtual const uint8_t type() const; - const uint32_t get_sender_ssrc() const; - const uint64_t get_ntp() const; - const uint32_t get_rtp_ts() const; - const uint32_t get_rtp_send_packets() const; - const uint32_t get_rtp_send_bytes() const; + virtual uint8_t type() const; + uint32_t get_sender_ssrc() const; + uint64_t get_ntp() const; + uint32_t get_rtp_ts() const; + uint32_t get_rtp_send_packets() const; + uint32_t get_rtp_send_bytes() const; void set_sender_ssrc(uint32_t ssrc); void set_ntp(uint64_t ntp); @@ -165,15 +165,15 @@ public: virtual ~SrsRtcpRR(); // overload SrsRtcpCommon - virtual const uint8_t type() const; + virtual uint8_t type() const; - const uint32_t get_rb_ssrc() const; - const float get_lost_rate() const; - const uint32_t get_lost_packets() const; - const uint32_t get_highest_sn() const; - const uint32_t get_jitter() const; - const uint32_t get_lsr() const; - const uint32_t get_dlsr() const; + uint32_t get_rb_ssrc() const; + float get_lost_rate() const; + uint32_t get_lost_packets() const; + uint32_t get_highest_sn() const; + uint32_t get_jitter() const; + uint32_t get_lsr() const; + uint32_t get_dlsr() const; void set_rb_ssrc(uint32_t ssrc); void set_lost_rate(float rate); @@ -271,13 +271,13 @@ public: SrsRtcpTWCC(uint32_t sender_ssrc = 0); virtual ~SrsRtcpTWCC(); - const uint32_t get_media_ssrc() const; - const uint16_t get_base_sn() const; - const uint16_t get_packet_status_count() const; - const uint32_t get_reference_time() const; - const uint8_t get_feedback_count() const; - const std::vector get_packet_chucks() const; - const std::vector get_recv_deltas() const; + uint32_t get_media_ssrc() const; + uint16_t get_base_sn() const; + uint16_t get_packet_status_count() const; + uint32_t get_reference_time() const; + uint8_t get_feedback_count() const; + std::vector get_packet_chucks() const; + std::vector get_recv_deltas() const; void set_media_ssrc(uint32_t ssrc); void set_base_sn(uint16_t sn); @@ -313,8 +313,8 @@ public: SrsRtcpNack(uint32_t sender_ssrc = 0); virtual ~SrsRtcpNack(); - const uint32_t get_media_ssrc() const; - const std::vector get_lost_sns() const; + uint32_t get_media_ssrc() const; + std::vector get_lost_sns() const; void set_media_ssrc(uint32_t ssrc); void add_lost_sn(uint16_t sn); diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index 20a691a15..286b925e6 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -43,7 +43,7 @@ srs_utime_t _srs_tmp_timeout = (100 * SRS_UTIME_MILLISECONDS); ISrsLog* _srs_log = new MockEmptyLog(SrsLogLevelDisabled); ISrsContext* _srs_context = new SrsThreadContext(); // app module. -SrsConfig* _srs_config = NULL; +SrsConfig* _srs_config = new SrsConfig(); SrsServer* _srs_server = NULL; bool _srs_in_docker = false; From 0408040ed75e3b933f19d27190581f40b8cb57d2 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 30 Jul 2020 19:26:28 +0800 Subject: [PATCH 14/36] Fix utest fail for C++11 or C++14 --- trunk/auto/utest.sh | 2 +- trunk/src/utest/srs_utest.hpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/trunk/auto/utest.sh b/trunk/auto/utest.sh index e7ce6a4a1..f29d698ba 100755 --- a/trunk/auto/utest.sh +++ b/trunk/auto/utest.sh @@ -49,7 +49,7 @@ USER_DIR = . CPPFLAGS += -I\$(GTEST_DIR)/include # Flags passed to the C++ compiler. -CXXFLAGS += ${CXXFLAGS} -Wextra ${UTEST_EXTRA_DEFINES} +CXXFLAGS += ${CXXFLAGS} ${UTEST_EXTRA_DEFINES} -Wno-unused-private-field -Wno-unused-command-line-argument # All tests produced by this Makefile. Remember to add new tests you # created to the list. diff --git a/trunk/src/utest/srs_utest.hpp b/trunk/src/utest/srs_utest.hpp index bf2f26c8a..252c9928f 100644 --- a/trunk/src/utest/srs_utest.hpp +++ b/trunk/src/utest/srs_utest.hpp @@ -24,6 +24,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SRS_UTEST_PUBLIC_SHARED_HPP #define SRS_UTEST_PUBLIC_SHARED_HPP +// Before define the private/protected, we must include some system header files. +// Or it may fail with: +// redeclared with different access struct __xfer_bufptrs +// @see https://stackoverflow.com/questions/47839718/sstream-redeclared-with-public-access-compiler-error +#include "gtest/gtest.h" + // Public all private and protected members. #define private public #define protected public @@ -33,7 +39,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include -#include "gtest/gtest.h" #include using namespace std; From 8aa20d390e2b9a1babc9ae81462ae28ea9200ab1 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 12:36:34 +0800 Subject: [PATCH 15/36] RTC: Disable track by default --- trunk/src/app/srs_app_rtc_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index f08f2b142..579b4af1d 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1349,7 +1349,7 @@ SrsRtcTrackDescription::SrsRtcTrackDescription() ssrc_ = 0; rtx_ssrc_ = 0; fec_ssrc_ = 0; - is_active_ = true; + is_active_ = false; media_ = NULL; red_ = NULL; From 0eae1bd493781fa85f3a3cddf02ca951af2512aa Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 12:49:12 +0800 Subject: [PATCH 16/36] RTC: Enable track of player when init done. --- trunk/src/app/srs_app_rtc_conn.cpp | 42 +++++++++++++++++++++++++++ trunk/src/app/srs_app_rtc_conn.hpp | 4 +++ trunk/src/app/srs_app_rtc_server.cpp | 4 +++ trunk/src/app/srs_app_rtc_source.cpp | 4 ++- trunk/src/app/srs_app_rtc_source.hpp | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 1 + 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 1c2c8c199..03eddcdea 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -525,6 +525,35 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u } } +void SrsRtcPlayStream::set_track_status(bool status) +{ + std::ostringstream merged_log; + + // set video track status + if (true) { + std::map::iterator it; + for (it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { + SrsRtcVideoSendTrack* track = it->second; + + bool previous = track->set_track_status(status); + merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},"; + } + } + + // set audio track status + if (true) { + std::map::iterator it; + for (it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { + SrsRtcAudioSendTrack* track = it->second; + + bool previous = track->set_track_status(status); + merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},"; + } + } + + srs_trace("set status, %s", merged_log.str().c_str()); +} + srs_error_t SrsRtcPlayStream::notify(int type, srs_utime_t interval, srs_utime_t tick) { srs_error_t err = srs_success; @@ -2276,6 +2305,19 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& return err; } +srs_error_t SrsRtcConnection::set_play_track_status(bool status) +{ + srs_error_t err = srs_success; + + if (!player_) { + return srs_error_new(ERROR_RTC_NO_PLAYER, "set play track status"); + } + + player_->set_track_status(status); + + return err; +} + #ifdef SRS_OSX // These functions are similar to the older byteorder(3) family of functions. // For example, be32toh() is identical to ntohl(). diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index f90ae8721..240da89d6 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -208,6 +208,8 @@ private: srs_error_t send_packets(SrsRtcStream* source, const std::vector& pkts, SrsRtcPlayStreamStatistic& info); public: void nack_fetch(std::vector& pkts, uint32_t ssrc, uint16_t seq); + // Directly set the status of track, generally for init to set the default value. + void set_track_status(bool status); // interface ISrsHourGlass public: virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); @@ -409,6 +411,8 @@ public: void simulate_nack_drop(int nn); void simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes); srs_error_t do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info); + // Directly set the status of play track, generally for init to set the default value. + srs_error_t set_play_track_status(bool status); private: srs_error_t on_binding_request(SrsStunPacket* r); // publish media capabilitiy negotiate diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index ea5280895..8991f1b9d 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -413,6 +413,10 @@ srs_error_t SrsRtcServer::do_create_session( if ((err = session->add_player(req, remote_sdp, local_sdp)) != srs_success) { return srs_error_wrap(err, "add player"); } + + // TODO: FIXME: Handle error. + // All tracks default as inactive, so we must enable them. + session->set_play_track_status(true); } std::string local_pwd = srs_random_str(32); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 579b4af1d..da49573ac 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1756,9 +1756,11 @@ SrsRtpPacket2* SrsRtcSendTrack::fetch_rtp_packet(uint16_t seq) } // TODO: FIXME: Should refine logs, set tracks in a time. -void SrsRtcSendTrack::set_track_status(bool active) +bool SrsRtcSendTrack::set_track_status(bool active) { + bool previous_status = track_desc_->is_active_; track_desc_->is_active_ = active; + return previous_status; } bool SrsRtcSendTrack::get_track_status() diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index a4ba09973..ecfad71f5 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -510,7 +510,7 @@ public: public: bool has_ssrc(uint32_t ssrc); SrsRtpPacket2* fetch_rtp_packet(uint16_t seq); - void set_track_status(bool active); + bool set_track_status(bool active); bool get_track_status(); std::string get_track_id(); public: diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 111338f04..e77923ae1 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -356,6 +356,7 @@ #define ERROR_RTC_STREM_STARTED 5025 #define ERROR_RTC_STREAM_DESC 5026 #define ERROR_RTC_TRACK_CODEC 5027 +#define ERROR_RTC_NO_PLAYER 5028 /////////////////////////////////////////////////////// // GB28181 API error. From c72fb76334311843f1d3b1b578bfd46c4fa76742 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 13:10:00 +0800 Subject: [PATCH 17/36] RTC: Cover default track status --- trunk/src/utest/srs_utest_rtc.cpp | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 270753c44..5cde08cc3 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include VOID TEST(KernelRTCTest, SequenceCompare) { @@ -123,3 +125,35 @@ VOID TEST(KernelRTCTest, SequenceCompare) } } +VOID TEST(KernelRTCTest, DefaultTrackStatus) +{ + // By default, track is disabled. + if (true) { + SrsRtcTrackDescription td; + + // The track must default to disable, that is, the active is false. + EXPECT_FALSE(td.is_active_); + } + + // Enable it by player or connection. + if (true) { + SrsRtcConnection s(NULL, SrsContextId()); SrsRtcPlayStream play(&s, SrsContextId()); + SrsRtcAudioSendTrack* audio; SrsRtcVideoSendTrack *video; + + if (true) { + SrsRtcTrackDescription ds; ds.type_ = "audio"; ds.id_ = "NSNWOn19NDn12o8nNeji2"; ds.ssrc_ = 100; + play.audio_tracks_[ds.ssrc_] = audio = new SrsRtcAudioSendTrack(&s, &ds); + } + if (true) { + SrsRtcTrackDescription ds; ds.type_ = "video"; ds.id_ = "VMo22nfLDn122nfnDNL2"; ds.ssrc_ = 200; + play.video_tracks_[ds.ssrc_] = video = new SrsRtcVideoSendTrack(&s, &ds); + } + EXPECT_FALSE(audio->get_track_status()); + EXPECT_FALSE(video->get_track_status()); + + play.set_track_status(true); + EXPECT_TRUE(audio->get_track_status()); + EXPECT_TRUE(video->get_track_status()); + } +} + From 4aabbd74dce704f9cca15ef05c5cc35507213a61 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 13:12:39 +0800 Subject: [PATCH 18/36] RTC: Cover default status of track --- trunk/src/app/srs_app_rtc_conn.cpp | 6 +++--- trunk/src/app/srs_app_rtc_conn.hpp | 4 ++-- trunk/src/app/srs_app_rtc_server.cpp | 2 +- trunk/src/utest/srs_utest_rtc.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 03eddcdea..6fb1f3e30 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -525,7 +525,7 @@ void SrsRtcPlayStream::nack_fetch(vector& pkts, uint32_t ssrc, u } } -void SrsRtcPlayStream::set_track_status(bool status) +void SrsRtcPlayStream::set_all_tracks_status(bool status) { std::ostringstream merged_log; @@ -2305,7 +2305,7 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& return err; } -srs_error_t SrsRtcConnection::set_play_track_status(bool status) +srs_error_t SrsRtcConnection::set_all_tracks_status_for_play(bool status) { srs_error_t err = srs_success; @@ -2313,7 +2313,7 @@ srs_error_t SrsRtcConnection::set_play_track_status(bool status) return srs_error_new(ERROR_RTC_NO_PLAYER, "set play track status"); } - player_->set_track_status(status); + player_->set_all_tracks_status(status); return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 240da89d6..59814ab73 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -209,7 +209,7 @@ private: public: void nack_fetch(std::vector& pkts, uint32_t ssrc, uint16_t seq); // Directly set the status of track, generally for init to set the default value. - void set_track_status(bool status); + void set_all_tracks_status(bool status); // interface ISrsHourGlass public: virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); @@ -412,7 +412,7 @@ public: void simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes); srs_error_t do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info); // Directly set the status of play track, generally for init to set the default value. - srs_error_t set_play_track_status(bool status); + srs_error_t set_all_tracks_status_for_play(bool status); private: srs_error_t on_binding_request(SrsStunPacket* r); // publish media capabilitiy negotiate diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 8991f1b9d..da19ccab0 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -416,7 +416,7 @@ srs_error_t SrsRtcServer::do_create_session( // TODO: FIXME: Handle error. // All tracks default as inactive, so we must enable them. - session->set_play_track_status(true); + session->set_all_tracks_status_for_play(true); } std::string local_pwd = srs_random_str(32); diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 5cde08cc3..f88ae78bc 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -151,7 +151,7 @@ VOID TEST(KernelRTCTest, DefaultTrackStatus) EXPECT_FALSE(audio->get_track_status()); EXPECT_FALSE(video->get_track_status()); - play.set_track_status(true); + play.set_all_tracks_status(true); EXPECT_TRUE(audio->get_track_status()); EXPECT_TRUE(video->get_track_status()); } From a40abf8df2b3ed2e2b292851786e2488b1389fd5 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 18:18:15 +0800 Subject: [PATCH 19/36] RTC: Refine error log --- trunk/src/app/srs_app_listener.cpp | 12 +++++++++++- trunk/src/app/srs_app_rtc_server.cpp | 9 +++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 0c4386d59..7094bdbcf 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -42,13 +42,15 @@ using namespace std; #include #include - // set the max packet size. #define SRS_UDP_MAX_PACKET_SIZE 65535 // sleep in srs_utime_t for udp recv packet. #define SrsUdpPacketRecvCycleInterval 0 +// Set the byte at specified position. +#define _srs_set_byte(data, size, b, index) if (index < size) b = data[index] + ISrsUdpHandler::ISrsUdpHandler() { } @@ -541,8 +543,16 @@ srs_error_t SrsUdpMuxListener::cycle() SrsContextRestore(cid); err = handler->on_udp_packet(&skt); } + // Use pithy print to show more smart information. if (err != srs_success) { if (pp_pkt_handler_err->can_print(err)) { + // Append more information. + if (true) { + char* data = skt.data(); int size = skt.size(); + uint8_t b0 = 0, b1 = 0; _srs_set_byte(data, size, b0, 0); _srs_set_byte(data, size, b1, 1); uint8_t b2 = 0, b3 = 0; _srs_set_byte(data, size, b2, 2); _srs_set_byte(data, size, b3, 3); + uint8_t b4 = 0, b5 = 0; _srs_set_byte(data, size, b4, 4); _srs_set_byte(data, size, b5, 5); uint8_t b6 = 0, b7 = 0; _srs_set_byte(data, size, b6, 6); _srs_set_byte(data, size, b7, 7); + err = srs_error_wrap(err, "size=%u, data=[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]", size, b0, b1, b2, b3, b4, b5, b6, b7); + } srs_warn("handle udp pkt, count=%u, err: %s", pp_pkt_handler_err->nn_count, srs_error_desc(err).c_str()); } srs_freep(err); diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index da19ccab0..ccafc026e 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -309,7 +309,6 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) srs_info("recv stun packet from %s, use-candidate=%d, ice-controlled=%d, ice-controlling=%d", peer_id.c_str(), ping.get_use_candidate(), ping.get_ice_controlled(), ping.get_ice_controlling()); - // TODO: FIXME: For ICE trickle, we may get STUN packets before SDP answer, so maybe should response it. if (!session) { session = find_session_by_username(ping.get_username()); @@ -318,8 +317,10 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) session->switch_to_context(); } } + + // TODO: FIXME: For ICE trickle, we may get STUN packets before SDP answer, so maybe should response it. if (!session) { - return srs_error_new(ERROR_RTC_STUN, "can not find session, stun username=%s, peer_id=%s", + return srs_error_new(ERROR_RTC_STUN, "no session, stun username=%s, peer_id=%s", ping.get_username().c_str(), peer_id.c_str()); } @@ -328,7 +329,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) // For DTLS, RTCP or RTP, which does not support peer address changing. if (!session) { - return srs_error_new(ERROR_RTC_STUN, "can not find session, peer_id=%s", peer_id.c_str()); + return srs_error_new(ERROR_RTC_STUN, "no session, peer_id=%s", peer_id.c_str()); } if (is_dtls((uint8_t*)data, size)) { @@ -340,7 +341,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) return session->on_rtp(data, size); } - return srs_error_new(ERROR_RTC_UDP, "unknown udp packet type"); + return srs_error_new(ERROR_RTC_UDP, "unknown packet"); } srs_error_t SrsRtcServer::listen_api() From 0905558d49494b4b2687adbdad4890ad04a71ebc Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 19:28:52 +0800 Subject: [PATCH 20/36] BUILD: Compatible with 3.0 options, ignore it --- trunk/auto/options.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 934759de3..e195c3cb5 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -488,24 +488,24 @@ function apply_detail_options() { # if specified export single file, export project first. if [ $SRS_EXPORT_LIBRTMP_SINGLE != NO ]; then - echo "Not support --export-librtmp-single" - exit -1 + echo "Warning: Ingore --export-librtmp-single" + SRS_EXPORT_LIBRTMP_SINGLE=NO fi # disable almost all features for export srs-librtmp. if [ $SRS_EXPORT_LIBRTMP_PROJECT != NO ]; then - echo "Not support --export-librtmp-project" - exit -1 + echo "Warning: Ingore --export-librtmp-project" + SRS_EXPORT_LIBRTMP_PROJECT=NO fi if [[ $SRS_LIBRTMP != NO ]]; then - echo "Not support --librtmp" - exit -1 + echo "Warning: Ingore --librtmp" + SRS_LIBRTMP=NO fi if [[ $SRS_RESEARCH != NO ]]; then - echo "Not support --research" - exit -1 + echo "Warning: Ingore --research" + SRS_RESEARCH=NO fi if [[ $SRS_SRTP_ASM == YES && $SRS_RTC == NO ]]; then From b847a0a218d1b9491e9f4fae8afc725a676a1721 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 19:31:14 +0800 Subject: [PATCH 21/36] BUILD: Compatible with 3.0 options, ignore it --- trunk/auto/options.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index e195c3cb5..7d1da01ab 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -590,11 +590,13 @@ function check_option_conflicts() { fi if [[ $SRS_CROSS_BUILD == YES && ($SRS_TOOL_CC == 'gcc' || $SRS_TOOL_CXX == 'g++' || $SRS_TOOL_AR == 'ar') ]]; then - echo "For crossbuild, must not use default toolchain, cc: $SRS_TOOL_CC, cxx: $SRS_TOOL_CXX, ar: $SRS_TOOL_AR"; exit -1 + echo "Warning: For crossbuild, must not use default toolchain, cc: $SRS_TOOL_CC, cxx: $SRS_TOOL_CXX, ar: $SRS_TOOL_AR" + SRS_CROSS_BUILD=NO fi if [[ $SRS_NGINX == YES ]]; then - echo "Don't support building NGINX, please use docker https://github.com/ossrs/srs-docker"; exit -1; + echo "Warning: Don't support building NGINX, please use docker https://github.com/ossrs/srs-docker" + SRS_NGINX=NO fi # For OSX, recommend to use DTrace, https://blog.csdn.net/win_lin/article/details/53503869 From dd138897728a2fd68a7f372bc168a37e8435453e Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 3 Aug 2020 19:33:34 +0800 Subject: [PATCH 22/36] BUILD: Compatible with 3.0 options, ignore it --- trunk/auto/depends.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index c42542d8f..d646dbf33 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -666,14 +666,15 @@ if [ $SRS_FFMPEG_TOOL = YES ]; then if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg/bin/ffmpeg ]]; then echo "ffmpeg-4.1 is ok."; else - echo "Error: no FFmpeg found at /usr/local/bin/ffmpeg"; + echo "Warning: No FFmpeg found at /usr/local/bin/ffmpeg"; echo " please copy it from srs-docker"; echo " or download from http://ffmpeg.org/download.html"; echo " or disable it by --without-ffmpeg"; - exit -1; fi # Always update the links. - (cd ${SRS_OBJS} && rm -rf ffmpeg && ln -sf ${SRS_PLATFORM}/ffmpeg) + if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg ]]; then + (cd ${SRS_OBJS} && rm -rf ffmpeg && ln -sf ${SRS_PLATFORM}/ffmpeg) + fi fi ##################################################################################### From c659098f71d3aa4030bef6a2f70cadf2dcdbbd70 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 13:45:17 +0800 Subject: [PATCH 23/36] RTC: Set tracks to active for publisher --- trunk/src/app/srs_app_rtc_conn.cpp | 45 ++++++++++++++++++++++------ trunk/src/app/srs_app_rtc_conn.hpp | 4 ++- trunk/src/app/srs_app_rtc_server.cpp | 7 ++--- trunk/src/app/srs_app_rtc_source.cpp | 17 +++++++++++ trunk/src/app/srs_app_rtc_source.hpp | 3 ++ trunk/src/utest/srs_utest_rtc.cpp | 23 +++++++++++++- 6 files changed, 84 insertions(+), 15 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 6fb1f3e30..be85223ab 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -551,7 +551,7 @@ void SrsRtcPlayStream::set_all_tracks_status(bool status) } } - srs_trace("set status, %s", merged_log.str().c_str()); + srs_trace("RTC: Init tracks %s ok", merged_log.str().c_str()); } srs_error_t SrsRtcPlayStream::notify(int type, srs_utime_t interval, srs_utime_t tick) @@ -922,6 +922,35 @@ srs_error_t SrsRtcPublishStream::start() return err; } +void SrsRtcPublishStream::set_all_tracks_status(bool status) +{ + std::ostringstream merged_log; + + // set video track status + if (true) { + std::vector::iterator it; + for (it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { + SrsRtcVideoRecvTrack* track = *it; + + bool previous = track->set_track_status(status); + merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},"; + } + } + + // set audio track status + if (true) { + std::vector::iterator it; + for (it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { + SrsRtcAudioRecvTrack* track = *it; + + bool previous = track->set_track_status(status); + merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},"; + } + } + + srs_trace("RTC: Init tracks %s ok", merged_log.str().c_str()); +} + srs_error_t SrsRtcPublishStream::send_rtcp_rr() { srs_error_t err = srs_success; @@ -2305,17 +2334,15 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& return err; } -srs_error_t SrsRtcConnection::set_all_tracks_status_for_play(bool status) +void SrsRtcConnection::set_all_tracks_status(bool status) { - srs_error_t err = srs_success; - - if (!player_) { - return srs_error_new(ERROR_RTC_NO_PLAYER, "set play track status"); + if (player_) { + player_->set_all_tracks_status(status); } - player_->set_all_tracks_status(status); - - return err; + if (publisher_) { + publisher_->set_all_tracks_status(status); + } } #ifdef SRS_OSX diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 59814ab73..607bcb6ad 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -259,6 +259,8 @@ public: public: srs_error_t initialize(SrsRequest* req, SrsRtcStreamDescription* stream_desc); srs_error_t start(); + // Directly set the status of track, generally for init to set the default value. + void set_all_tracks_status(bool status); private: srs_error_t send_rtcp_rr(); srs_error_t send_rtcp_xr_rrtr(); @@ -412,7 +414,7 @@ public: void simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes); srs_error_t do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info); // Directly set the status of play track, generally for init to set the default value. - srs_error_t set_all_tracks_status_for_play(bool status); + void set_all_tracks_status(bool status); private: srs_error_t on_binding_request(SrsStunPacket* r); // publish media capabilitiy negotiate diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index ccafc026e..38a20856e 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -414,12 +414,11 @@ srs_error_t SrsRtcServer::do_create_session( if ((err = session->add_player(req, remote_sdp, local_sdp)) != srs_success) { return srs_error_wrap(err, "add player"); } - - // TODO: FIXME: Handle error. - // All tracks default as inactive, so we must enable them. - session->set_all_tracks_status_for_play(true); } + // All tracks default as inactive, so we must enable them. + session->set_all_tracks_status(true); + std::string local_pwd = srs_random_str(32); std::string local_ufrag = ""; // TODO: FIXME: Rename for a better name, it's not an username. diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index da49573ac..a72153473 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1589,6 +1589,23 @@ srs_error_t SrsRtcRecvTrack::send_rtcp_xr_rrtr() return err; } +bool SrsRtcRecvTrack::set_track_status(bool active) +{ + bool previous_status = track_desc_->is_active_; + track_desc_->is_active_ = active; + return previous_status; +} + +bool SrsRtcRecvTrack::get_track_status() +{ + return track_desc_->is_active_; +} + +std::string SrsRtcRecvTrack::get_track_id() +{ + return track_desc_->id_; +} + srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index ecfad71f5..60033408e 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -465,6 +465,9 @@ public: void update_send_report_time(const SrsNtp& ntp); srs_error_t send_rtcp_rr(); srs_error_t send_rtcp_xr_rrtr(); + bool set_track_status(bool active); + bool get_track_status(); + std::string get_track_id(); protected: srs_error_t on_nack(SrsRtpPacket2* pkt); public: diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index f88ae78bc..7ceeb8d96 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -135,7 +135,7 @@ VOID TEST(KernelRTCTest, DefaultTrackStatus) EXPECT_FALSE(td.is_active_); } - // Enable it by player or connection. + // Enable it by player. if (true) { SrsRtcConnection s(NULL, SrsContextId()); SrsRtcPlayStream play(&s, SrsContextId()); SrsRtcAudioSendTrack* audio; SrsRtcVideoSendTrack *video; @@ -155,5 +155,26 @@ VOID TEST(KernelRTCTest, DefaultTrackStatus) EXPECT_TRUE(audio->get_track_status()); EXPECT_TRUE(video->get_track_status()); } + + // Enable it by publisher. + if (true) { + SrsRtcConnection s(NULL, SrsContextId()); SrsRtcPublishStream publish(&s); + SrsRtcAudioRecvTrack* audio; SrsRtcVideoRecvTrack *video; + + if (true) { + SrsRtcTrackDescription ds; ds.type_ = "audio"; ds.id_ = "NSNWOn19NDn12o8nNeji2"; ds.ssrc_ = 100; + audio = new SrsRtcAudioRecvTrack(&s, &ds); publish.audio_tracks_.push_back(audio); + } + if (true) { + SrsRtcTrackDescription ds; ds.type_ = "video"; ds.id_ = "VMo22nfLDn122nfnDNL2"; ds.ssrc_ = 200; + video = new SrsRtcVideoRecvTrack(&s, &ds); publish.video_tracks_.push_back(video); + } + EXPECT_FALSE(audio->get_track_status()); + EXPECT_FALSE(video->get_track_status()); + + publish.set_all_tracks_status(true); + EXPECT_TRUE(audio->get_track_status()); + EXPECT_TRUE(video->get_track_status()); + } } From baceb7f6b035c9f0f97bad00e4584428c7b097b2 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 14:07:15 +0800 Subject: [PATCH 24/36] RTC: Fix the SDP encode issue --- trunk/src/app/srs_app_rtc_api.cpp | 8 ++++++-- trunk/src/app/srs_app_rtc_sdp.cpp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp index 3a5791cb2..52c78cf45 100644 --- a/trunk/src/app/srs_app_rtc_api.cpp +++ b/trunk/src/app/srs_app_rtc_api.cpp @@ -195,6 +195,8 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe } string local_sdp_str = os.str(); + // Filter the \r\n to \\r\\n for JSON. + local_sdp_str = srs_string_replace(local_sdp_str.c_str(), "\r\n", "\\r\\n"); res->set("code", SrsJsonAny::integer(ERROR_SUCCESS)); res->set("server", SrsJsonAny::integer(SrsStatistic::instance()->server_id())); @@ -207,7 +209,7 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe srs_trace("RTC username=%s, offer=%dB, answer=%dB", session->username().c_str(), remote_sdp_str.length(), local_sdp_str.length()); srs_trace("RTC remote offer: %s", srs_string_replace(remote_sdp_str.c_str(), "\r\n", "\\r\\n").c_str()); - srs_trace("RTC local answer: %s", srs_string_replace(local_sdp_str.c_str(), "\r\n", "\\r\\n").c_str()); + srs_trace("RTC local answer: %s", local_sdp_str.c_str()); return err; } @@ -545,6 +547,8 @@ srs_error_t SrsGoApiRtcPublish::do_serve_http(ISrsHttpResponseWriter* w, ISrsHtt } string local_sdp_str = os.str(); + // Filter the \r\n to \\r\\n for JSON. + local_sdp_str = srs_string_replace(local_sdp_str.c_str(), "\r\n", "\\r\\n"); res->set("code", SrsJsonAny::integer(ERROR_SUCCESS)); res->set("server", SrsJsonAny::integer(SrsStatistic::instance()->server_id())); @@ -557,7 +561,7 @@ srs_error_t SrsGoApiRtcPublish::do_serve_http(ISrsHttpResponseWriter* w, ISrsHtt srs_trace("RTC username=%s, offer=%dB, answer=%dB", session->username().c_str(), remote_sdp_str.length(), local_sdp_str.length()); srs_trace("RTC remote offer: %s", srs_string_replace(remote_sdp_str.c_str(), "\r\n", "\\r\\n").c_str()); - srs_trace("RTC local answer: %s", srs_string_replace(local_sdp_str.c_str(), "\r\n", "\\r\\n").c_str()); + srs_trace("RTC local answer: %s", local_sdp_str.c_str()); return err; } diff --git a/trunk/src/app/srs_app_rtc_sdp.cpp b/trunk/src/app/srs_app_rtc_sdp.cpp index b5b942675..86fd5a2fd 100644 --- a/trunk/src/app/srs_app_rtc_sdp.cpp +++ b/trunk/src/app/srs_app_rtc_sdp.cpp @@ -34,7 +34,7 @@ using namespace std; #include // TODO: FIXME: Maybe we should use json.encode to escape it? -const std::string kCRLF = "\\r\\n"; +const std::string kCRLF = "\r\n"; #define FETCH(is,word) \ if (!(is >> word)) {\ From 103bf86eefcfc8dc8098d12f7ace8089becf6105 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 15:06:51 +0800 Subject: [PATCH 25/36] RTC: Remove dead code for source --- trunk/src/app/srs_app_rtc_source.cpp | 45 +++++++--------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index a72153473..d303f5d24 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1374,6 +1374,7 @@ bool SrsRtcTrackDescription::has_ssrc(uint32_t ssrc) if (ssrc == ssrc_ || ssrc == rtx_ssrc_ || ssrc == fec_ssrc_) { return true; } + return false; } @@ -1547,18 +1548,12 @@ SrsRtcRecvTrack::~SrsRtcRecvTrack() bool SrsRtcRecvTrack::has_ssrc(uint32_t ssrc) { - if (track_desc_) { - return track_desc_->has_ssrc(ssrc); - } - - return false; + return track_desc_->has_ssrc(ssrc); } void SrsRtcRecvTrack::update_rtt(int rtt) { - if (nack_receiver_) { - nack_receiver_->update_rtt(rtt); - } + nack_receiver_->update_rtt(rtt); } void SrsRtcRecvTrack::update_send_report_time(const SrsNtp& ntp) @@ -1569,24 +1564,12 @@ void SrsRtcRecvTrack::update_send_report_time(const SrsNtp& ntp) srs_error_t SrsRtcRecvTrack::send_rtcp_rr() { - srs_error_t err = srs_success; - - if (session_) { - return session_->send_rtcp_rr(track_desc_->ssrc_, rtp_queue_, last_sender_report_sys_time, last_sender_report_ntp); - } - - return err; + return session_->send_rtcp_rr(track_desc_->ssrc_, rtp_queue_, last_sender_report_sys_time, last_sender_report_ntp); } srs_error_t SrsRtcRecvTrack::send_rtcp_xr_rrtr() { - srs_error_t err = srs_success; - - if (track_desc_) { - return session_->send_rtcp_xr_rrtr(track_desc_->ssrc_); - } - - return err; + return session_->send_rtcp_xr_rrtr(track_desc_->ssrc_); } bool SrsRtcRecvTrack::set_track_status(bool active) @@ -1669,10 +1652,8 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk statistic_->packets++; statistic_->bytes += pkt->nb_bytes(); - if (source) { - if ((err = source->on_rtp(pkt)) != srs_success) { - return srs_error_wrap(err, "source on rtp"); - } + if ((err = source->on_rtp(pkt)) != srs_success) { + return srs_error_wrap(err, "source on rtp"); } // For NACK to handle packet. @@ -1706,10 +1687,8 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk pkt->frame_type = SrsFrameTypeVideo; - if (source) { - if ((err = source->on_rtp(pkt)) != srs_success) { - return srs_error_wrap(err, "source on rtp"); - } + if ((err = source->on_rtp(pkt)) != srs_success) { + return srs_error_wrap(err, "source on rtp"); } // TODO: FIXME: add rtp process @@ -1756,11 +1735,7 @@ SrsRtcSendTrack::~SrsRtcSendTrack() bool SrsRtcSendTrack::has_ssrc(uint32_t ssrc) { - if (track_desc_) { - return track_desc_->has_ssrc(ssrc); - } - - return false; + return track_desc_->has_ssrc(ssrc); } SrsRtpPacket2* SrsRtcSendTrack::fetch_rtp_packet(uint16_t seq) From 49e768ad09ff799cf0d9d26ac52d1f72a31d2198 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 16:56:27 +0800 Subject: [PATCH 26/36] RTC: Fix bug for utest --- trunk/src/app/srs_app_rtc_conn.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index be85223ab..b515fdd11 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -823,6 +823,7 @@ SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session) session_ = session; request_keyframe_ = false; + req = NULL; source = NULL; nn_simulate_nack_drop = 0; nack_enabled_ = false; From d439e3634432664bb477fbd8c159deff09e013a8 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 17:03:25 +0800 Subject: [PATCH 27/36] RTC: Covert basic packet identify for DTLS/STUN/RTP/RTCP --- trunk/src/app/srs_app_rtc_server.cpp | 33 +++++---- trunk/src/utest/srs_utest_rtc.cpp | 103 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 38a20856e..413dea282 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -97,6 +97,7 @@ void SrsRtcBlackhole::sendto(void* data, int len) return; } + // For blackhole, we ignore any error. srs_sendto(blackhole_stfd, data, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT); } @@ -105,24 +106,32 @@ SrsRtcBlackhole* _srs_blackhole = new SrsRtcBlackhole(); // @global dtls certficate for rtc module. SrsDtlsCertificate* _srs_rtc_dtls_certificate = new SrsDtlsCertificate(); -static bool is_stun(const uint8_t* data, const int size) +// TODO: Should support error response. +// For STUN packet, 0x00 is binding request, 0x01 is binding success response. +bool srs_is_stun(const uint8_t* data, size_t size) { - return data != NULL && size > 0 && (data[0] == 0 || data[0] == 1); + return size > 0 && (data[0] == 0 || data[0] == 1); } -static bool is_dtls(const uint8_t* data, size_t len) +// change_cipher_spec(20), alert(21), handshake(22), application_data(23) +// @see https://tools.ietf.org/html/rfc2246#section-6.2.1 +bool srs_is_dtls(const uint8_t* data, size_t len) { - return (len >= 13 && (data[0] > 19 && data[0] < 64)); + return (len >= 13 && (data[0] > 19 && data[0] < 64)); } -static bool is_rtp_or_rtcp(const uint8_t* data, size_t len) +// For RTP or RTCP, the V=2 which is in the high 2bits, 0xC0 (1100 0000) +bool srs_is_rtp_or_rtcp(const uint8_t* data, size_t len) { - return (len >= 12 && (data[0] & 0xC0) == 0x80); + return (len >= 12 && (data[0] & 0xC0) == 0x80); } -static bool is_rtcp(const uint8_t* data, size_t len) +// For RTCP, PT is [128, 223] (or without marker [0, 95]). +// Literally, RTCP starts from 64 not 0, so PT is [192, 223] (or without marker [64, 95]). +// @note For RTP, the PT is [96, 127], or [224, 255] with marker. +bool srs_is_rtcp(const uint8_t* data, size_t len) { - return (len >= 12) && (data[0] & 0x80) && (data[1] >= 200 && data[1] <= 209); + return (len >= 12) && (data[0] & 0x80) && (data[1] >= 192 && data[1] <= 223); } static std::vector get_candidate_ips() @@ -301,7 +310,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) } // For STUN, the peer address may change. - if (is_stun((uint8_t*)data, size)) { + if (srs_is_stun((uint8_t*)data, size)) { SrsStunPacket ping; if ((err = ping.decode(data, size)) != srs_success) { return srs_error_wrap(err, "decode stun packet failed"); @@ -332,10 +341,10 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) return srs_error_new(ERROR_RTC_STUN, "no session, peer_id=%s", peer_id.c_str()); } - if (is_dtls((uint8_t*)data, size)) { + if (srs_is_dtls((uint8_t*)data, size)) { return session->on_dtls(data, size); - } else if (is_rtp_or_rtcp((uint8_t*)data, size)) { - if (is_rtcp((uint8_t*)data, size)) { + } else if (srs_is_rtp_or_rtcp((uint8_t*)data, size)) { + if (srs_is_rtcp((uint8_t*)data, size)) { return session->on_rtcp(data, size); } return session->on_rtp(data, size); diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 7ceeb8d96..1d22ac897 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +using namespace std; + VOID TEST(KernelRTCTest, SequenceCompare) { if (true) { @@ -125,6 +128,106 @@ VOID TEST(KernelRTCTest, SequenceCompare) } } +extern bool srs_is_stun(const uint8_t* data, size_t size); +extern bool srs_is_dtls(const uint8_t* data, size_t len); +extern bool srs_is_rtp_or_rtcp(const uint8_t* data, size_t len); +extern bool srs_is_rtcp(const uint8_t* data, size_t len); + +#define mock_arr_push(arr, elem) arr.push_back(vector(elem, elem + sizeof(elem))) + +VOID TEST(KernelRTCTest, TestPacketType) +{ + // DTLS packet. + vector< vector > dtlss; + if (true) { uint8_t data[13] = {20}; mock_arr_push(dtlss, data); } // change_cipher_spec(20) + if (true) { uint8_t data[13] = {21}; mock_arr_push(dtlss, data); } // alert(21) + if (true) { uint8_t data[13] = {22}; mock_arr_push(dtlss, data); } // handshake(22) + if (true) { uint8_t data[13] = {23}; mock_arr_push(dtlss, data); } // application_data(23) + for (int i = 0; i < (int)dtlss.size(); i++) { + vector elem = dtlss.at(i); + EXPECT_TRUE(srs_is_dtls(&elem[0], (size_t)elem.size())); + } + + for (int i = 0; i < (int)dtlss.size(); i++) { + vector elem = dtlss.at(i); + EXPECT_FALSE(srs_is_dtls(&elem[0], 1)); + + // All DTLS should not be other packets. + EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size())); + EXPECT_TRUE(srs_is_dtls(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } + + // STUN packet. + vector< vector > stuns; + if (true) { uint8_t data[1] = {0}; mock_arr_push(stuns, data); } // binding request. + if (true) { uint8_t data[1] = {1}; mock_arr_push(stuns, data); } // binding success response. + for (int i = 0; i < (int)stuns.size(); i++) { + vector elem = stuns.at(i); + EXPECT_TRUE(srs_is_stun(&elem[0], (size_t)elem.size())); + } + + for (int i = 0; i < (int)stuns.size(); i++) { + vector elem = stuns.at(i); + EXPECT_FALSE(srs_is_stun(&elem[0], 0)); + + // All STUN should not be other packets. + EXPECT_TRUE(srs_is_stun(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } + + // RTCP packet. + vector< vector > rtcps; + if (true) { uint8_t data[12] = {0x80, 192}; mock_arr_push(rtcps, data); } + if (true) { uint8_t data[12] = {0x80, 200}; mock_arr_push(rtcps, data); } // SR + if (true) { uint8_t data[12] = {0x80, 201}; mock_arr_push(rtcps, data); } // RR + if (true) { uint8_t data[12] = {0x80, 202}; mock_arr_push(rtcps, data); } // SDES + if (true) { uint8_t data[12] = {0x80, 203}; mock_arr_push(rtcps, data); } // BYE + if (true) { uint8_t data[12] = {0x80, 204}; mock_arr_push(rtcps, data); } // APP + if (true) { uint8_t data[12] = {0x80, 223}; mock_arr_push(rtcps, data); } + for (int i = 0; i < (int)rtcps.size(); i++) { + vector elem = rtcps.at(i); + EXPECT_TRUE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } + + for (int i = 0; i < (int)rtcps.size(); i++) { + vector elem = rtcps.at(i); + EXPECT_FALSE(srs_is_rtcp(&elem[0], 2)); + + // All RTCP should not be other packets. + EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size())); + EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size())); + EXPECT_TRUE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } + + // RTP packet. + vector< vector > rtps; + if (true) { uint8_t data[12] = {0x80, 96}; mock_arr_push(rtps, data); } + if (true) { uint8_t data[12] = {0x80, 127}; mock_arr_push(rtps, data); } + if (true) { uint8_t data[12] = {0x80, 224}; mock_arr_push(rtps, data); } + if (true) { uint8_t data[12] = {0x80, 255}; mock_arr_push(rtps, data); } + for (int i = 0; i < (int)rtps.size(); i++) { + vector elem = rtps.at(i); + EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } + + for (int i = 0; i < (int)rtps.size(); i++) { + vector elem = rtps.at(i); + EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], 2)); + + // All RTP should not be other packets. + EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size())); + EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size())); + EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size())); + } +} + VOID TEST(KernelRTCTest, DefaultTrackStatus) { // By default, track is disabled. From fc10e98f1c5374ab95dc445b7dee83b08357f4d0 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 4 Aug 2020 20:08:21 +0800 Subject: [PATCH 28/36] RTC: Remove dead code. Fix DTLS empty ctx issue --- trunk/src/app/srs_app_rtc_conn.cpp | 52 +++++------------ trunk/src/app/srs_app_rtc_conn.hpp | 5 -- trunk/src/app/srs_app_rtc_dtls.cpp | 84 ++++++++++++++++++---------- trunk/src/app/srs_app_rtc_source.cpp | 15 ----- trunk/src/app/srs_app_rtc_source.hpp | 6 +- trunk/src/core/srs_core.hpp | 1 + 6 files changed, 73 insertions(+), 90 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b515fdd11..5b7eda79b 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -89,10 +89,13 @@ srs_error_t SrsSecurityTransport::start_active_handshake() srs_error_t SrsSecurityTransport::write_dtls_data(void* data, int size) { srs_error_t err = srs_success; - if (size) { - if ((err = session_->sendonly_skt->sendto(data, size, 0)) != srs_success) { - return srs_error_wrap(err, "send dtls packet"); - } + + if (!size) { + return err; + } + + if ((err = session_->sendonly_skt->sendto(data, size, 0)) != srs_success) { + return srs_error_wrap(err, "send dtls packet"); } if (_srs_blackhole->blackhole) { @@ -114,13 +117,13 @@ srs_error_t SrsSecurityTransport::on_dtls_handshake_done() if (handshake_done) { return err; } + handshake_done = true; // TODO: FIXME: Add cost for DTLS. srs_trace("RTC: DTLS handshake done."); - handshake_done = true; if ((err = srtp_initialize()) != srs_success) { - return srs_error_wrap(err, "srtp init failed"); + return srs_error_wrap(err, "srtp init"); } return session_->on_connection_established(); @@ -147,7 +150,7 @@ srs_error_t SrsSecurityTransport::srtp_initialize() } if ((err = srtp_->initialize(recv_key, send_key)) != srs_success) { - return srs_error_wrap(err, "srtp init failed"); + return srs_error_wrap(err, "srtp init"); } return err; @@ -155,56 +158,32 @@ srs_error_t SrsSecurityTransport::srtp_initialize() srs_error_t SrsSecurityTransport::protect_rtp(const char* plaintext, char* cipher, int& nb_cipher) { - if (!srtp_) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); - } - return srtp_->protect_rtp(plaintext, cipher, nb_cipher); } srs_error_t SrsSecurityTransport::protect_rtcp(const char* plaintext, char* cipher, int& nb_cipher) { - if (!srtp_) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); - } - return srtp_->protect_rtcp(plaintext, cipher, nb_cipher); } // TODO: FIXME: Merge with protect_rtp. srs_error_t SrsSecurityTransport::protect_rtp2(void* rtp_hdr, int* len_ptr) { - if (!srtp_) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); - } - return srtp_->protect_rtp2(rtp_hdr, len_ptr); } srs_error_t SrsSecurityTransport::unprotect_rtp(const char* cipher, char* plaintext, int& nb_plaintext) { - if (!srtp_) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtp unprotect failed"); - } - return srtp_->unprotect_rtp(cipher, plaintext, nb_plaintext); } srs_error_t SrsSecurityTransport::unprotect_rtcp(const char* cipher, char* plaintext, int& nb_plaintext) { - if (!srtp_) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); - } - return srtp_->unprotect_rtcp(cipher, plaintext, nb_plaintext); } SrsRtcPlayStreamStatistic::SrsRtcPlayStreamStatistic() { -#if defined(SRS_DEBUG) - debug_id = 0; -#endif - nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; @@ -353,18 +332,18 @@ srs_error_t SrsRtcPlayStream::cycle() SrsRequest* req = session_->req; if ((err = _srs_rtc_sources->fetch_or_create(req, &source)) != srs_success) { - return srs_error_wrap(err, "rtc fetch source failed"); + return srs_error_wrap(err, "fetch source"); } SrsRtcConsumer* consumer = NULL; SrsAutoFree(SrsRtcConsumer, consumer); if ((err = source->create_consumer(consumer)) != srs_success) { - return srs_error_wrap(err, "rtc create consumer, source url=%s", req->get_stream_url().c_str()); + return srs_error_wrap(err, "create consumer, source=%s", req->get_stream_url().c_str()); } // TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames. if ((err = source->consumer_dumps(consumer)) != srs_success) { - return srs_error_wrap(err, "dumps consumer, source url=%s", req->get_stream_url().c_str()); + return srs_error_wrap(err, "dumps consumer, url=%s", req->get_stream_url().c_str()); } realtime = _srs_config->get_realtime_enabled(req->vhost, true); @@ -447,11 +426,6 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectortransport_) { - return err; - } - vector send_pkts; // Covert kernel messages to RTP packets. for (int i = 0; i < (int)pkts.size(); i++) { diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 607bcb6ad..74900f7c9 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -131,11 +131,6 @@ private: // A group of RTP packets for outgoing(send to players). class SrsRtcPlayStreamStatistic { -public: -#if defined(SRS_DEBUG) - // Debug id. - uint32_t debug_id; -#endif public: // The total bytes of AVFrame packets. int nn_bytes; diff --git a/trunk/src/app/srs_app_rtc_dtls.cpp b/trunk/src/app/srs_app_rtc_dtls.cpp index 218fb4e0e..7c6c52e50 100644 --- a/trunk/src/app/srs_app_rtc_dtls.cpp +++ b/trunk/src/app/srs_app_rtc_dtls.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include +#include // The return value of verify_callback controls the strategy of the further verification process. If verify_callback // returns 0, the verification process is immediately stopped with "verification failed" state. If SSL_VERIFY_PEER is @@ -161,7 +162,7 @@ srs_error_t SrsDtlsCertificate::initialize() int serial = rand(); ASN1_INTEGER_set(X509_get_serialNumber(dtls_cert), serial); - const std::string& aor = "ossrs.net"; + const std::string& aor = RTMP_SIG_SRS_DOMAIN; X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, (unsigned char *) aor.data(), aor.size(), -1, 0); X509_set_issuer_name(dtls_cert, subject); @@ -385,10 +386,6 @@ srs_error_t SrsDtls::do_handshake() { srs_error_t err = srs_success; - if (!callback) { - return srs_error_new(ERROR_RTC_DTLS, "no callback"); - } - int ret = SSL_do_handshake(dtls); unsigned char *out_bio_data; @@ -419,7 +416,7 @@ srs_error_t SrsDtls::do_handshake() if (out_bio_len) { if ((err = callback->write_dtls_data(out_bio_data, out_bio_len)) != srs_success) { - return srs_error_wrap(err, "dtls send"); + return srs_error_wrap(err, "dtls send size=%u", out_bio_len); } } @@ -450,7 +447,7 @@ srs_error_t SrsDtls::on_dtls(char* data, int nb_data) if (nb > 0 && callback) { if ((err = callback->on_dtls_application_data(dtls_read_buf, nb)) != srs_success) { - return srs_error_wrap(err, "dtls application data process"); + return srs_error_wrap(err, "on DTLS data, size=%u", nb); } } } @@ -477,7 +474,7 @@ srs_error_t SrsDtls::get_srtp_key(std::string& recv_key, std::string& send_key) unsigned char material[SRTP_MASTER_KEY_LEN * 2] = {0}; // client(SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN) + server static const string dtls_srtp_lable = "EXTRACTOR-dtls_srtp"; if (!SSL_export_keying_material(dtls, material, sizeof(material), dtls_srtp_lable.c_str(), dtls_srtp_lable.size(), NULL, 0, 0)) { - return srs_error_new(ERROR_RTC_SRTP_INIT, "SSL_export_keying_material failed"); + return srs_error_new(ERROR_RTC_SRTP_INIT, "SSL export key r0=%u", ERR_get_error()); } size_t offset = 0; @@ -544,8 +541,9 @@ srs_error_t SrsSRTP::initialize(string recv_key, std::string send_key) memcpy(rkey, recv_key.data(), recv_key.size()); policy.key = rkey; - if (srtp_create(&recv_ctx_, &policy) != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp_create recv failed"); + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_create(&recv_ctx_, &policy)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp create r0=%u", r0); } policy.ssrc.type = ssrc_any_outbound; @@ -554,8 +552,8 @@ srs_error_t SrsSRTP::initialize(string recv_key, std::string send_key) memcpy(skey, send_key.data(), send_key.size()); policy.key = skey; - if (srtp_create(&send_ctx_, &policy) != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp_create recv failed"); + if ((r0 = srtp_create(&send_ctx_, &policy)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp create r0=%u", r0); } return err; @@ -565,10 +563,16 @@ srs_error_t SrsSRTP::protect_rtp(const char* plaintext, char* cipher, int& nb_ci { srs_error_t err = srs_success; + // If DTLS/SRTP is not ready, fail. + if (!send_ctx_) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "not ready"); + } + memcpy(cipher, plaintext, nb_cipher); - // TODO: FIXME: Wrap error code. - if (srtp_protect(send_ctx_, cipher, &nb_cipher) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_protect(send_ctx_, cipher, &nb_cipher)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect r0=%u", r0); } return err; @@ -578,10 +582,16 @@ srs_error_t SrsSRTP::protect_rtcp(const char* plaintext, char* cipher, int& nb_c { srs_error_t err = srs_success; + // If DTLS/SRTP is not ready, fail. + if (!send_ctx_) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "not ready"); + } + memcpy(cipher, plaintext, nb_cipher); - // TODO: FIXME: Wrap error code. - if (srtp_protect_rtcp(send_ctx_, cipher, &nb_cipher) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_protect_rtcp(send_ctx_, cipher, &nb_cipher)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect r0=%u", r0); } return err; @@ -591,9 +601,14 @@ srs_error_t SrsSRTP::protect_rtp2(void* rtp_hdr, int* len_ptr) { srs_error_t err = srs_success; - // TODO: FIXME: Wrap error code. - if (srtp_protect(send_ctx_, rtp_hdr, len_ptr) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); + // If DTLS/SRTP is not ready, fail. + if (!send_ctx_) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "not ready"); + } + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_protect(send_ctx_, rtp_hdr, len_ptr)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect r0=%u", r0); } return err; @@ -603,10 +618,16 @@ srs_error_t SrsSRTP::unprotect_rtp(const char* cipher, char* plaintext, int& nb_ { srs_error_t err = srs_success; + // If DTLS/SRTP is not ready, fail. + if (!recv_ctx_) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "not ready"); + } + memcpy(plaintext, cipher, nb_plaintext); - srtp_err_status_t r0 = srtp_unprotect(recv_ctx_, plaintext, &nb_plaintext); - if (r0 != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "unprotect r0=%u", r0); + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_unprotect(recv_ctx_, plaintext, &nb_plaintext)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtp unprotect r0=%u", r0); } return err; @@ -616,11 +637,18 @@ srs_error_t SrsSRTP::unprotect_rtcp(const char* cipher, char* plaintext, int& nb { srs_error_t err = srs_success; + // If DTLS/SRTP is not ready, fail. + if (!recv_ctx_) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "not ready"); + } + memcpy(plaintext, cipher, nb_plaintext); - // TODO: FIXME: Wrap error code. - if (srtp_unprotect_rtcp(recv_ctx_, plaintext, &nb_plaintext) != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_unprotect_rtcp(recv_ctx_, plaintext, &nb_plaintext)) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect r0=%u", r0); } return err; -} \ No newline at end of file +} + diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index d303f5d24..3e22995f0 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1627,11 +1627,6 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) return err; } -srs_error_t SrsRtcRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) -{ - return srs_success; -} - SrsRtcAudioRecvTrack::SrsRtcAudioRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc) : SrsRtcRecvTrack(session, track_desc, true) { @@ -1765,16 +1760,6 @@ std::string SrsRtcSendTrack::get_track_id() return track_desc_->id_; } -srs_error_t SrsRtcSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) -{ - return srs_success; -} - -srs_error_t SrsRtcSendTrack::on_rtcp(SrsRtpPacket2* pkt) -{ - return srs_success; -} - void SrsRtcSendTrack::on_recv_nack() { SrsRtcTrackStatistic* statistic = statistic_; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 60033408e..2911fe4c2 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -471,7 +471,7 @@ public: protected: srs_error_t on_nack(SrsRtpPacket2* pkt); public: - virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt); + virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) = 0; }; class SrsRtcAudioRecvTrack : public SrsRtcRecvTrack @@ -517,8 +517,8 @@ public: bool get_track_status(); std::string get_track_id(); public: - virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info); - virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt); + virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) = 0; + virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt) = 0; virtual void on_recv_nack(); }; diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index bb983c2af..9fa326aff 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -46,6 +46,7 @@ #define RTMP_SIG_SRS_AUTHORS "Winlin,Wenjie,Runner365,John,B.P.Y,Lixin" #define RTMP_SIG_SRS_VERSION SRS_XSTR(VERSION_MAJOR) "." SRS_XSTR(VERSION_MINOR) "." SRS_XSTR(VERSION_REVISION) #define RTMP_SIG_SRS_SERVER RTMP_SIG_SRS_KEY "/" RTMP_SIG_SRS_VERSION "(" RTMP_SIG_SRS_CODE ")" +#define RTMP_SIG_SRS_DOMAIN "ossrs.net" // The current stable release. #define VERSION_STABLE 3 From 77b6151857119d8ca7700644f468adaf8395d83c Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 16:23:31 +0800 Subject: [PATCH 29/36] RTC: Use srs_string_dumps_hex to dump some bytes when error --- trunk/src/app/srs_app_listener.cpp | 7 +--- trunk/src/app/srs_app_rtc_conn.cpp | 7 ++-- trunk/src/app/srs_app_utility.cpp | 58 ++++++++++++++++++------------ trunk/src/app/srs_app_utility.hpp | 7 ++-- trunk/src/utest/srs_utest_rtc.cpp | 36 +++++++++++++++++++ 5 files changed, 83 insertions(+), 32 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 7094bdbcf..ac5a0d6b3 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -48,9 +48,6 @@ using namespace std; // sleep in srs_utime_t for udp recv packet. #define SrsUdpPacketRecvCycleInterval 0 -// Set the byte at specified position. -#define _srs_set_byte(data, size, b, index) if (index < size) b = data[index] - ISrsUdpHandler::ISrsUdpHandler() { } @@ -549,9 +546,7 @@ srs_error_t SrsUdpMuxListener::cycle() // Append more information. if (true) { char* data = skt.data(); int size = skt.size(); - uint8_t b0 = 0, b1 = 0; _srs_set_byte(data, size, b0, 0); _srs_set_byte(data, size, b1, 1); uint8_t b2 = 0, b3 = 0; _srs_set_byte(data, size, b2, 2); _srs_set_byte(data, size, b3, 3); - uint8_t b4 = 0, b5 = 0; _srs_set_byte(data, size, b4, 4); _srs_set_byte(data, size, b5, 5); uint8_t b6 = 0, b7 = 0; _srs_set_byte(data, size, b6, 6); _srs_set_byte(data, size, b7, 7); - err = srs_error_wrap(err, "size=%u, data=[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]", size, b0, b1, b2, b3, b4, b5, b6, b7); + err = srs_error_wrap(err, "size=%u, data=[%s]", size, srs_string_dumps_hex(data, size, 8).c_str()); } srs_warn("handle udp pkt, count=%u, err: %s", pp_pkt_handler_err->nn_count, srs_error_desc(err).c_str()); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 5b7eda79b..18cc80b35 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -543,8 +543,10 @@ srs_error_t SrsRtcPlayStream::on_rtcp(char* data, int nb_data) { srs_error_t err = srs_success; + // TODO: Use SrsBuffer to parse it. char* ph = data; int nb_left = nb_data; + while (nb_left) { uint8_t payload_type = ph[1]; uint16_t length_4bytes = (((uint16_t)ph[2]) << 8) | ph[3]; @@ -552,7 +554,8 @@ srs_error_t SrsRtcPlayStream::on_rtcp(char* data, int nb_data) int length = (length_4bytes + 1) * 4; if (length > nb_data) { - return srs_error_new(ERROR_RTC_RTCP, "invalid rtcp packet, length=%u", length); + return srs_error_new(ERROR_RTC_RTCP, "invalid length=%u/%u, left=%u, bytes=%s", + length, nb_data, nb_left, srs_string_dumps_hex(ph, nb_left, 8).c_str()); } srs_verbose("on rtcp, payload_type=%u", payload_type); @@ -594,7 +597,7 @@ srs_error_t SrsRtcPlayStream::on_rtcp(char* data, int nb_data) } if (err != srs_success) { - return srs_error_wrap(err, "rtcp"); + return srs_error_wrap(err, "rtcp left=%u, bytes=%s", nb_left, srs_string_dumps_hex(ph, nb_left, 8).c_str()); } ph += length; diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index da186efb3..a6c72f722 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -1281,37 +1281,51 @@ void srs_api_dump_summaries(SrsJsonObject* obj) sys->set("conn_srs", SrsJsonAny::integer(nrs->nb_conn_srs)); } -string srs_string_dumps_hex(const std::string& str, const int& limit) +string srs_string_dumps_hex(const std::string& str) { - return srs_string_dumps_hex(str.c_str(), str.size(), limit); + return srs_string_dumps_hex(str.c_str(), str.size()); } -string srs_string_dumps_hex(const char* buf, const int length, const int& limit) +string srs_string_dumps_hex(const char* str, int length) { - string ret; + return srs_string_dumps_hex(str, length, INT_MAX); +} - char tmp_buf[1024*16]; - tmp_buf[0] = '\n'; - int len = 1; - - for (int i = 0; i < length && i < limit; ++i) { - int nb = snprintf(tmp_buf + len, sizeof(tmp_buf) - len - 2, "%02X ", (uint8_t)buf[i]); - if (nb <= 0) +string srs_string_dumps_hex(const char* str, int length, int limit) +{ + return srs_string_dumps_hex(str, length, limit, ' ', 128, '\n'); +} + +string srs_string_dumps_hex(const char* str, int length, int limit, char seperator, int line_limit, char newline) +{ + const int LIMIT = 1024*16; + static char buf[LIMIT]; + + int len = 0; + for (int i = 0; i < length && i < limit && i < LIMIT; ++i) { + int nb = snprintf(buf + len, LIMIT - len, "%02x", (uint8_t)str[i]); + if (nb < 0 || nb > LIMIT - len) { break; + } + len += nb; - len += nb; + // Only append seperator and newline when not last byte. + if (i < length - 1 && i < limit - 1 && i < LIMIT - 1) { + if (seperator && len < LIMIT) { + buf[len++] = seperator; + } - if (i % 48 == 47) { - tmp_buf[len++] = '\n'; - ret.append(tmp_buf, len); - len = 0; - } - } - tmp_buf[len] = '\0'; - ret.append(tmp_buf, len); - - return ret; + if (newline && line_limit && i > 0 && ((i + 1) % line_limit) == 0 && len < LIMIT) { + buf[len++] = newline; + } + } + } + // Empty string. + if (len <= 0) { + return ""; + } + return string(buf, len); } string srs_getenv(string key) diff --git a/trunk/src/app/srs_app_utility.hpp b/trunk/src/app/srs_app_utility.hpp index a4a73ef54..63bfef577 100644 --- a/trunk/src/app/srs_app_utility.hpp +++ b/trunk/src/app/srs_app_utility.hpp @@ -652,8 +652,11 @@ extern bool srs_is_boolean(std::string str); extern void srs_api_dump_summaries(SrsJsonObject* obj); // Dump string(str in length) to hex, it will process min(limit, length) chars. -extern std::string srs_string_dumps_hex(const std::string& str, const int& limit = INT_MAX); -extern std::string srs_string_dumps_hex(const char* str, const int length, const int& limit = INT_MAX); +// Append seperator between each elem, and newline when exceed line_limit, '\0' to ignore. +extern std::string srs_string_dumps_hex(const std::string& str); +extern std::string srs_string_dumps_hex(const char* str, int length); +extern std::string srs_string_dumps_hex(const char* str, int length, int limit); +extern std::string srs_string_dumps_hex(const char* str, int length, int limit, char seperator, int line_limit, char newline); // Get ENV variable, which may starts with $. // srs_getenv("EIP") === srs_getenv("$EIP") diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 1d22ac897..9621f5d40 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include #include #include @@ -128,6 +129,41 @@ VOID TEST(KernelRTCTest, SequenceCompare) } } +VOID TEST(KernelRTCTest, DumpsHexToString) +{ + if (true) { + EXPECT_STREQ("", srs_string_dumps_hex(NULL, 0).c_str()); + } + + if (true) { + uint8_t data[] = {0, 0, 0, 0}; + EXPECT_STREQ("00 00 00 00", srs_string_dumps_hex((const char*)data, sizeof(data)).c_str()); + } + + if (true) { + uint8_t data[] = {0, 1, 2, 3}; + EXPECT_STREQ("00 01 02 03", srs_string_dumps_hex((const char*)data, sizeof(data)).c_str()); + } + + if (true) { + uint8_t data[] = {0xa, 3, 0xf, 3}; + EXPECT_STREQ("0a 03 0f 03", srs_string_dumps_hex((const char*)data, sizeof(data)).c_str()); + } + + if (true) { + uint8_t data[] = {0xa, 3, 0xf, 3}; + EXPECT_STREQ("0a,03,0f,03", srs_string_dumps_hex((const char*)data, sizeof(data), INT_MAX, ',', 0, 0).c_str()); + EXPECT_STREQ("0a030f03", srs_string_dumps_hex((const char*)data, sizeof(data), INT_MAX, '\0', 0, 0).c_str()); + EXPECT_STREQ("0a,03,\n0f,03", srs_string_dumps_hex((const char*)data, sizeof(data), INT_MAX, ',', 2, '\n').c_str()); + EXPECT_STREQ("0a,03,0f,03", srs_string_dumps_hex((const char*)data, sizeof(data), INT_MAX, ',', 2,'\0').c_str()); + } + + if (true) { + uint8_t data[] = {0xa, 3, 0xf}; + EXPECT_STREQ("0a 03", srs_string_dumps_hex((const char*)data, sizeof(data), 2).c_str()); + } +} + extern bool srs_is_stun(const uint8_t* data, size_t size); extern bool srs_is_dtls(const uint8_t* data, size_t len); extern bool srs_is_rtp_or_rtcp(const uint8_t* data, size_t len); From 77403dd970a3c12d87d2d87161dbb7fd31e004db Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 16:38:23 +0800 Subject: [PATCH 30/36] RTC: Refine error log, show some plaintext body bytes. --- trunk/src/app/srs_app_rtc_conn.cpp | 20 ++++++++++++++++++-- trunk/src/app/srs_app_rtc_conn.hpp | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 18cc80b35..282d924da 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1038,8 +1038,24 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) _srs_blackhole->sendto(unprotected_buf, nb_unprotected_buf); } - char* buf = unprotected_buf; - int nb_buf = nb_unprotected_buf; + // Handle the plaintext RTP packet. + if ((err = do_on_rtp(unprotected_buf, nb_unprotected_buf)) != srs_success) { + int nb_header = h.nb_bytes(); + const char* body = unprotected_buf + nb_header; + int nb_body = nb_unprotected_buf - nb_header; + return srs_error_wrap(err, "cipher=%u, plaintext=%u, body=%s", nb_data, nb_unprotected_buf, + srs_string_dumps_hex(body, nb_body, 8).c_str()); + } + + return err; +} + +srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) +{ + srs_error_t err = srs_success; + + char* buf = plaintext; + int nb_buf = nb_plaintext; // Decode the RTP packet from buffer. SrsRtpPacket2* pkt = new SrsRtpPacket2(); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 74900f7c9..afe96eb04 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -261,6 +261,9 @@ private: srs_error_t send_rtcp_xr_rrtr(); public: srs_error_t on_rtp(char* buf, int nb_buf); +private: + srs_error_t do_on_rtp(char* plaintext, int nb_plaintext); +public: virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); private: srs_error_t send_periodic_twcc(); From d156bc2a1b76898fde6ff2ce65a7853a8817ba55 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 16:47:11 +0800 Subject: [PATCH 31/36] RTC: Refine error, show some bytes for RTCP --- trunk/src/app/srs_app_rtc_conn.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 282d924da..e68f6d661 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1915,14 +1915,10 @@ srs_error_t SrsRtcConnection::on_rtcp(char* data, int nb_data) { srs_error_t err = srs_success; - if (transport_ == NULL) { - return srs_error_new(ERROR_RTC_RTCP, "recv unexpect rtp packet before dtls done"); - } - char unprotected_buf[kRtpPacketSize]; int nb_unprotected_buf = nb_data; if ((err = transport_->unprotect_rtcp(data, unprotected_buf, nb_unprotected_buf)) != srs_success) { - return srs_error_wrap(err, "rtcp unprotect failed"); + return srs_error_wrap(err, "rtcp unprotect"); } if (_srs_blackhole->blackhole) { @@ -1930,11 +1926,16 @@ srs_error_t SrsRtcConnection::on_rtcp(char* data, int nb_data) } if (player_) { - return player_->on_rtcp(unprotected_buf, nb_unprotected_buf); + err = player_->on_rtcp(unprotected_buf, nb_unprotected_buf); } if (publisher_) { - return publisher_->on_rtcp(unprotected_buf, nb_unprotected_buf); + err = publisher_->on_rtcp(unprotected_buf, nb_unprotected_buf); + } + + if (err != srs_success) { + return srs_error_wrap(err, "cipher=%u, plaintext=%u, bytes=%s", nb_data, nb_unprotected_buf, + srs_string_dumps_hex(unprotected_buf, nb_unprotected_buf, 8).c_str()); } return err; @@ -1948,11 +1949,7 @@ srs_error_t SrsRtcConnection::on_rtcp_feedback(char* data, int nb_data) srs_error_t SrsRtcConnection::on_rtp(char* data, int nb_data) { if (publisher_ == NULL) { - return srs_error_new(ERROR_RTC_RTCP, "rtc publisher null"); - } - - if (transport_ == NULL) { - return srs_error_new(ERROR_RTC_RTCP, "recv unexpect rtp packet before dtls done"); + return srs_error_new(ERROR_RTC_RTCP, "no publisher"); } //TODO: FIXME: add unprotect_rtcp. From 75119a14cfdd876bed42f6ee031eeec0d575af95 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 17:17:33 +0800 Subject: [PATCH 32/36] RTC: Check error for send_rtcp_rr --- trunk/src/app/srs_app_rtc_conn.cpp | 42 +++++++++------------------- trunk/src/app/srs_app_rtc_source.cpp | 10 ++++++- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e68f6d661..676856023 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -935,12 +935,16 @@ srs_error_t SrsRtcPublishStream::send_rtcp_rr() for (int i = 0; i < (int)video_tracks_.size(); ++i) { SrsRtcVideoRecvTrack* track = video_tracks_.at(i); - track->send_rtcp_rr(); + if ((err = track->send_rtcp_rr()) != srs_success) { + return srs_error_wrap(err, "track=%s", track->get_track_id().c_str()); + } } for (int i = 0; i < (int)audio_tracks_.size(); ++i) { SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); - track->send_rtcp_rr(); + if ((err = track->send_rtcp_rr()) != srs_success) { + return srs_error_wrap(err, "track=%s", track->get_track_id().c_str()); + } } session_->stat_->nn_rr++; @@ -1512,8 +1516,12 @@ srs_error_t SrsRtcPublishStream::notify(int type, srs_utime_t interval, srs_utim } if (type == SRS_TICKID_RTCP) { + if ((err = send_rtcp_rr()) != srs_success) { + srs_warn("RR err %s", srs_error_desc(err).c_str()); + srs_freep(err); + } + // TODO: FIXME: Check error. - send_rtcp_rr(); send_rtcp_xr_rrtr(); // TODO: FIXME: Check error. @@ -2051,11 +2059,6 @@ srs_error_t SrsRtcConnection::notify(int type, srs_utime_t interval, srs_utime_t void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks) { - // If DTLS is not OK, drop all messages. - if (!transport_) { - return; - } - // @see: https://tools.ietf.org/html/rfc4585#section-6.1 vector nack_seqs; nack->get_nack_seqs(nack_seqs); @@ -2102,11 +2105,6 @@ srs_error_t SrsRtcConnection::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_ { srs_error_t err = srs_success; - // If DTLS is not OK, drop all messages. - if (!transport_) { - return err; - } - // @see https://tools.ietf.org/html/rfc3550#section-6.4.2 char buf[kRtpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); @@ -2115,8 +2113,6 @@ srs_error_t SrsRtcConnection::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_ stream.write_2bytes(7); stream.write_4bytes(ssrc); // TODO: FIXME: Should be 1? - // TODO: FIXME: Implements it. - // TODO: FIXME: See https://github.com/ossrs/srs/blob/f81d35d20f04ebec01915cb78a882e45b7ee8800/trunk/src/app/srs_app_rtc_queue.cpp uint8_t fraction_lost = 0; uint32_t cumulative_number_of_packets_lost = 0 & 0x7FFFFF; uint32_t extended_highest_sequence = rtp_queue->get_extended_highest_sequence(); @@ -2139,7 +2135,7 @@ srs_error_t SrsRtcConnection::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_ stream.write_4bytes(rr_lsr); stream.write_4bytes(rr_dlsr); - srs_verbose("RR ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, extended_highest_sequence=%u, interarrival_jitter=%u", + srs_info("RR ssrc=%u, fraction_lost=%u, cumulative_number_of_packets_lost=%u, extended_highest_sequence=%u, interarrival_jitter=%u", ssrc, fraction_lost, cumulative_number_of_packets_lost, extended_highest_sequence, interarrival_jitter); char protected_buf[kRtpPacketSize]; @@ -2148,20 +2144,13 @@ srs_error_t SrsRtcConnection::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_ return srs_error_wrap(err, "protect rtcp rr"); } - // TDOO: FIXME: Check error. - sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); - return err; + return sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); } srs_error_t SrsRtcConnection::send_rtcp_xr_rrtr(uint32_t ssrc) { srs_error_t err = srs_success; - // If DTLS is not OK, drop all messages. - if (!transport_) { - return err; - } - /* @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2 @@ -2218,11 +2207,6 @@ srs_error_t SrsRtcConnection::send_rtcp_fb_pli(uint32_t ssrc) { srs_error_t err = srs_success; - // If DTLS is not OK, drop all messages. - if (!transport_) { - return err; - } - char buf[kRtpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); stream.write_1bytes(0x81); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 3e22995f0..21b66ecf0 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1564,7 +1564,15 @@ void SrsRtcRecvTrack::update_send_report_time(const SrsNtp& ntp) srs_error_t SrsRtcRecvTrack::send_rtcp_rr() { - return session_->send_rtcp_rr(track_desc_->ssrc_, rtp_queue_, last_sender_report_sys_time, last_sender_report_ntp); + srs_error_t err = srs_success; + + uint32_t ssrc = track_desc_->ssrc_; + const uint64_t& last_time = last_sender_report_sys_time; + if ((err = session_->send_rtcp_rr(ssrc, rtp_queue_, last_time, last_sender_report_ntp)) != srs_success) { + return srs_error_wrap(err, "send RR ssrc=%u, last_time=%" PRId64, ssrc, last_time); + } + + return err; } srs_error_t SrsRtcRecvTrack::send_rtcp_xr_rrtr() From f149c84dd06ebbcfdb6f8ca43270947ffdaa14e9 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 17:24:26 +0800 Subject: [PATCH 33/36] RTC: Check error for send_rtcp_rr --- trunk/src/app/srs_app_rtc_conn.cpp | 19 +++++++++++-------- trunk/src/app/srs_app_rtc_source.cpp | 10 ++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 676856023..7c9a14faa 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -958,12 +958,16 @@ srs_error_t SrsRtcPublishStream::send_rtcp_xr_rrtr() for (int i = 0; i < (int)video_tracks_.size(); ++i) { SrsRtcVideoRecvTrack* track = video_tracks_.at(i); - track->send_rtcp_xr_rrtr(); + if ((err = track->send_rtcp_xr_rrtr()) != srs_success) { + return srs_error_wrap(err, "track=%s", track->get_track_id().c_str()); + } } for (int i = 0; i < (int)audio_tracks_.size(); ++i) { SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); - track->send_rtcp_xr_rrtr(); + if ((err = track->send_rtcp_xr_rrtr()) != srs_success) { + return srs_error_wrap(err, "track=%s", track->get_track_id().c_str()); + } } session_->stat_->nn_xr++; @@ -1521,8 +1525,10 @@ srs_error_t SrsRtcPublishStream::notify(int type, srs_utime_t interval, srs_utim srs_freep(err); } - // TODO: FIXME: Check error. - send_rtcp_xr_rrtr(); + if ((err = send_rtcp_xr_rrtr()) != srs_success) { + srs_warn("XR err %s", srs_error_desc(err).c_str()); + srs_freep(err); + } // TODO: FIXME: Check error. // We should not depends on the received packet, @@ -2197,10 +2203,7 @@ srs_error_t SrsRtcConnection::send_rtcp_xr_rrtr(uint32_t ssrc) return srs_error_wrap(err, "protect rtcp xr"); } - // TDOO: FIXME: Check error. - sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); - - return err; + return sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); } srs_error_t SrsRtcConnection::send_rtcp_fb_pli(uint32_t ssrc) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 21b66ecf0..d4648b0c3 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1569,7 +1569,7 @@ srs_error_t SrsRtcRecvTrack::send_rtcp_rr() uint32_t ssrc = track_desc_->ssrc_; const uint64_t& last_time = last_sender_report_sys_time; if ((err = session_->send_rtcp_rr(ssrc, rtp_queue_, last_time, last_sender_report_ntp)) != srs_success) { - return srs_error_wrap(err, "send RR ssrc=%u, last_time=%" PRId64, ssrc, last_time); + return srs_error_wrap(err, "ssrc=%u, last_time=%" PRId64, ssrc, last_time); } return err; @@ -1577,7 +1577,13 @@ srs_error_t SrsRtcRecvTrack::send_rtcp_rr() srs_error_t SrsRtcRecvTrack::send_rtcp_xr_rrtr() { - return session_->send_rtcp_xr_rrtr(track_desc_->ssrc_); + srs_error_t err = srs_success; + + if ((err = session_->send_rtcp_xr_rrtr(track_desc_->ssrc_)) != srs_success) { + return srs_error_wrap(err, "ssrc=%u", track_desc_->ssrc_); + } + + return err; } bool SrsRtcRecvTrack::set_track_status(bool active) From 5c853e02ee7c6b6d2368dd5d458ea73ec3a2b8b3 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 17:46:56 +0800 Subject: [PATCH 34/36] RTC: Check error for send_periodic_twcc --- trunk/src/app/srs_app_rtc_conn.cpp | 46 ++++++++++++++---------------- trunk/src/app/srs_app_rtc_conn.hpp | 1 - 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 7c9a14faa..9f3894599 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -808,7 +808,6 @@ SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session) nn_audio_frames = 0; twcc_id_ = 0; - last_twcc_feedback_time_ = 0; twcc_fb_count_ = 0; } @@ -1133,30 +1132,25 @@ void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer srs_error_t SrsRtcPublishStream::send_periodic_twcc() { srs_error_t err = srs_success; - srs_utime_t now = srs_get_system_time(); - if(0 == last_twcc_feedback_time_) { - last_twcc_feedback_time_ = now; - return err; - } - srs_utime_t diff = now - last_twcc_feedback_time_; - if( diff >= 50 * SRS_UTIME_MILLISECONDS) { - last_twcc_feedback_time_ = now; - char pkt[kRtcpPacketSize]; - SrsBuffer *buffer = new SrsBuffer(pkt, sizeof(pkt)); - SrsAutoFree(SrsBuffer, buffer); - rtcp_twcc_.set_feedback_count(twcc_fb_count_); - twcc_fb_count_++; - if((err = rtcp_twcc_.encode(buffer)) != srs_success) { - return srs_error_wrap(err, "fail to generate twcc feedback packet"); - } - int nb_protected_buf = buffer->pos(); - char protected_buf[kRtpPacketSize]; - if (session_->transport_->protect_rtcp(pkt, protected_buf, nb_protected_buf) == srs_success) { - session_->sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); - } + + char pkt[kRtcpPacketSize]; + SrsBuffer *buffer = new SrsBuffer(pkt, sizeof(pkt)); + SrsAutoFree(SrsBuffer, buffer); + + rtcp_twcc_.set_feedback_count(twcc_fb_count_); + twcc_fb_count_++; + + if((err = rtcp_twcc_.encode(buffer)) != srs_success) { + return srs_error_wrap(err, "encode, count=%u", twcc_fb_count_); } - return err; + int nb_protected_buf = buffer->pos(); + char protected_buf[kRtpPacketSize]; + if ((err = session_->transport_->protect_rtcp(pkt, protected_buf, nb_protected_buf)) != srs_success) { + return srs_error_wrap(err, "protect rtcp, size=%u", nb_protected_buf); + } + + return session_->sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); } srs_error_t SrsRtcPublishStream::on_rtcp(char* data, int nb_data) @@ -1530,10 +1524,12 @@ srs_error_t SrsRtcPublishStream::notify(int type, srs_utime_t interval, srs_utim srs_freep(err); } - // TODO: FIXME: Check error. // We should not depends on the received packet, // instead we should send feedback every Nms. - send_periodic_twcc(); + if ((err = send_periodic_twcc()) != srs_success) { + srs_warn("TWCC err %s", srs_error_desc(err).c_str()); + srs_freep(err); + } } return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index afe96eb04..35d86752a 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -242,7 +242,6 @@ private: std::vector audio_tracks_; std::vector video_tracks_; private: - srs_utime_t last_twcc_feedback_time_; int twcc_id_; uint8_t twcc_fb_count_; SrsRtcpTWCC rtcp_twcc_; From 70d561421c583e5f3ee1e0b6455e6a0c2c79dd67 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Aug 2020 18:06:54 +0800 Subject: [PATCH 35/36] RTC: Check error for send_rtcp_fb_pli --- trunk/src/app/srs_app_rtc_conn.cpp | 5 +---- trunk/src/app/srs_app_rtc_source.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 9f3894599..e7ff1a8d3 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -2226,10 +2226,7 @@ srs_error_t SrsRtcConnection::send_rtcp_fb_pli(uint32_t ssrc) return srs_error_wrap(err, "protect rtcp psfb pli"); } - // TDOO: FIXME: Check error. - sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); - - return err; + return sendonly_skt->sendto(protected_buf, nb_protected_buf, 0); } void SrsRtcConnection::simulate_nack_drop(int nn) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index d4648b0c3..9f37932ad 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1704,8 +1704,11 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk if (request_key_frame_) { // TODO: FIXME: add coroutine to request key frame. request_key_frame_ = false; - // TODO: FIXME: Check error. - session_->send_rtcp_fb_pli(track_desc_->ssrc_); + + if ((err = session_->send_rtcp_fb_pli(track_desc_->ssrc_)) != srs_success) { + srs_warn("PLI err %s", srs_error_desc(err).c_str()); + srs_freep(err); + } } // For NACK to handle packet. From 9530ea73e337fda5507053859a155e849e9ca3c9 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 6 Aug 2020 11:15:28 +0800 Subject: [PATCH 36/36] RTC: Refine error check. 4.0.37 --- README.md | 1 + trunk/src/core/srs_core_version4.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a8ceb58ca..281c939ea 100755 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2020-08-06, RTC: Refine error check. 4.0.37 * v4.0, 2020-07-25, RTC: Support multiple address for client. 4.0.36 * v4.0, 2020-07-11, Refine log context with random string. 4.0.35 * v4.0, 2020-07-04, Fix some bugs for RTC. 4.0.34 diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 035cfb349..8c04a607d 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 36 +#define SRS_VERSION4_REVISION 37 #endif