mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #133, rtsp extract tcp/udp listener.
This commit is contained in:
parent
4807f7850d
commit
40fbfd8560
17 changed files with 876 additions and 300 deletions
|
@ -1395,7 +1395,7 @@ int SrsConfig::check_config()
|
|||
SrsConfDirective* conf = stream_caster->at(i);
|
||||
string n = conf->name;
|
||||
if (n != "enabled" && n != "caster" && n != "output"
|
||||
&& n != "listen"
|
||||
&& n != "listen" && n != "rtp_port_min" && n != "rtp_port_max"
|
||||
) {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret);
|
||||
|
@ -2065,6 +2065,30 @@ int SrsConfig::get_stream_caster_listen(SrsConfDirective* sc)
|
|||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
int SrsConfig::get_stream_caster_rtp_port_min(SrsConfDirective* sc)
|
||||
{
|
||||
srs_assert(sc);
|
||||
|
||||
SrsConfDirective* conf = sc->get("rtp_port_min");
|
||||
if (!conf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
int SrsConfig::get_stream_caster_rtp_port_max(SrsConfDirective* sc)
|
||||
{
|
||||
srs_assert(sc);
|
||||
|
||||
SrsConfDirective* conf = sc->get("rtp_port_max");
|
||||
if (!conf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
SrsConfDirective* SrsConfig::get_vhost(string vhost)
|
||||
{
|
||||
srs_assert(root);
|
||||
|
|
|
@ -481,6 +481,14 @@ public:
|
|||
* get the listen port of stream caster.
|
||||
*/
|
||||
virtual int get_stream_caster_listen(SrsConfDirective* sc);
|
||||
/**
|
||||
* get the min udp port for rtp of stream caster rtsp.
|
||||
*/
|
||||
virtual int get_stream_caster_rtp_port_min(SrsConfDirective* sc);
|
||||
/**
|
||||
* get the max udp port for rtp of stream caster rtsp.
|
||||
*/
|
||||
virtual int get_stream_caster_rtp_port_max(SrsConfDirective* sc);
|
||||
// vhost specified section
|
||||
public:
|
||||
/**
|
||||
|
|
272
trunk/src/app/srs_app_listener.cpp
Normal file
272
trunk/src/app/srs_app_listener.cpp
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 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_listener.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_app_server.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
||||
// set the max packet size.
|
||||
#define SRS_UDP_MAX_PACKET_SIZE 65535
|
||||
|
||||
// sleep in ms for udp recv packet.
|
||||
#define SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS 0
|
||||
|
||||
// nginx also set to 512
|
||||
#define SERVER_LISTEN_BACKLOG 512
|
||||
|
||||
ISrsUdpHandler::ISrsUdpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsUdpHandler::~ISrsUdpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTcpHandler::ISrsTcpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTcpHandler::~ISrsTcpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, int p)
|
||||
{
|
||||
handler = h;
|
||||
port = p;
|
||||
|
||||
_fd = -1;
|
||||
stfd = NULL;
|
||||
|
||||
nb_buf = SRS_UDP_MAX_PACKET_SIZE;
|
||||
buf = new char[nb_buf];
|
||||
|
||||
pthread = new SrsThread("udp", this, 0, true);
|
||||
}
|
||||
|
||||
SrsUdpListener::~SrsUdpListener()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
pthread->stop();
|
||||
srs_freep(pthread);
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(_fd);
|
||||
|
||||
srs_freep(buf);
|
||||
}
|
||||
|
||||
int SrsUdpListener::fd()
|
||||
{
|
||||
return _fd;
|
||||
}
|
||||
|
||||
int SrsUdpListener::listen()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
ret = ERROR_SOCKET_CREATE;
|
||||
srs_error("create linux socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create linux socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
int reuse_socket = 1;
|
||||
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||
ret = ERROR_SOCKET_SETREUSE;
|
||||
srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
ret = ERROR_SOCKET_BIND;
|
||||
srs_error("bind socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("bind socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
if ((stfd = st_netfd_open_socket(_fd)) == NULL){
|
||||
ret = ERROR_ST_OPEN_SOCKET;
|
||||
srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("st open socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create st listen thread success, port=%d", port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsUdpListener::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
for (;;) {
|
||||
// TODO: FIXME: support ipv6, @see man 7 ipv6
|
||||
sockaddr_in from;
|
||||
int nb_from = sizeof(sockaddr_in);
|
||||
int nread = 0;
|
||||
|
||||
if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) {
|
||||
srs_warn("ignore recv udp packet failed, nread=%d", nread);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ret = handler->on_udp_packet(&from, buf, nread)) != ERROR_SUCCESS) {
|
||||
srs_warn("handle udp packet failed. ret=%d", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS > 0) {
|
||||
st_usleep(SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, int p)
|
||||
{
|
||||
handler = h;
|
||||
port = p;
|
||||
|
||||
_fd = -1;
|
||||
stfd = NULL;
|
||||
|
||||
pthread = new SrsThread("tcp", this, 0, true);
|
||||
}
|
||||
|
||||
SrsTcpListener::~SrsTcpListener()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
pthread->stop();
|
||||
srs_freep(pthread);
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
int SrsTcpListener::fd()
|
||||
{
|
||||
return _fd;
|
||||
}
|
||||
|
||||
int SrsTcpListener::listen()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
ret = ERROR_SOCKET_CREATE;
|
||||
srs_error("create linux socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create linux socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
int reuse_socket = 1;
|
||||
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||
ret = ERROR_SOCKET_SETREUSE;
|
||||
srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
ret = ERROR_SOCKET_BIND;
|
||||
srs_error("bind socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("bind socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
if (::listen(_fd, SERVER_LISTEN_BACKLOG) == -1) {
|
||||
ret = ERROR_SOCKET_LISTEN;
|
||||
srs_error("listen socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("listen socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
if ((stfd = st_netfd_open_socket(_fd)) == NULL){
|
||||
ret = ERROR_ST_OPEN_SOCKET;
|
||||
srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("st open socket success. port=%d, fd=%d", port, _fd);
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create st listen thread success, port=%d", port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTcpListener::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
||||
|
||||
if(client_stfd == NULL){
|
||||
// ignore error.
|
||||
srs_error("ignore accept thread stoppped for accept client error");
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
||||
|
||||
if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
125
trunk/src/app/srs_app_listener.hpp
Normal file
125
trunk/src/app/srs_app_listener.hpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 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_LISTENER_HPP
|
||||
#define SRS_APP_LISTENER_HPP
|
||||
|
||||
/*
|
||||
#include <srs_app_listener.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_thread.hpp>
|
||||
|
||||
class sockaddr_in;
|
||||
|
||||
/**
|
||||
* the udp packet handler.
|
||||
*/
|
||||
class ISrsUdpHandler
|
||||
{
|
||||
public:
|
||||
ISrsUdpHandler();
|
||||
virtual ~ISrsUdpHandler();
|
||||
public:
|
||||
/**
|
||||
* when udp listener got a udp packet, notice server to process it.
|
||||
* @param type, the client type, used to create concrete connection,
|
||||
* for instance RTMP connection to serve client.
|
||||
* @param from, the udp packet from address.
|
||||
* @param buf, the udp packet bytes, user should copy if need to use.
|
||||
* @param nb_buf, the size of udp packet bytes.
|
||||
* @remark user should never use the buf, for it's a shared memory bytes.
|
||||
*/
|
||||
virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* the tcp connection handler.
|
||||
*/
|
||||
class ISrsTcpHandler
|
||||
{
|
||||
public:
|
||||
ISrsTcpHandler();
|
||||
virtual ~ISrsTcpHandler();
|
||||
public:
|
||||
/**
|
||||
* when got tcp client.
|
||||
*/
|
||||
virtual int on_tcp_client(st_netfd_t stfd) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* bind udp port, start thread to recv packet and handler it.
|
||||
*/
|
||||
class SrsUdpListener : public ISrsThreadHandler
|
||||
{
|
||||
private:
|
||||
int _fd;
|
||||
st_netfd_t stfd;
|
||||
SrsThread* pthread;
|
||||
private:
|
||||
char* buf;
|
||||
int nb_buf;
|
||||
private:
|
||||
ISrsUdpHandler* handler;
|
||||
int port;
|
||||
public:
|
||||
SrsUdpListener(ISrsUdpHandler* h, int p);
|
||||
virtual ~SrsUdpListener();
|
||||
public:
|
||||
virtual int fd();
|
||||
public:
|
||||
virtual int listen();
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
};
|
||||
|
||||
/**
|
||||
* bind and listen tcp port, use handler to process the client.
|
||||
*/
|
||||
class SrsTcpListener : public ISrsThreadHandler
|
||||
{
|
||||
private:
|
||||
int _fd;
|
||||
st_netfd_t stfd;
|
||||
SrsThread* pthread;
|
||||
private:
|
||||
ISrsTcpHandler* handler;
|
||||
int port;
|
||||
public:
|
||||
SrsTcpListener(ISrsTcpHandler* h, int p);
|
||||
virtual ~SrsTcpListener();
|
||||
public:
|
||||
virtual int fd();
|
||||
public:
|
||||
virtual int listen();
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -49,14 +49,6 @@ using namespace std;
|
|||
#include <srs_rtmp_amf0.hpp>
|
||||
#include <srs_raw_avc.hpp>
|
||||
|
||||
ISrsUdpHandler::ISrsUdpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsUdpHandler::~ISrsUdpHandler()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpegtsQueue::SrsMpegtsQueue()
|
||||
{
|
||||
nb_audios = nb_videos = 0;
|
||||
|
|
|
@ -50,27 +50,7 @@ class SrsRawAacStreamCodec;
|
|||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
|
||||
/**
|
||||
* the udp packet handler.
|
||||
*/
|
||||
class ISrsUdpHandler
|
||||
{
|
||||
public:
|
||||
ISrsUdpHandler();
|
||||
virtual ~ISrsUdpHandler();
|
||||
public:
|
||||
/**
|
||||
* when udp listener got a udp packet, notice server to process it.
|
||||
* @param type, the client type, used to create concrete connection,
|
||||
* for instance RTMP connection to serve client.
|
||||
* @param from, the udp packet from address.
|
||||
* @param buf, the udp packet bytes, user should copy if need to use.
|
||||
* @param nb_buf, the size of udp packet bytes.
|
||||
* @remark user should never use the buf, for it's a shared memory bytes.
|
||||
*/
|
||||
virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) = 0;
|
||||
};
|
||||
#include <srs_app_listener.hpp>
|
||||
|
||||
/**
|
||||
* the queue for mpegts over udp to send packets.
|
||||
|
|
|
@ -44,9 +44,14 @@ ISrsRtspHandler::~ISrsRtspHandler()
|
|||
{
|
||||
}
|
||||
|
||||
SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o)
|
||||
SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax)
|
||||
{
|
||||
output = o;
|
||||
local_port_min = lpmin;
|
||||
local_port_max = lpmax;
|
||||
|
||||
session = "O9EaZ4bf"; // TODO: FIXME: generate session id.
|
||||
|
||||
caster = c;
|
||||
stfd = fd;
|
||||
skt = new SrsStSocket(fd);
|
||||
|
@ -97,12 +102,35 @@ int SrsRtspConn::do_cycle()
|
|||
return ret;
|
||||
}
|
||||
} else if (req->is_announce()) {
|
||||
srs_assert(req->sdp);
|
||||
sps = req->sdp->video_sps;
|
||||
pps = req->sdp->video_pps;
|
||||
asc = req->sdp->audio_sh;
|
||||
srs_trace("rtsp: video(#%s, %s), audio(#%s, %s, %sHZ %schannels)",
|
||||
req->sdp->video_stream_id.c_str(), req->sdp->video_codec.c_str(),
|
||||
req->sdp->audio_stream_id.c_str(), req->sdp->audio_codec.c_str(),
|
||||
req->sdp->audio_sample_rate.c_str(), req->sdp->audio_channel.c_str()
|
||||
);
|
||||
if ((ret = rtsp->send_message(new SrsRtspResponse(req->seq))) != ERROR_SUCCESS) {
|
||||
if (!srs_is_client_gracefully_close(ret)) {
|
||||
srs_error("rtsp: send ANNOUNCE response failed. ret=%d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} else if (req->is_setup()) {
|
||||
srs_assert(req->transport);
|
||||
SrsRtspSetupResponse* res = new SrsRtspSetupResponse(req->seq);
|
||||
res->client_port_min = req->transport->client_port_min;
|
||||
res->client_port_max = req->transport->client_port_max;
|
||||
res->local_port_min = local_port_min;
|
||||
res->local_port_max = local_port_max;
|
||||
res->session = session;
|
||||
if ((ret = rtsp->send_message(res)) != ERROR_SUCCESS) {
|
||||
if (!srs_is_client_gracefully_close(ret)) {
|
||||
srs_error("rtsp: send SETUP response failed. ret=%d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,6 +172,8 @@ SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
|
|||
{
|
||||
// TODO: FIXME: support reload.
|
||||
output = _srs_config->get_stream_caster_output(c);
|
||||
local_port_min = _srs_config->get_stream_caster_rtp_port_min(c);
|
||||
local_port_max = _srs_config->get_stream_caster_rtp_port_max(c);
|
||||
}
|
||||
|
||||
SrsRtspCaster::~SrsRtspCaster()
|
||||
|
@ -160,7 +190,11 @@ int SrsRtspCaster::serve_client(st_netfd_t stfd)
|
|||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsRtspConn* conn = new SrsRtspConn(this, stfd, output);
|
||||
SrsRtspConn* conn = new SrsRtspConn(
|
||||
this, stfd,
|
||||
output, local_port_min, local_port_max
|
||||
);
|
||||
|
||||
if ((ret = conn->serve()) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: serve client failed. ret=%d", ret);
|
||||
srs_freep(conn);
|
||||
|
|
|
@ -65,13 +65,23 @@ class SrsRtspConn : public ISrsThreadHandler
|
|||
{
|
||||
private:
|
||||
std::string output;
|
||||
int local_port_min;
|
||||
int local_port_max;
|
||||
private:
|
||||
std::string session;
|
||||
// video sequence header.
|
||||
std::string sps;
|
||||
std::string pps;
|
||||
// audio sequence header.
|
||||
std::string asc;
|
||||
private:
|
||||
st_netfd_t stfd;
|
||||
SrsStSocket* skt;
|
||||
SrsRtspStack* rtsp;
|
||||
SrsRtspCaster* caster;
|
||||
SrsThread* trd;
|
||||
public:
|
||||
SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o);
|
||||
SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax);
|
||||
virtual ~SrsRtspConn();
|
||||
public:
|
||||
virtual int serve();
|
||||
|
@ -90,6 +100,9 @@ class SrsRtspCaster : public ISrsRtspHandler
|
|||
{
|
||||
private:
|
||||
std::string output;
|
||||
int local_port_min;
|
||||
int local_port_max;
|
||||
private:
|
||||
std::vector<SrsRtspConn*> clients;
|
||||
public:
|
||||
SrsRtspCaster(SrsConfDirective* c);
|
||||
|
|
|
@ -24,8 +24,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_app_server.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -51,15 +49,6 @@ using namespace std;
|
|||
// signal defines.
|
||||
#define SIGNAL_RELOAD SIGHUP
|
||||
|
||||
// nginx also set to 512
|
||||
#define SERVER_LISTEN_BACKLOG 512
|
||||
|
||||
// sleep in ms for udp recv packet.
|
||||
#define SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS 0
|
||||
|
||||
// set the max packet size.
|
||||
#define SRS_UDP_MAX_PACKET_SIZE 65535
|
||||
|
||||
// system interval in ms,
|
||||
// all resolution times should be times togother,
|
||||
// for example, system-interval is x=1s(1000ms),
|
||||
|
@ -122,26 +111,13 @@ std::string __srs_listener_type2string(SrsListenerType type)
|
|||
|
||||
SrsListener::SrsListener(SrsServer* server, SrsListenerType type)
|
||||
{
|
||||
fd = -1;
|
||||
stfd = NULL;
|
||||
|
||||
_port = 0;
|
||||
_server = server;
|
||||
_type = type;
|
||||
|
||||
pthread = new SrsThread("listen", this, 0, true);
|
||||
}
|
||||
|
||||
SrsListener::~SrsListener()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
pthread->stop();
|
||||
srs_freep(pthread);
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(fd);
|
||||
}
|
||||
|
||||
SrsListenerType SrsListener::type()
|
||||
|
@ -149,92 +125,55 @@ SrsListenerType SrsListener::type()
|
|||
return _type;
|
||||
}
|
||||
|
||||
int SrsListener::listen(int port)
|
||||
SrsStreamListener::SrsStreamListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type)
|
||||
{
|
||||
listener = NULL;
|
||||
}
|
||||
|
||||
SrsStreamListener::~SrsStreamListener()
|
||||
{
|
||||
srs_freep(listener);
|
||||
}
|
||||
|
||||
int SrsStreamListener::listen(int port)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
_port = port;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
ret = ERROR_SOCKET_CREATE;
|
||||
srs_error("create linux socket error. port=%d, ret=%d", port, ret);
|
||||
|
||||
srs_freep(listener);
|
||||
listener = new SrsTcpListener(this, port);
|
||||
|
||||
if ((ret = listener->listen()) != ERROR_SUCCESS) {
|
||||
srs_error("tcp listen failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create linux socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
int reuse_socket = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||
ret = ERROR_SOCKET_SETREUSE;
|
||||
srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(_port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
ret = ERROR_SOCKET_BIND;
|
||||
srs_error("bind socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("bind socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
|
||||
ret = ERROR_SOCKET_LISTEN;
|
||||
srs_error("listen socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("listen socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
if ((stfd = st_netfd_open_socket(fd)) == NULL){
|
||||
ret = ERROR_ST_OPEN_SOCKET;
|
||||
srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("st open socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create st listen thread success, port=%d", port);
|
||||
|
||||
srs_info("listen thread cid=%d, current_cid=%d, "
|
||||
"listen at port=%d, type=%d, fd=%d started success, port=%d",
|
||||
pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
|
||||
|
||||
srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);
|
||||
|
||||
srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsListener::cycle()
|
||||
int SrsStreamListener::on_tcp_client(st_netfd_t stfd)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
||||
|
||||
if(client_stfd == NULL){
|
||||
// ignore error.
|
||||
srs_error("ignore accept thread stoppped for accept client error");
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
||||
|
||||
if ((ret = _server->accept_client(_type, client_stfd)) != ERROR_SUCCESS) {
|
||||
if ((ret = _server->accept_client(_type, stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef SRS_AUTO_STREAM_CASTER
|
||||
SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type)
|
||||
{
|
||||
_type = type;
|
||||
listener = NULL;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
|
@ -247,34 +186,52 @@ SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsCon
|
|||
SrsRtspListener::~SrsRtspListener()
|
||||
{
|
||||
srs_freep(caster);
|
||||
srs_freep(listener);
|
||||
}
|
||||
|
||||
int SrsRtspListener::cycle()
|
||||
int SrsRtspListener::listen(int port)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(_type == SrsListenerRtsp);
|
||||
|
||||
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
||||
|
||||
if(client_stfd == NULL){
|
||||
// ignore error.
|
||||
srs_error("ignore accept thread stoppped for accept client error");
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
||||
|
||||
if ((ret = caster->serve_client(client_stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
_port = port;
|
||||
|
||||
srs_freep(listener);
|
||||
listener = new SrsTcpListener(this, port);
|
||||
|
||||
if ((ret = listener->listen()) != ERROR_SUCCESS) {
|
||||
srs_error("udp caster listen failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_info("listen thread cid=%d, current_cid=%d, "
|
||||
"listen at port=%d, type=%d, fd=%d started success, port=%d",
|
||||
pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
|
||||
|
||||
srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type)
|
||||
int SrsRtspListener::on_tcp_client(st_netfd_t stfd)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = caster->serve_client(stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type)
|
||||
{
|
||||
_type = type;
|
||||
nb_buf = SRS_UDP_MAX_PACKET_SIZE;
|
||||
buf = new char[nb_buf];
|
||||
listener = NULL;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
|
@ -284,13 +241,13 @@ SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfD
|
|||
}
|
||||
}
|
||||
|
||||
SrsUdpListener::~SrsUdpListener()
|
||||
SrsUdpCasterListener::~SrsUdpCasterListener()
|
||||
{
|
||||
srs_freep(caster);
|
||||
srs_freep(buf);
|
||||
srs_freep(listener);
|
||||
}
|
||||
|
||||
int SrsUdpListener::listen(int port)
|
||||
int SrsUdpCasterListener::listen(int port)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
@ -299,83 +256,20 @@ int SrsUdpListener::listen(int port)
|
|||
srs_assert(_type == SrsListenerMpegTsOverUdp);
|
||||
|
||||
_port = port;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
ret = ERROR_SOCKET_CREATE;
|
||||
srs_error("create linux socket error. port=%d, ret=%d", port, ret);
|
||||
|
||||
srs_freep(listener);
|
||||
listener = new SrsUdpListener(caster, port);
|
||||
|
||||
if ((ret = listener->listen()) != ERROR_SUCCESS) {
|
||||
srs_error("udp caster listen failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create linux socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
int reuse_socket = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||
ret = ERROR_SOCKET_SETREUSE;
|
||||
srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(_port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
ret = ERROR_SOCKET_BIND;
|
||||
srs_error("bind socket error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("bind socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
if ((stfd = st_netfd_open_socket(fd)) == NULL){
|
||||
ret = ERROR_ST_OPEN_SOCKET;
|
||||
srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("st open socket success. port=%d, fd=%d", port, fd);
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("create st listen thread success, port=%d", port);
|
||||
|
||||
srs_info("listen thread cid=%d, current_cid=%d, "
|
||||
"listen at port=%d, type=%d, fd=%d started success, port=%d",
|
||||
pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
|
||||
|
||||
srs_trace("%s listen at udp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsUdpListener::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(_type == SrsListenerMpegTsOverUdp);
|
||||
|
||||
for (;;) {
|
||||
// TODO: FIXME: support ipv6, @see man 7 ipv6
|
||||
sockaddr_in from;
|
||||
int nb_from = sizeof(sockaddr_in);
|
||||
int nread = 0;
|
||||
|
||||
if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) {
|
||||
srs_warn("ignore recv udp packet failed, nread=%d", nread);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ret = caster->on_udp_packet(&from, buf, nread)) != ERROR_SUCCESS) {
|
||||
srs_warn("handle udp packet failed. ret=%d", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS > 0) {
|
||||
st_usleep(SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS * 1000);
|
||||
}
|
||||
}
|
||||
srs_trace("%s listen at udp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -992,7 +886,7 @@ int SrsServer::listen_rtmp()
|
|||
close_listeners(SrsListenerRtmpStream);
|
||||
|
||||
for (int i = 0; i < (int)ports.size(); i++) {
|
||||
SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream);
|
||||
SrsListener* listener = new SrsStreamListener(this, SrsListenerRtmpStream);
|
||||
listeners.push_back(listener);
|
||||
|
||||
int port = ::atoi(ports[i].c_str());
|
||||
|
@ -1012,7 +906,7 @@ int SrsServer::listen_http_api()
|
|||
#ifdef SRS_AUTO_HTTP_API
|
||||
close_listeners(SrsListenerHttpApi);
|
||||
if (_srs_config->get_http_api_enabled()) {
|
||||
SrsListener* listener = new SrsListener(this, SrsListenerHttpApi);
|
||||
SrsListener* listener = new SrsStreamListener(this, SrsListenerHttpApi);
|
||||
listeners.push_back(listener);
|
||||
|
||||
int port = _srs_config->get_http_api_listen();
|
||||
|
@ -1033,7 +927,7 @@ int SrsServer::listen_http_stream()
|
|||
#ifdef SRS_AUTO_HTTP_SERVER
|
||||
close_listeners(SrsListenerHttpStream);
|
||||
if (_srs_config->get_http_stream_enabled()) {
|
||||
SrsListener* listener = new SrsListener(this, SrsListenerHttpStream);
|
||||
SrsListener* listener = new SrsStreamListener(this, SrsListenerHttpStream);
|
||||
listeners.push_back(listener);
|
||||
|
||||
int port = _srs_config->get_http_stream_listen();
|
||||
|
@ -1067,7 +961,7 @@ int SrsServer::listen_stream_caster()
|
|||
|
||||
std::string caster = _srs_config->get_stream_caster_engine(stream_caster);
|
||||
if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) {
|
||||
listener = new SrsUdpListener(this, SrsListenerMpegTsOverUdp, stream_caster);
|
||||
listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster);
|
||||
} else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP) {
|
||||
listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster);
|
||||
} else {
|
||||
|
|
|
@ -35,9 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_reload.hpp>
|
||||
#include <srs_app_thread.hpp>
|
||||
#include <srs_app_source.hpp>
|
||||
#include <srs_app_hls.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
|
||||
class SrsServer;
|
||||
class SrsConnection;
|
||||
|
@ -49,6 +49,8 @@ class SrsKbps;
|
|||
class SrsConfDirective;
|
||||
class ISrsUdpHandler;
|
||||
class ISrsRtspHandler;
|
||||
class SrsUdpListener;
|
||||
class SrsTcpListener;
|
||||
|
||||
// listener type for server to identify the connection,
|
||||
// that is, use different type to process the connection.
|
||||
|
@ -69,60 +71,71 @@ enum SrsListenerType
|
|||
/**
|
||||
* the common tcp listener, for RTMP/HTTP server.
|
||||
*/
|
||||
class SrsListener : public ISrsThreadHandler
|
||||
class SrsListener
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
SrsListenerType _type;
|
||||
protected:
|
||||
int fd;
|
||||
st_netfd_t stfd;
|
||||
int _port;
|
||||
SrsServer* _server;
|
||||
SrsThread* pthread;
|
||||
public:
|
||||
SrsListener(SrsServer* server, SrsListenerType type);
|
||||
virtual ~SrsListener();
|
||||
public:
|
||||
virtual SrsListenerType type();
|
||||
virtual int listen(int port);
|
||||
// interface ISrsThreadHandler.
|
||||
virtual int listen(int port) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* tcp listener.
|
||||
*/
|
||||
class SrsStreamListener : virtual public SrsListener, virtual public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
SrsTcpListener* listener;
|
||||
public:
|
||||
virtual int cycle();
|
||||
SrsStreamListener(SrsServer* server, SrsListenerType type);
|
||||
virtual ~SrsStreamListener();
|
||||
public:
|
||||
virtual int listen(int port);
|
||||
// ISrsTcpHandler
|
||||
public:
|
||||
virtual int on_tcp_client(st_netfd_t stfd);
|
||||
};
|
||||
|
||||
#ifdef SRS_AUTO_STREAM_CASTER
|
||||
/**
|
||||
* the tcp listener, for rtsp server.
|
||||
*/
|
||||
class SrsRtspListener : public SrsListener
|
||||
class SrsRtspListener : virtual public SrsListener, virtual public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
SrsTcpListener* listener;
|
||||
private:
|
||||
ISrsRtspHandler* caster;
|
||||
public:
|
||||
SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
|
||||
virtual ~SrsRtspListener();
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
virtual int listen(int port);
|
||||
// ISrsTcpHandler
|
||||
public:
|
||||
virtual int on_tcp_client(st_netfd_t stfd);
|
||||
};
|
||||
|
||||
/**
|
||||
* the udp listener, for udp server.
|
||||
*/
|
||||
class SrsUdpListener : public SrsListener
|
||||
class SrsUdpCasterListener : public SrsListener
|
||||
{
|
||||
private:
|
||||
char* buf;
|
||||
int nb_buf;
|
||||
SrsUdpListener* listener;
|
||||
ISrsUdpHandler* caster;
|
||||
public:
|
||||
SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
|
||||
virtual ~SrsUdpListener();
|
||||
SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
|
||||
virtual ~SrsUdpCasterListener();
|
||||
public:
|
||||
virtual int listen(int port);
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue