mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
add rtc http request and response, exchange sdp.
This commit is contained in:
parent
3ce5f6ce6a
commit
bc22ebe949
11 changed files with 488 additions and 2 deletions
2
trunk/configure
vendored
2
trunk/configure
vendored
|
@ -254,7 +254,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
|
||||||
"srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_edge"
|
"srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_edge"
|
||||||
"srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
|
"srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
|
||||||
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
|
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
|
||||||
"srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
|
"srs_app_mpegts_udp" "srs_app_rtc_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
|
||||||
"srs_app_caster_flv" "srs_app_process" "srs_app_ng_exec"
|
"srs_app_caster_flv" "srs_app_process" "srs_app_ng_exec"
|
||||||
"srs_app_hourglass" "srs_app_dash" "srs_app_fragment" "srs_app_dvr"
|
"srs_app_hourglass" "srs_app_dash" "srs_app_fragment" "srs_app_dvr"
|
||||||
"srs_app_coworkers" "srs_app_hybrid")
|
"srs_app_coworkers" "srs_app_hybrid")
|
||||||
|
|
90
trunk/research/players/srs_rtc_player.html
Normal file
90
trunk/research/players/srs_rtc_player.html
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cmn-Hans">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
rtc_media_player: <br>
|
||||||
|
<video id = "rtc_media_player" autoplay></video>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var PeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
|
||||||
|
var SessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
|
||||||
|
|
||||||
|
var url = "http://hw.com:1985/api/v1/sdp/";
|
||||||
|
|
||||||
|
var method = "POST";
|
||||||
|
var shouldBeAsync = true;
|
||||||
|
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open(method, url, shouldBeAsync);
|
||||||
|
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
|
||||||
|
var pc = new PeerConnection(null);
|
||||||
|
|
||||||
|
var constraints = {
|
||||||
|
mandatory: {
|
||||||
|
OfferToReceiveAudio: true,
|
||||||
|
OfferToReceiveVideo: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var sendViewerOfferFn = function(desc) {
|
||||||
|
console.log('sendViewerOfferFn:', desc);
|
||||||
|
|
||||||
|
pc.setLocalDescription(desc);
|
||||||
|
|
||||||
|
var sdp_json = {"sdp":desc.sdp, "app":"webrtc", "stream":"test"};
|
||||||
|
request.send(JSON.stringify(sdp_json));
|
||||||
|
};
|
||||||
|
|
||||||
|
pc.createOffer(sendViewerOfferFn,
|
||||||
|
function(error) {
|
||||||
|
console.log('sendViewerOfferFn error:' + error);
|
||||||
|
},
|
||||||
|
constraints
|
||||||
|
);
|
||||||
|
|
||||||
|
pc.onaddstream = function(event) {
|
||||||
|
console.log('onaddstream');
|
||||||
|
document.getElementById('rtc_media_player').srcObject = event.stream;
|
||||||
|
rtc_media_player.load();
|
||||||
|
};
|
||||||
|
|
||||||
|
pc.onicecandidate = function(event) {
|
||||||
|
console.log('onicecandidate');
|
||||||
|
};
|
||||||
|
|
||||||
|
pc.onconnectionstatechange = function(event) {
|
||||||
|
console.log('onconnectionstatechange');
|
||||||
|
};
|
||||||
|
|
||||||
|
pc.onicegatheringstatechange = function(event) {
|
||||||
|
console.log('onicegatheringstatechange');
|
||||||
|
};
|
||||||
|
|
||||||
|
pc.onsignalingstatechange = function(event) {
|
||||||
|
console.log('onsignalingstatechange');
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function(event) {
|
||||||
|
console.log('http error');
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onload = function () {
|
||||||
|
console.log('onload,' , request.responseText);
|
||||||
|
var json = JSON.parse(request.responseText);
|
||||||
|
console.log('onmessage viewerResponse:', json.sdp);
|
||||||
|
|
||||||
|
pc.setRemoteDescription(new SessionDescription({type:'answer', sdp:json.sdp}));
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
|
@ -3486,7 +3486,7 @@ srs_error_t SrsConfig::check_normal_config()
|
||||||
&& n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file"
|
&& n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file"
|
||||||
&& n != "max_connections" && n != "daemon" && n != "heartbeat"
|
&& n != "max_connections" && n != "daemon" && n != "heartbeat"
|
||||||
&& n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
|
&& n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
|
||||||
&& n != "http_server" && n != "stream_caster" && n != "srt_server"
|
&& n != "http_server" && n != "stream_caster" && n != "rtc" && n != "srt_server"
|
||||||
&& n != "utc_time" && n != "work_dir" && n != "asprocess"
|
&& n != "utc_time" && n != "work_dir" && n != "asprocess"
|
||||||
&& n != "ff_log_level" && n != "grace_final_wait" && n != "force_grace_quit"
|
&& n != "ff_log_level" && n != "grace_final_wait" && n != "force_grace_quit"
|
||||||
&& n != "grace_start_wait"
|
&& n != "grace_start_wait"
|
||||||
|
@ -4216,6 +4216,45 @@ int SrsConfig::get_stream_caster_rtp_port_max(SrsConfDirective* conf)
|
||||||
return ::atoi(conf->arg0().c_str());
|
return ::atoi(conf->arg0().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_rtc_enabled()
|
||||||
|
{
|
||||||
|
SrsConfDirective* conf = root->get("rtc");
|
||||||
|
return get_rtc_enabled(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::get_rtc_enabled(SrsConfDirective* conf)
|
||||||
|
{
|
||||||
|
static bool DEFAULT = false;
|
||||||
|
|
||||||
|
if (!conf) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = conf->get("enabled");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_rtc_listen()
|
||||||
|
{
|
||||||
|
static int DEFAULT = 9527;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("rtc");
|
||||||
|
if (!conf) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = conf->get("listen");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::atoi(conf->arg0().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_vhost(string vhost, bool try_default_vhost)
|
SrsConfDirective* SrsConfig::get_vhost(string vhost, bool try_default_vhost)
|
||||||
{
|
{
|
||||||
srs_assert(root);
|
srs_assert(root);
|
||||||
|
|
|
@ -490,6 +490,13 @@ public:
|
||||||
virtual int get_stream_caster_rtp_port_min(SrsConfDirective* conf);
|
virtual int get_stream_caster_rtp_port_min(SrsConfDirective* conf);
|
||||||
// Get the max udp port for rtp of stream caster rtsp.
|
// Get the max udp port for rtp of stream caster rtsp.
|
||||||
virtual int get_stream_caster_rtp_port_max(SrsConfDirective* conf);
|
virtual int get_stream_caster_rtp_port_max(SrsConfDirective* conf);
|
||||||
|
|
||||||
|
// rtc section
|
||||||
|
public:
|
||||||
|
virtual int get_rtc_enabled();
|
||||||
|
virtual bool get_rtc_enabled(SrsConfDirective* conf);
|
||||||
|
virtual int get_rtc_listen();
|
||||||
|
|
||||||
// vhost specified section
|
// vhost specified section
|
||||||
public:
|
public:
|
||||||
// Get the vhost directive by vhost name.
|
// Get the vhost directive by vhost name.
|
||||||
|
|
|
@ -47,6 +47,73 @@ using namespace std;
|
||||||
#include <srs_protocol_utility.hpp>
|
#include <srs_protocol_utility.hpp>
|
||||||
#include <srs_app_coworkers.hpp>
|
#include <srs_app_coworkers.hpp>
|
||||||
|
|
||||||
|
string test_sdp =
|
||||||
|
"v=0\\r\\n"
|
||||||
|
"o=- 0 0 IN IP4 127.0.0.1\\r\\n"
|
||||||
|
"s=-\\r\\n"
|
||||||
|
"t=0 0\\r\\n"
|
||||||
|
"a=ice-lite\\r\\n"
|
||||||
|
"a=group:BUNDLE 0 1\\r\\n"
|
||||||
|
"a=msid-semantic: WMS 6VrfBKXrwK\\r\\n"
|
||||||
|
"m=audio 9 UDP/TLS/RTP/SAVPF 111\\r\\n"
|
||||||
|
"c=IN IP4 0.0.0.0\\r\\n"
|
||||||
|
"a=candidate:10 1 udp 2115783679 192.168.170.129 9527 typ host generation 0\\r\\n"
|
||||||
|
"a=rtcp:9 IN IP4 0.0.0.0\\r\\n"
|
||||||
|
"a=ice-ufrag:xiaozhihongjohn\\r\\n"
|
||||||
|
"a=ice-pwd:simple_rtmp_server__john\\r\\n"
|
||||||
|
"a=ice-options:trickle\\r\\n"
|
||||||
|
"a=fingerprint:sha-256 76:E8:6A:6D:48:F0:86:58:30:2E:69:56:0F:C6:A1:B8:69:98:5D:73:45:93:37:8E:C4:2B:C7:97:04:18:E4:24\\r\\n"
|
||||||
|
"a=sendrecv\\r\\n"
|
||||||
|
"a=mid:0\\r\\n"
|
||||||
|
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\\r\\n"
|
||||||
|
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\\r\\n"
|
||||||
|
"a=rtcp-mux\\r\\n"
|
||||||
|
"a=rtpmap:111 opus/48000/2\\r\\n"
|
||||||
|
"a=fmtp:111 minptime=10;useinbandfec=1\\r\\n"
|
||||||
|
"a=maxptime:60\\r\\n"
|
||||||
|
"a=ssrc:3233846890 cname:o/i14u9pJrxRKAsu\\r\\n"
|
||||||
|
"a=ssrc:3233846890 msid:6VrfBKXrwK a0\\r\\n"
|
||||||
|
"a=ssrc:3233846890 mslabel:6VrfBKXrwK\\r\\n"
|
||||||
|
"a=ssrc:3233846890 label:6VrfBKXrwKa0\\r\\n"
|
||||||
|
"m=video 9 UDP/TLS/RTP/SAVPF 96 98 102\\r\\n"
|
||||||
|
"c=IN IP4 0.0.0.0\\r\\n"
|
||||||
|
"a=candidate:10 1 udp 2115783679 192.168.170.129 9527 typ host generation 0\\r\\n"
|
||||||
|
"a=rtcp:9 IN IP4 0.0.0.0\\r\\n"
|
||||||
|
"b=as:2000000\\r\\n"
|
||||||
|
"a=ice-ufrag:xiaozhihongjohn\\r\\n"
|
||||||
|
"a=ice-pwd:simple_rtmp_server__john\\r\\n"
|
||||||
|
"a=ice-options:trickle\\r\\n"
|
||||||
|
"a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\\r\\n"
|
||||||
|
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\\r\\n"
|
||||||
|
"a=extmap:4 urn:3gpp:video-orientation\\r\\n"
|
||||||
|
"a=fingerprint:sha-256 76:E8:6A:6D:48:F0:86:58:30:2E:69:56:0F:C6:A1:B8:69:98:5D:73:45:93:37:8E:C4:2B:C7:97:04:18:E4:24\\r\\n"
|
||||||
|
"a=sendrecv\\r\\n"
|
||||||
|
"a=mid:1\\r\\n"
|
||||||
|
"a=rtcp-mux\\r\\n"
|
||||||
|
"a=rtpmap:96 VP8/90000\\r\\n"
|
||||||
|
"a=rtcp-fb:96 ccm fir\\r\\n"
|
||||||
|
"a=rtcp-fb:96 nack\\r\\n"
|
||||||
|
"a=rtcp-fb:96 nack pli\\r\\n"
|
||||||
|
"a=rtcp-fb:96 goog-remb\\r\\n"
|
||||||
|
"a=rtcp-fb:96 transport-cc\\r\\n"
|
||||||
|
"a=rtpmap:98 VP9/90000\\r\\n"
|
||||||
|
"a=rtcp-fb:98 ccm fir\\r\\n"
|
||||||
|
"a=rtcp-fb:98 nack\\r\\n"
|
||||||
|
"a=rtcp-fb:98 nack pli\\r\\n"
|
||||||
|
"a=rtcp-fb:98 goog-remb\\r\\n"
|
||||||
|
"a=rtcp-fb:98 transport-cc\\r\\n"
|
||||||
|
"a=rtpmap:102 H264/90000\\r\\n"
|
||||||
|
"a=rtcp-fb:102 goog-remb\\r\\n"
|
||||||
|
"a=rtcp-fb:102 transport-cc\\r\\n"
|
||||||
|
"a=rtcp-fb:102 ccm fir \\r\\n"
|
||||||
|
"a=rtcp-fb:102 nack\\r\\n"
|
||||||
|
"a=rtcp-fb:102 nack pli \\r\\n"
|
||||||
|
"a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\\r\\n"
|
||||||
|
"a=ssrc:3233846889 cname:o/i14u9pJrxRKAsu\\r\\n"
|
||||||
|
"a=ssrc:3233846889 msid:6VrfBKXrwK v0\\r\\n"
|
||||||
|
"a=ssrc:3233846889 mslabel:6VrfBKXrwK\\r\\n"
|
||||||
|
"a=ssrc:3233846889 label:6VrfBKXrwKv0\\r\\n";
|
||||||
|
|
||||||
srs_error_t srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data)
|
srs_error_t srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -780,6 +847,44 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
||||||
return srs_api_response(w, r, obj->dumps());
|
return srs_api_response(w, r, obj->dumps());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsGoApiSdp::SrsGoApiSdp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoApiSdp::~SrsGoApiSdp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsGoApiSdp::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
SrsStatistic* stat = SrsStatistic::instance();
|
||||||
|
|
||||||
|
// path: {pattern}{stream_id}
|
||||||
|
// e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100
|
||||||
|
int sid = r->parse_rest_id(entry->pattern);
|
||||||
|
|
||||||
|
SrsStatisticStream* stream = NULL;
|
||||||
|
if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) {
|
||||||
|
return srs_api_response_code(w, r, ERROR_RTMP_STREAM_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsJsonObject* obj = SrsJsonAny::object();
|
||||||
|
SrsAutoFree(SrsJsonObject, obj);
|
||||||
|
|
||||||
|
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||||
|
obj->set("server", SrsJsonAny::integer(stat->server_id()));
|
||||||
|
|
||||||
|
if (r->is_http_post()) {
|
||||||
|
obj->set("sdp", SrsJsonAny::str(test_sdp.c_str()));
|
||||||
|
} else {
|
||||||
|
return srs_go_http_error(w, SRS_CONSTS_HTTP_MethodNotAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs_api_response(w, r, obj->dumps());
|
||||||
|
}
|
||||||
|
|
||||||
SrsGoApiClients::SrsGoApiClients()
|
SrsGoApiClients::SrsGoApiClients()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,15 @@ public:
|
||||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
|
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SrsGoApiSdp : public ISrsHttpHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsGoApiSdp();
|
||||||
|
virtual ~SrsGoApiSdp();
|
||||||
|
public:
|
||||||
|
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
|
||||||
|
};
|
||||||
|
|
||||||
class SrsGoApiClients : public ISrsHttpHandler
|
class SrsGoApiClients : public ISrsHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
89
trunk/src/app/srs_app_rtc_udp.cpp
Normal file
89
trunk/src/app/srs_app_rtc_udp.cpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2020 Winlin
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <srs_app_rtc_udp.hpp>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <srs_app_config.hpp>
|
||||||
|
#include <srs_kernel_error.hpp>
|
||||||
|
#include <srs_kernel_log.hpp>
|
||||||
|
#include <srs_app_config.hpp>
|
||||||
|
#include <srs_kernel_ts.hpp>
|
||||||
|
#include <srs_kernel_buffer.hpp>
|
||||||
|
#include <srs_kernel_ts.hpp>
|
||||||
|
#include <srs_kernel_stream.hpp>
|
||||||
|
#include <srs_kernel_file.hpp>
|
||||||
|
#include <srs_core_autofree.hpp>
|
||||||
|
#include <srs_kernel_utility.hpp>
|
||||||
|
#include <srs_rtmp_stack.hpp>
|
||||||
|
#include <srs_app_st.hpp>
|
||||||
|
#include <srs_protocol_utility.hpp>
|
||||||
|
#include <srs_app_utility.hpp>
|
||||||
|
#include <srs_protocol_amf0.hpp>
|
||||||
|
#include <srs_raw_avc.hpp>
|
||||||
|
#include <srs_app_pithy_print.hpp>
|
||||||
|
#include <srs_app_rtmp_conn.hpp>
|
||||||
|
#include <srs_protocol_utility.hpp>
|
||||||
|
|
||||||
|
SrsRtcOverUdp::SrsRtcOverUdp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRtcOverUdp::~SrsRtcOverUdp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtcOverUdp::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
|
||||||
|
{
|
||||||
|
char address_string[64];
|
||||||
|
char port_string[16];
|
||||||
|
if(getnameinfo(from, fromlen,
|
||||||
|
(char*)&address_string, sizeof(address_string),
|
||||||
|
(char*)&port_string, sizeof(port_string),
|
||||||
|
NI_NUMERICHOST|NI_NUMERICSERV)) {
|
||||||
|
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||||
|
}
|
||||||
|
std::string peer_ip = std::string(address_string);
|
||||||
|
int peer_port = atoi(port_string);
|
||||||
|
|
||||||
|
srs_error_t err = on_udp_bytes(peer_ip, peer_port, buf, nb_buf);
|
||||||
|
if (err != srs_success) {
|
||||||
|
return srs_error_wrap(err, "process udp");
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtcOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf)
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
srs_trace("recv rtc udp packet from %s:%d, nb_buf=%d", host.c_str(), port, nb_buf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
52
trunk/src/app/srs_app_rtc_udp.hpp
Normal file
52
trunk/src/app/srs_app_rtc_udp.hpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2020 Winlin
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRS_APP_RTC_UDP_HPP
|
||||||
|
#define SRS_APP_RTC_UDP_HPP
|
||||||
|
|
||||||
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
|
struct sockaddr;
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <srs_app_st.hpp>
|
||||||
|
#include <srs_kernel_ts.hpp>
|
||||||
|
#include <srs_app_listener.hpp>
|
||||||
|
|
||||||
|
// The rtc over udp stream receiver
|
||||||
|
class SrsRtcOverUdp : virtual public ISrsUdpHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
SrsRtcOverUdp();
|
||||||
|
virtual ~SrsRtcOverUdp();
|
||||||
|
// Interface ISrsUdpHandler
|
||||||
|
public:
|
||||||
|
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||||
|
private:
|
||||||
|
virtual srs_error_t on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -44,6 +44,7 @@ using namespace std;
|
||||||
#include <srs_app_utility.hpp>
|
#include <srs_app_utility.hpp>
|
||||||
#include <srs_app_heartbeat.hpp>
|
#include <srs_app_heartbeat.hpp>
|
||||||
#include <srs_app_mpegts_udp.hpp>
|
#include <srs_app_mpegts_udp.hpp>
|
||||||
|
#include <srs_app_rtc_udp.hpp>
|
||||||
#include <srs_app_rtsp.hpp>
|
#include <srs_app_rtsp.hpp>
|
||||||
#include <srs_app_statistic.hpp>
|
#include <srs_app_statistic.hpp>
|
||||||
#include <srs_app_caster_flv.hpp>
|
#include <srs_app_caster_flv.hpp>
|
||||||
|
@ -108,6 +109,8 @@ std::string srs_listener_type2string(SrsListenerType type)
|
||||||
return "RTSP";
|
return "RTSP";
|
||||||
case SrsListenerFlv:
|
case SrsListenerFlv:
|
||||||
return "HTTP-FLV";
|
return "HTTP-FLV";
|
||||||
|
case SrsListenerRtcOverUdp:
|
||||||
|
return "RTC over UDP";
|
||||||
default:
|
default:
|
||||||
return "UNKONWN";
|
return "UNKONWN";
|
||||||
}
|
}
|
||||||
|
@ -335,6 +338,45 @@ SrsUdpCasterListener::~SrsUdpCasterListener()
|
||||||
srs_freep(caster);
|
srs_freep(caster);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsRtcListener::SrsRtcListener(SrsServer* svr, SrsListenerType t) : SrsListener(svr, t)
|
||||||
|
{
|
||||||
|
srs_assert(type == SrsListenerRtcOverUdp);
|
||||||
|
rtc = new SrsRtcOverUdp();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRtcListener::~SrsRtcListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtcListener::listen(std::string i, int p)
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
// the caller already ensure the type is ok,
|
||||||
|
// we just assert here for unknown stream caster.
|
||||||
|
srs_assert(type == SrsListenerRtcOverUdp);
|
||||||
|
|
||||||
|
ip = i;
|
||||||
|
port = p;
|
||||||
|
|
||||||
|
srs_freep(listener);
|
||||||
|
listener = new SrsUdpListener(rtc, ip, port);
|
||||||
|
|
||||||
|
if ((err = listener->listen()) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify the handler the fd changed.
|
||||||
|
if ((err = rtc->on_stfd_change(listener->stfd())) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "notify fd change failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
string v = srs_listener_type2string(type);
|
||||||
|
srs_trace("%s listen at udp://%s:%d, fd=%d", v.c_str(), ip.c_str(), port, listener->fd());
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
SrsSignalManager* SrsSignalManager::instance = NULL;
|
SrsSignalManager* SrsSignalManager::instance = NULL;
|
||||||
|
|
||||||
SrsSignalManager::SrsSignalManager(SrsServer* s)
|
SrsSignalManager::SrsSignalManager(SrsServer* s)
|
||||||
|
@ -728,6 +770,10 @@ srs_error_t SrsServer::listen()
|
||||||
if ((err = listen_stream_caster()) != srs_success) {
|
if ((err = listen_stream_caster()) != srs_success) {
|
||||||
return srs_error_wrap(err, "stream caster listen");
|
return srs_error_wrap(err, "stream caster listen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = listen_rtc()) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "rtc listen");
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = conn_manager->start()) != srs_success) {
|
if ((err = conn_manager->start()) != srs_success) {
|
||||||
return srs_error_wrap(err, "connection manager");
|
return srs_error_wrap(err, "connection manager");
|
||||||
|
@ -790,6 +836,9 @@ srs_error_t SrsServer::http_handle()
|
||||||
if ((err = http_api_mux->handle("/api/v1/streams/", new SrsGoApiStreams())) != srs_success) {
|
if ((err = http_api_mux->handle("/api/v1/streams/", new SrsGoApiStreams())) != srs_success) {
|
||||||
return srs_error_wrap(err, "handle streams");
|
return srs_error_wrap(err, "handle streams");
|
||||||
}
|
}
|
||||||
|
if ((err = http_api_mux->handle("/api/v1/sdp/", new SrsGoApiSdp())) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "handle sdp");
|
||||||
|
}
|
||||||
if ((err = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != srs_success) {
|
if ((err = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != srs_success) {
|
||||||
return srs_error_wrap(err, "handle clients");
|
return srs_error_wrap(err, "handle clients");
|
||||||
}
|
}
|
||||||
|
@ -1188,6 +1237,35 @@ srs_error_t SrsServer::listen_stream_caster()
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsServer::listen_rtc()
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
close_listeners(SrsListenerRtcOverUdp);
|
||||||
|
|
||||||
|
if (!_srs_config->get_rtc_enabled()) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsListener* listener = NULL;
|
||||||
|
|
||||||
|
listener = new SrsRtcListener(this, SrsListenerRtcOverUdp);
|
||||||
|
srs_assert(listener != NULL);
|
||||||
|
|
||||||
|
listeners.push_back(listener);
|
||||||
|
|
||||||
|
int port = _srs_config->get_rtc_listen();
|
||||||
|
if (port <= 0) {
|
||||||
|
return srs_error_new(ERROR_RTC_PORT, "invalid port=%d", port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = listener->listen(srs_any_address_for_listener(), port)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "listen at %d", port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
void SrsServer::close_listeners(SrsListenerType type)
|
void SrsServer::close_listeners(SrsListenerType type)
|
||||||
{
|
{
|
||||||
std::vector<SrsListener*>::iterator it;
|
std::vector<SrsListener*>::iterator it;
|
||||||
|
|
|
@ -68,6 +68,8 @@ enum SrsListenerType
|
||||||
SrsListenerRtsp = 4,
|
SrsListenerRtsp = 4,
|
||||||
// TCP stream, FLV stream over HTTP.
|
// TCP stream, FLV stream over HTTP.
|
||||||
SrsListenerFlv = 5,
|
SrsListenerFlv = 5,
|
||||||
|
// UDP sream, rtp over udp
|
||||||
|
SrsListenerRtcOverUdp = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A common tcp listener, for RTMP/HTTP server.
|
// A common tcp listener, for RTMP/HTTP server.
|
||||||
|
@ -155,6 +157,19 @@ public:
|
||||||
virtual ~SrsUdpCasterListener();
|
virtual ~SrsUdpCasterListener();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A UDP listener, for udp stream caster server.
|
||||||
|
class SrsRtcListener : public SrsListener
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SrsUdpListener* listener;
|
||||||
|
ISrsUdpHandler* rtc;
|
||||||
|
public:
|
||||||
|
SrsRtcListener(SrsServer* svr, SrsListenerType t);
|
||||||
|
virtual ~SrsRtcListener();
|
||||||
|
public:
|
||||||
|
virtual srs_error_t listen(std::string i, int p);
|
||||||
|
};
|
||||||
|
|
||||||
// Convert signal to io,
|
// Convert signal to io,
|
||||||
// @see: st-1.9/docs/notes.html
|
// @see: st-1.9/docs/notes.html
|
||||||
class SrsSignalManager : public ISrsCoroutineHandler
|
class SrsSignalManager : public ISrsCoroutineHandler
|
||||||
|
@ -284,6 +299,7 @@ private:
|
||||||
virtual srs_error_t listen_http_api();
|
virtual srs_error_t listen_http_api();
|
||||||
virtual srs_error_t listen_http_stream();
|
virtual srs_error_t listen_http_stream();
|
||||||
virtual srs_error_t listen_stream_caster();
|
virtual srs_error_t listen_stream_caster();
|
||||||
|
virtual srs_error_t listen_rtc();
|
||||||
// Close the listeners for specified type,
|
// Close the listeners for specified type,
|
||||||
// Remove the listen object from manager.
|
// Remove the listen object from manager.
|
||||||
virtual void close_listeners(SrsListenerType type);
|
virtual void close_listeners(SrsListenerType type);
|
||||||
|
|
|
@ -321,6 +321,7 @@
|
||||||
#define ERROR_HTTP_302_INVALID 4038
|
#define ERROR_HTTP_302_INVALID 4038
|
||||||
#define ERROR_BASE64_DECODE 4039
|
#define ERROR_BASE64_DECODE 4039
|
||||||
#define ERROR_HTTP_STREAM_EOF 4040
|
#define ERROR_HTTP_STREAM_EOF 4040
|
||||||
|
#define ERROR_RTC_PORT 4041
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// HTTP API error.
|
// HTTP API error.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue