diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 10feffc55..becd2c311 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -323,6 +323,12 @@ else echo "#undef SRS_AUTO_HTTP_SERVER" >> $SRS_AUTO_HEADERS_H fi +if [ $SRS_STREAM_CASTER = YES ]; then + echo "#define SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H +else + echo "#undef SRS_AUTO_STREAM_CASTER" >> $SRS_AUTO_HEADERS_H +fi + if [ $SRS_HTTP_API = YES ]; then echo "#define SRS_AUTO_HTTP_API" >> $SRS_AUTO_HEADERS_H else diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index dea0f89f3..adec4828a 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -25,6 +25,7 @@ SRS_INGEST=RESERVED SRS_STAT=RESERVED SRS_HTTP_CALLBACK=RESERVED SRS_HTTP_SERVER=RESERVED +SRS_STREAM_CASTER=RESERVED SRS_HTTP_API=RESERVED SRS_LIBRTMP=RESERVED SRS_RESEARCH=RESERVED @@ -114,6 +115,7 @@ Options: build nginx at: ./objs/nginx/sbin/nginx --with-http-callback enable http hooks, build cherrypy as demo api server. --with-http-server enable http server to delivery http stream. + --with-stream-caster enable stream caster to serve other stream over other protocol. --with-http-api enable http api, to manage SRS by http api. --with-ffmpeg enable transcoding tool ffmpeg. build ffmpeg at: ./objs/ffmpeg/bin/ffmpeg @@ -138,6 +140,7 @@ Options: --without-nginx disable delivery HTTP stream with nginx. --without-http-callback disable http, http hooks callback. --without-http-server disable http server, use external server to delivery http stream. + --without-stream-caster disable stream caster, only listen and serve RTMP/HTTP. --without-http-api disable http api, only use console to manage SRS process. --without-ffmpeg disable the ffmpeg transcode tool feature. --without-transcode disable the transcoding feature. @@ -213,6 +216,7 @@ function parse_user_option() { --with-stat) SRS_STAT=YES ;; --with-http-callback) SRS_HTTP_CALLBACK=YES ;; --with-http-server) SRS_HTTP_SERVER=YES ;; + --with-stream-caster) SRS_STREAM_CASTER=YES ;; --with-http-api) SRS_HTTP_API=YES ;; --with-librtmp) SRS_LIBRTMP=YES ;; --with-research) SRS_RESEARCH=YES ;; @@ -235,6 +239,7 @@ function parse_user_option() { --without-stat) SRS_STAT=NO ;; --without-http-callback) SRS_HTTP_CALLBACK=NO ;; --without-http-server) SRS_HTTP_SERVER=NO ;; + --without-stream-caster) SRS_STREAM_CASTER=NO ;; --without-http-api) SRS_HTTP_API=NO ;; --without-librtmp) SRS_LIBRTMP=NO ;; --without-research) SRS_RESEARCH=NO ;; @@ -362,6 +367,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=NO SRS_HTTP_CALLBACK=NO SRS_HTTP_SERVER=NO + SRS_STREAM_CASTER=NO SRS_HTTP_API=NO SRS_LIBRTMP=NO SRS_RESEARCH=NO @@ -387,6 +393,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=YES @@ -412,6 +419,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=NO SRS_HTTP_CALLBACK=NO SRS_HTTP_SERVER=NO + SRS_STREAM_CASTER=NO SRS_HTTP_API=NO SRS_LIBRTMP=NO SRS_RESEARCH=NO @@ -437,6 +445,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=NO SRS_HTTP_CALLBACK=NO SRS_HTTP_SERVER=NO + SRS_STREAM_CASTER=NO SRS_HTTP_API=NO SRS_LIBRTMP=NO SRS_RESEARCH=NO @@ -462,6 +471,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=NO SRS_HTTP_CALLBACK=NO SRS_HTTP_SERVER=NO + SRS_STREAM_CASTER=NO SRS_HTTP_API=NO SRS_LIBRTMP=NO SRS_RESEARCH=NO @@ -487,6 +497,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -513,6 +524,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -538,6 +550,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -563,6 +576,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=YES @@ -588,6 +602,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=NO SRS_RESEARCH=NO @@ -613,6 +628,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -638,6 +654,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -663,6 +680,7 @@ function apply_user_presets() { SRS_HTTP_PARSER=YES SRS_HTTP_CALLBACK=YES SRS_HTTP_SERVER=YES + SRS_STREAM_CASTER=YES SRS_HTTP_API=YES SRS_LIBRTMP=YES SRS_RESEARCH=NO @@ -723,6 +741,7 @@ function apply_user_detail_options() { SRS_HTTP_PARSER=NO SRS_HTTP_CALLBACK=NO SRS_HTTP_SERVER=NO + SRS_STREAM_CASTER=NO SRS_HTTP_API=NO SRS_LIBRTMP=YES SRS_RESEARCH=YES @@ -752,6 +771,7 @@ function regenerate_options() { if [ $SRS_STAT = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-stat"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-stat"; fi if [ $SRS_HTTP_CALLBACK = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-callback"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-callback"; fi if [ $SRS_HTTP_SERVER = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-server"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-server"; fi + if [ $SRS_STREAM_CASTER = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-stream-caster"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-stream-caster"; fi if [ $SRS_HTTP_API = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-http-api"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-http-api"; fi if [ $SRS_LIBRTMP = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-librtmp"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-librtmp"; fi if [ $SRS_RESEARCH = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --with-research"; else SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --without-research"; fi @@ -828,6 +848,7 @@ function check_option_conflicts() { if [ $SRS_FFMPEG_TOOL = RESERVED ]; then echo "you must specifies the ffmpeg, see: ./configure --help"; __check_ok=NO; fi if [ $SRS_HTTP_CALLBACK = RESERVED ]; then echo "you must specifies the http-callback, see: ./configure --help"; __check_ok=NO; fi if [ $SRS_HTTP_SERVER = RESERVED ]; then echo "you must specifies the http-server, see: ./configure --help"; __check_ok=NO; fi + if [ $SRS_STREAM_CASTER = RESERVED ]; then echo "you must specifies the stream-caster, see: ./configure --help"; __check_ok=NO; fi if [ $SRS_HTTP_API = RESERVED ]; then echo "you must specifies the http-api, see: ./configure --help"; __check_ok=NO; fi if [ $SRS_LIBRTMP = RESERVED ]; then echo "you must specifies the librtmp, see: ./configure --help"; __check_ok=NO; fi if [ $SRS_RESEARCH = RESERVED ]; then echo "you must specifies the research, see: ./configure --help"; __check_ok=NO; fi diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index deae4fd71..a0730b65c 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -142,6 +142,16 @@ stream_caster { # whether stream caster is enabled. # default: off enabled on; + # the caster type of stream, the casters: + # mpegts_over_udp, MPEG-TS over UDP caster. + caster mpegts_over_udp; + # the output rtmp url. + # for example, rtmp://127.0.0.1/live/livestream. + output rtmp://127.0.0.1/live/livestream; + # the listen port for stream caster. + # for caster: + # mpegts_over_udp, listen at udp port. + listen 1935; } ############################################################################################# diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index b1eb64ed7..f15cd4ea3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -140,6 +140,11 @@ bool SrsConfDirective::is_vhost() return name == "vhost"; } +bool SrsConfDirective::is_stream_caster() +{ + return name == "stream_caster"; +} + int SrsConfDirective::parse(SrsConfigBuffer* buffer) { return parse_conf(buffer, parse_file); @@ -519,6 +524,8 @@ int SrsConfig::reload_conf(SrsConfig* conf) return ret; } + // TODO: FIXME: support reload stream_caster. + // merge config: vhost if ((ret = reload_vhost(old_root)) != ERROR_SUCCESS) { return ret; @@ -1295,6 +1302,7 @@ int SrsConfig::check_config() srs_trace("srs checking config..."); vector vhosts = get_vhosts(); + vector stream_casters = get_stream_casters(); //////////////////////////////////////////////////////////////////////// // check empty @@ -1315,7 +1323,7 @@ int SrsConfig::check_config() && n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file" && n != "max_connections" && n != "daemon" && n != "heartbeat" && n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print" - && n != "http_stream" && n != "http_server") + && n != "http_stream" && n != "http_server" && n != "stream_caster") { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported directive %s, ret=%d", n.c_str(), ret); @@ -1381,6 +1389,20 @@ int SrsConfig::check_config() } } } + for (int n = 0; n < (int)stream_casters.size(); n++) { + SrsConfDirective* stream_caster = stream_casters[n]; + for (int i = 0; stream_caster && i < (int)stream_caster->directives.size(); i++) { + SrsConfDirective* conf = stream_caster->at(i); + string n = conf->name; + if (n != "enabled" && n != "caster" && n != "output" + && n != "listen" + ) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret); + return ret; + } + } + } for (int n = 0; n < (int)vhosts.size(); n++) { SrsConfDirective* vhost = vhosts[n]; for (int i = 0; vhost && i < (int)vhost->directives.size(); i++) { @@ -1969,6 +1991,77 @@ int SrsConfig::get_pithy_print_edge() return ::atoi(pithy->arg0().c_str()); } +vector SrsConfig::get_stream_casters() +{ + srs_assert(root); + + std::vector stream_casters; + + for (int i = 0; i < (int)root->directives.size(); i++) { + SrsConfDirective* conf = root->at(i); + + if (!conf->is_stream_caster()) { + continue; + } + + stream_casters.push_back(conf); + } + + return stream_casters; +} + +bool SrsConfig::get_stream_caster_enabled(SrsConfDirective* sc) +{ + srs_assert(sc); + + SrsConfDirective* conf = sc->get("enabled"); + if (!conf) { + return SRS_CONF_DEFAULT_STREAM_CASTER_ENABLED; + } + + if (conf->arg0() != "on") { + return false; + } + + return true; +} + +string SrsConfig::get_stream_caster_engine(SrsConfDirective* sc) +{ + srs_assert(sc); + + SrsConfDirective* conf = sc->get("caster"); + if (!conf) { + return ""; + } + + return conf->arg0(); +} + +string SrsConfig::get_stream_caster_output(SrsConfDirective* sc) +{ + srs_assert(sc); + + SrsConfDirective* conf = sc->get("output"); + if (!conf) { + return ""; + } + + return conf->arg0(); +} + +int SrsConfig::get_stream_caster_listen(SrsConfDirective* sc) +{ + srs_assert(sc); + + SrsConfDirective* conf = sc->get("listen"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); +} + SrsConfDirective* SrsConfig::get_vhost(string vhost) { srs_assert(root); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 2111a9dba..eb3a29707 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -80,6 +80,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_SECURITY_ENABLED false +#define SRS_CONF_DEFAULT_STREAM_CASTER_ENABLED false +#define SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP "mpegts_over_udp" + #define SRS_CONF_DEFAULT_STATS_NETWORK_DEVICE_INDEX 0 #define SRS_CONF_DEFAULT_STAGE_PLAY_USER_INTERVAL_MS 10000 @@ -188,6 +191,10 @@ public: * whether current directive is vhost. */ virtual bool is_vhost(); + /** + * whether current directive is stream_caster. + */ + virtual bool is_stream_caster(); // parse utilities public: /** @@ -446,6 +453,28 @@ public: * the edge will get stream from upnode. */ virtual int get_pithy_print_edge(); +// stream_caster section +public: + /** + * get all stream_caster in config file. + */ + virtual std::vector get_stream_casters(); + /** + * get whether the specified stream_caster is enabled. + */ + virtual bool get_stream_caster_enabled(SrsConfDirective* sc); + /** + * get the engine of stream_caster, the caster config. + */ + virtual std::string get_stream_caster_engine(SrsConfDirective* sc); + /** + * get the output rtmp url of stream_caster, the output config. + */ + virtual std::string get_stream_caster_output(SrsConfDirective* sc); + /** + * get the listen port of stream caster. + */ + virtual int get_stream_caster_listen(SrsConfDirective* sc); // vhost specified section public: /** diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 193d613dc..515ee9bc7 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -93,6 +93,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // SRS_SYS_CYCLE_INTERVAL * SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES #define SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES 9 +std::string __srs_listener_type2string(SrsListenerType type) +{ + switch (type) { + case SrsListenerRtmpStream: + return "RTMP"; + case SrsListenerHttpApi: + return "HTTP-API"; + case SrsListenerHttpStream: + return "HTTP-Server"; + case SrsListenerMpegTsOverUdp: + return "MPEG-TS over UDP"; + default: + return "UNKONWN"; + } +} + SrsListener::SrsListener(SrsServer* server, SrsListenerType type) { fd = -1; @@ -174,18 +190,15 @@ int SrsListener::listen(int port) } srs_verbose("create st listen thread success, port=%d", port); - srs_trace("listen thread cid=%d, current_cid=%d, " + 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); return ret; } -void SrsListener::on_thread_start() -{ - srs_trace("listen cycle start, port=%d, type=%d, fd=%d", _port, _type, fd); -} - int SrsListener::cycle() { int ret = ERROR_SUCCESS; @@ -207,6 +220,86 @@ int SrsListener::cycle() return ret; } +SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type) +{ +} + +SrsUdpListener::~SrsUdpListener() +{ +} + +int SrsUdpListener::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 == 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); + 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); + + // TODO: FIXME: recv udp packet. + st_sleep(1); + + return ret; +} + SrsSignalManager* SrsSignalManager::instance = NULL; SrsSignalManager::SrsSignalManager(SrsServer* server) @@ -608,6 +701,10 @@ int SrsServer::listen() return ret; } + if ((ret = listen_stream_caster()) != ERROR_SUCCESS) { + return ret; + } + return ret; } @@ -869,6 +966,53 @@ int SrsServer::listen_http_stream() return ret; } +int SrsServer::listen_stream_caster() +{ + int ret = ERROR_SUCCESS; + +#ifdef SRS_AUTO_STREAM_CASTER + close_listeners(SrsListenerMpegTsOverUdp); + + std::vector::iterator it; + std::vector stream_casters = _srs_config->get_stream_casters(); + + for (it = stream_casters.begin(); it != stream_casters.end(); ++it) { + SrsConfDirective* stream_caster = *it; + if (!_srs_config->get_stream_caster_enabled(stream_caster)) { + continue; + } + + SrsUdpListener* listener = NULL; + + 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); + } else { + ret = ERROR_STREAM_CASTER_ENGINE; + srs_error("unsupported stream caster %s. ret=%d", caster.c_str(), ret); + return ret; + } + srs_assert(listener != NULL); + + listeners.push_back(listener); + + int port = _srs_config->get_stream_caster_listen(stream_caster); + if (port <= 0) { + ret = ERROR_STREAM_CASTER_PORT; + srs_error("invalid stream caster port %d. ret=%d", port, ret); + return ret; + } + + if ((ret = listener->listen(port)) != ERROR_SUCCESS) { + srs_error("StreamCaster listen at port %d failed. ret=%d", port, ret); + return ret; + } + } +#endif + + return ret; +} + void SrsServer::close_listeners(SrsListenerType type) { std::vector::iterator it; diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index d99426de6..5333ad461 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -50,18 +50,23 @@ class SrsKbps; enum SrsListenerType { // RTMP client, - SrsListenerRtmpStream = 0, + SrsListenerRtmpStream = 0, // HTTP api, - SrsListenerHttpApi = 1, + SrsListenerHttpApi = 1, // HTTP stream, HDS/HLS/DASH - SrsListenerHttpStream = 2 + SrsListenerHttpStream = 2, + // UDP stream, MPEG-TS over udp. + SrsListenerMpegTsOverUdp = 3, }; +/** +* the common tcp listener, for RTMP/HTTP server. +*/ class SrsListener : public ISrsThreadHandler { public: SrsListenerType _type; -private: +protected: int fd; st_netfd_t stfd; int _port; @@ -75,7 +80,21 @@ public: virtual int listen(int port); // interface ISrsThreadHandler. public: - virtual void on_thread_start(); + virtual int cycle(); +}; + +/** +* the udp listener, for udp server. +*/ +class SrsUdpListener : public SrsListener +{ +public: + SrsUdpListener(SrsServer* server, SrsListenerType type); + virtual ~SrsUdpListener(); +public: + virtual int listen(int port); +// interface ISrsThreadHandler. +public: virtual int cycle(); }; @@ -211,6 +230,7 @@ private: virtual int listen_rtmp(); virtual int listen_http_api(); virtual int listen_http_stream(); + virtual int listen_stream_caster(); /** * close the listeners for specified type, * remove the listen object from manager. diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 43e286697..9303ba429 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -204,7 +204,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_AAC_DATA_INVALID 3048 /////////////////////////////////////////////////////// -// HTTP protocol error. +// HTTP/StreamCaster protocol error. /////////////////////////////////////////////////////// #define ERROR_HTTP_PATTERN_EMPTY 4000 #define ERROR_HTTP_PATTERN_DUPLICATED 4001 @@ -216,6 +216,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_AAC_DECODE_ERROR 4007 #define ERROR_KERNEL_MP3_STREAM_CLOSED 4008 #define ERROR_MP3_DECODE_ERROR 4009 +#define ERROR_STREAM_CASTER_ENGINE 4010 +#define ERROR_STREAM_CASTER_PORT 4011 /** * whether the error code is an system control error.