mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
For RTC publisher, support black-hole
This commit is contained in:
parent
e4329fd1a0
commit
7692e589ed
5 changed files with 146 additions and 17 deletions
|
@ -461,6 +461,16 @@ rtc_server {
|
|||
# then system queue is 2000*4 = 8k, user can incrase reuseport to incrase the queue.
|
||||
# default: 2000
|
||||
queue_length 2000;
|
||||
# The black-hole to copy packet to, for debugging.
|
||||
# For example, when debugging Chrome publish stream, the received packets are encrypted cipher,
|
||||
# we can set the publisher black-hole, SRS will copy the plaintext packets to black-hole, and
|
||||
# we are able to capture the plaintext packets by wireshark.
|
||||
black_hole {
|
||||
# Whether enable the black-hole.
|
||||
enabled off;
|
||||
# The black-hole address for publisher, or SRS as receiver.
|
||||
publisher 127.0.0.1:10000;
|
||||
}
|
||||
}
|
||||
|
||||
vhost rtc.vhost.srs.com {
|
||||
|
|
|
@ -3645,7 +3645,7 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
string n = conf->at(i)->name;
|
||||
if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa"
|
||||
&& n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus"
|
||||
&& n != "padding" && n != "perf_stat" && n != "queue_length") {
|
||||
&& n != "padding" && n != "perf_stat" && n != "queue_length" && n != "black_hole") {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -4742,7 +4742,7 @@ std::string SrsConfig::get_rtc_server_candidates()
|
|||
return DEFAULT;
|
||||
}
|
||||
|
||||
return (conf->arg0().c_str());
|
||||
return conf->arg0();
|
||||
}
|
||||
|
||||
bool SrsConfig::get_rtc_server_ecdsa()
|
||||
|
@ -4943,6 +4943,50 @@ int SrsConfig::get_rtc_server_queue_length()
|
|||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
bool SrsConfig::get_rtc_server_black_hole()
|
||||
{
|
||||
static bool DEFAULT = false;
|
||||
|
||||
SrsConfDirective* conf = root->get("rtc_server");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("black_hole");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("enabled");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
||||
}
|
||||
|
||||
std::string SrsConfig::get_rtc_server_black_hole_publisher()
|
||||
{
|
||||
static string DEFAULT = "";
|
||||
|
||||
SrsConfDirective* conf = root->get("rtc_server");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("black_hole");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("publisher");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
return conf->arg0();
|
||||
}
|
||||
|
||||
SrsConfDirective* SrsConfig::get_rtc(string vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
|
|
@ -534,6 +534,8 @@ public:
|
|||
virtual int get_rtc_server_padding();
|
||||
virtual bool get_rtc_server_perf_stat();
|
||||
virtual int get_rtc_server_queue_length();
|
||||
virtual bool get_rtc_server_black_hole();
|
||||
virtual std::string get_rtc_server_black_hole_publisher();
|
||||
private:
|
||||
virtual int get_rtc_server_reuseport2();
|
||||
virtual bool get_rtc_server_gso2();
|
||||
|
|
|
@ -62,6 +62,7 @@ using namespace std;
|
|||
#include <srs_app_http_api.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
#include <srs_app_pithy_print.hpp>
|
||||
#include <srs_service_st.hpp>
|
||||
|
||||
// The RTP payload max size, reserved some paddings for SRTP as such:
|
||||
// kRtpPacketSize = kRtpMaxPayloadSize + paddings
|
||||
|
@ -296,6 +297,12 @@ srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* skt)
|
|||
}
|
||||
}
|
||||
|
||||
if (rtc_session->blackhole && rtc_session->blackhole_addr && rtc_session->blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = out_bio_data; int len = out_bio_len; SrsRtcSession* s = rtc_session;
|
||||
srs_sendto(s->blackhole_stfd, p, len, (sockaddr*)s->blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -314,6 +321,12 @@ srs_error_t SrsDtlsSession::on_dtls(SrsUdpMuxSocket* skt)
|
|||
return srs_error_new(ERROR_OpenSslBIOWrite, "BIO_write");
|
||||
}
|
||||
|
||||
if (rtc_session->blackhole && rtc_session->blackhole_addr && rtc_session->blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = skt->data(); int len = skt->size(); SrsRtcSession* s = rtc_session;
|
||||
srs_sendto(s->blackhole_stfd, p, len, (sockaddr*)s->blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
if (!handshake_done) {
|
||||
err = handshake(skt);
|
||||
} else {
|
||||
|
@ -2159,6 +2172,10 @@ SrsRtcSession::SrsRtcSession(SrsRtcServer* s, SrsRequest* r, const std::string&
|
|||
session_state = INIT;
|
||||
last_stun_time = 0;
|
||||
sessionStunTimeout = 0;
|
||||
|
||||
blackhole = false;
|
||||
blackhole_addr = NULL;
|
||||
blackhole_stfd = NULL;
|
||||
}
|
||||
|
||||
SrsRtcSession::~SrsRtcSession()
|
||||
|
@ -2167,6 +2184,8 @@ SrsRtcSession::~SrsRtcSession()
|
|||
srs_freep(publisher);
|
||||
srs_freep(dtls_session);
|
||||
srs_freep(req);
|
||||
srs_close_stfd(blackhole_stfd);
|
||||
srs_freep(blackhole_addr);
|
||||
}
|
||||
|
||||
void SrsRtcSession::set_local_sdp(const SrsSdp& sdp)
|
||||
|
@ -2191,6 +2210,30 @@ srs_error_t SrsRtcSession::initialize()
|
|||
sessionStunTimeout = _srs_config->get_rtc_stun_timeout(req->vhost);
|
||||
last_stun_time = srs_get_system_time();
|
||||
|
||||
blackhole = _srs_config->get_rtc_server_black_hole();
|
||||
|
||||
srs_trace("RTC init session, timeout=%dms, blackhole=%d", srsu2msi(sessionStunTimeout), blackhole);
|
||||
|
||||
if (blackhole) {
|
||||
string blackhole_ep = _srs_config->get_rtc_server_black_hole_publisher();
|
||||
if (!blackhole_ep.empty()) {
|
||||
string host; int port;
|
||||
srs_parse_hostport(blackhole_ep, host, port);
|
||||
|
||||
srs_freep(blackhole_addr);
|
||||
blackhole_addr = new sockaddr_in();
|
||||
blackhole_addr->sin_family = AF_INET;
|
||||
blackhole_addr->sin_addr.s_addr = inet_addr(host.c_str());
|
||||
blackhole_addr->sin_port = htons(port);
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
blackhole_stfd = srs_netfd_open_socket(fd);
|
||||
srs_assert(blackhole_stfd);
|
||||
|
||||
srs_trace("RTC blackhole %s:%d, fd=%d", host.c_str(), port, fd);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2274,6 +2317,19 @@ srs_error_t SrsRtcSession::on_binding_request(SrsUdpMuxSocket* skt, SrsStunPacke
|
|||
srs_trace("rtc session=%s, STUN done, waitting DTLS handshake.", id().c_str());
|
||||
}
|
||||
|
||||
// Write STUN messages to blackhole.
|
||||
if (blackhole && blackhole_addr && blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = skt->data(); int len = skt->size();
|
||||
srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
if (blackhole && blackhole_addr && blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = stream->data(); int len = stream->pos();
|
||||
srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2610,6 +2666,12 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* skt)
|
|||
return srs_error_wrap(err, "rtcp unprotect failed");
|
||||
}
|
||||
|
||||
if (blackhole && blackhole_addr && blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = unprotected_buf; int len = nb_unprotected_buf;
|
||||
srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
char* ph = unprotected_buf;
|
||||
int nb_left = nb_unprotected_buf;
|
||||
while (nb_left) {
|
||||
|
@ -2683,12 +2745,18 @@ srs_error_t SrsRtcSession::on_rtp(SrsUdpMuxSocket* skt)
|
|||
return srs_error_new(ERROR_RTC_RTCP, "recv unexpect rtp packet before dtls done");
|
||||
}
|
||||
|
||||
char* unprotected_buf = new char[1460];
|
||||
char* unprotected_buf = new char[kRtpPacketSize];
|
||||
int nb_unprotected_buf = skt->size();
|
||||
if ((err = dtls_session->unprotect_rtp(unprotected_buf, skt->data(), nb_unprotected_buf)) != srs_success) {
|
||||
return srs_error_wrap(err, "rtp unprotect failed");
|
||||
}
|
||||
|
||||
if (blackhole && blackhole_addr && blackhole_stfd) {
|
||||
// Ignore any error for black-hole.
|
||||
void* p = unprotected_buf; int len = nb_unprotected_buf;
|
||||
srs_sendto(blackhole_stfd, p, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
return publisher->on_rtp(skt, unprotected_buf, nb_unprotected_buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -305,6 +305,7 @@ public:
|
|||
|
||||
class SrsRtcSession
|
||||
{
|
||||
friend class SrsDtlsSession;
|
||||
friend class SrsRtcSenderThread;
|
||||
friend class SrsRtcPublisher;
|
||||
private:
|
||||
|
@ -327,6 +328,10 @@ private:
|
|||
bool encrypt;
|
||||
// The timeout of session, keep alive by STUN ping pong.
|
||||
srs_utime_t sessionStunTimeout;
|
||||
private:
|
||||
bool blackhole;
|
||||
sockaddr_in* blackhole_addr;
|
||||
srs_netfd_t blackhole_stfd;
|
||||
public:
|
||||
SrsRequest* req;
|
||||
SrsSource* source;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue