winlin

for #133, rtsp extract tcp/udp listener.

@@ -160,6 +160,11 @@ stream_caster { @@ -160,6 +160,11 @@ stream_caster {
160 # for mpegts_over_udp caster, listen at udp port. for example, 8935. 160 # for mpegts_over_udp caster, listen at udp port. for example, 8935.
161 # for rtsp caster, listen at tcp port. for example, 554. 161 # for rtsp caster, listen at tcp port. for example, 554.
162 listen 8935; 162 listen 8935;
  163 + # for the rtsp caster, the rtp server local port over udp,
  164 + # which reply the rtsp setup request message, the port will be used:
  165 + # [rtp_port_min, rtp_port_max)
  166 + rtp_port_min 57200;
  167 + rtp_port_max 57300;
163 } 168 }
164 stream_caster { 169 stream_caster {
165 enabled off; 170 enabled off;
@@ -392,7 +392,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then @@ -392,7 +392,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
392 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" 392 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
393 "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" 393 "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client"
394 "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" 394 "srs_app_recv_thread" "srs_app_security" "srs_app_statistic"
395 - "srs_app_mpegts_udp" "srs_app_rtsp") 395 + "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener")
396 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh 396 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
397 APP_OBJS="${MODULE_OBJS[@]}" 397 APP_OBJS="${MODULE_OBJS[@]}"
398 fi 398 fi
@@ -102,6 +102,8 @@ file @@ -102,6 +102,8 @@ file
102 ../../src/app/srs_app_json.cpp, 102 ../../src/app/srs_app_json.cpp,
103 ../../src/app/srs_app_kbps.hpp, 103 ../../src/app/srs_app_kbps.hpp,
104 ../../src/app/srs_app_kbps.cpp, 104 ../../src/app/srs_app_kbps.cpp,
  105 + ../../src/app/srs_app_listener.hpp,
  106 + ../../src/app/srs_app_listener.cpp,
105 ../../src/app/srs_app_log.hpp, 107 ../../src/app/srs_app_log.hpp,
106 ../../src/app/srs_app_log.cpp, 108 ../../src/app/srs_app_log.cpp,
107 ../../src/app/srs_app_mpegts_udp.hpp, 109 ../../src/app/srs_app_mpegts_udp.hpp,
@@ -82,6 +82,7 @@ @@ -82,6 +82,7 @@
82 <ClInclude Include="..\..\src\app\srs_app_ingest.hpp" /> 82 <ClInclude Include="..\..\src\app\srs_app_ingest.hpp" />
83 <ClInclude Include="..\..\src\app\srs_app_json.hpp" /> 83 <ClInclude Include="..\..\src\app\srs_app_json.hpp" />
84 <ClInclude Include="..\..\src\app\srs_app_kbps.hpp" /> 84 <ClInclude Include="..\..\src\app\srs_app_kbps.hpp" />
  85 + <ClInclude Include="..\..\src\app\srs_app_listener.hpp" />
85 <ClInclude Include="..\..\src\app\srs_app_log.hpp" /> 86 <ClInclude Include="..\..\src\app\srs_app_log.hpp" />
86 <ClInclude Include="..\..\src\app\srs_app_mpegts_udp.hpp" /> 87 <ClInclude Include="..\..\src\app\srs_app_mpegts_udp.hpp" />
87 <ClInclude Include="..\..\src\app\srs_app_pithy_print.hpp" /> 88 <ClInclude Include="..\..\src\app\srs_app_pithy_print.hpp" />
@@ -161,6 +162,7 @@ @@ -161,6 +162,7 @@
161 <ClCompile Include="..\..\src\app\srs_app_ingest.cpp" /> 162 <ClCompile Include="..\..\src\app\srs_app_ingest.cpp" />
162 <ClCompile Include="..\..\src\app\srs_app_json.cpp" /> 163 <ClCompile Include="..\..\src\app\srs_app_json.cpp" />
163 <ClCompile Include="..\..\src\app\srs_app_kbps.cpp" /> 164 <ClCompile Include="..\..\src\app\srs_app_kbps.cpp" />
  165 + <ClCompile Include="..\..\src\app\srs_app_listener.cpp" />
164 <ClCompile Include="..\..\src\app\srs_app_log.cpp" /> 166 <ClCompile Include="..\..\src\app\srs_app_log.cpp" />
165 <ClCompile Include="..\..\src\app\srs_app_mpegts_udp.cpp" /> 167 <ClCompile Include="..\..\src\app\srs_app_mpegts_udp.cpp" />
166 <ClCompile Include="..\..\src\app\srs_app_pithy_print.cpp" /> 168 <ClCompile Include="..\..\src\app\srs_app_pithy_print.cpp" />
@@ -235,6 +235,9 @@ @@ -235,6 +235,9 @@
235 <ClCompile Include="..\..\src\protocol\srs_rtsp_stack.cpp"> 235 <ClCompile Include="..\..\src\protocol\srs_rtsp_stack.cpp">
236 <Filter>srs</Filter> 236 <Filter>srs</Filter>
237 </ClCompile> 237 </ClCompile>
  238 + <ClCompile Include="..\..\src\app\srs_app_listener.cpp">
  239 + <Filter>srs</Filter>
  240 + </ClCompile>
238 </ItemGroup> 241 </ItemGroup>
239 <ItemGroup> 242 <ItemGroup>
240 <ClInclude Include="..\..\src\app\srs_app_bandwidth.hpp"> 243 <ClInclude Include="..\..\src\app\srs_app_bandwidth.hpp">
@@ -432,6 +435,9 @@ @@ -432,6 +435,9 @@
432 <ClInclude Include="..\..\src\protocol\srs_rtsp_stack.hpp"> 435 <ClInclude Include="..\..\src\protocol\srs_rtsp_stack.hpp">
433 <Filter>srs</Filter> 436 <Filter>srs</Filter>
434 </ClInclude> 437 </ClInclude>
  438 + <ClInclude Include="..\..\src\app\srs_app_listener.hpp">
  439 + <Filter>srs</Filter>
  440 + </ClInclude>
435 </ItemGroup> 441 </ItemGroup>
436 <ItemGroup> 442 <ItemGroup>
437 <Filter Include="research"> 443 <Filter Include="research">
@@ -1395,7 +1395,7 @@ int SrsConfig::check_config() @@ -1395,7 +1395,7 @@ int SrsConfig::check_config()
1395 SrsConfDirective* conf = stream_caster->at(i); 1395 SrsConfDirective* conf = stream_caster->at(i);
1396 string n = conf->name; 1396 string n = conf->name;
1397 if (n != "enabled" && n != "caster" && n != "output" 1397 if (n != "enabled" && n != "caster" && n != "output"
1398 - && n != "listen" 1398 + && n != "listen" && n != "rtp_port_min" && n != "rtp_port_max"
1399 ) { 1399 ) {
1400 ret = ERROR_SYSTEM_CONFIG_INVALID; 1400 ret = ERROR_SYSTEM_CONFIG_INVALID;
1401 srs_error("unsupported stream_caster directive %s, ret=%d", n.c_str(), ret); 1401 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) @@ -2065,6 +2065,30 @@ int SrsConfig::get_stream_caster_listen(SrsConfDirective* sc)
2065 return ::atoi(conf->arg0().c_str()); 2065 return ::atoi(conf->arg0().c_str());
2066 } 2066 }
2067 2067
  2068 +int SrsConfig::get_stream_caster_rtp_port_min(SrsConfDirective* sc)
  2069 +{
  2070 + srs_assert(sc);
  2071 +
  2072 + SrsConfDirective* conf = sc->get("rtp_port_min");
  2073 + if (!conf) {
  2074 + return 0;
  2075 + }
  2076 +
  2077 + return ::atoi(conf->arg0().c_str());
  2078 +}
  2079 +
  2080 +int SrsConfig::get_stream_caster_rtp_port_max(SrsConfDirective* sc)
  2081 +{
  2082 + srs_assert(sc);
  2083 +
  2084 + SrsConfDirective* conf = sc->get("rtp_port_max");
  2085 + if (!conf) {
  2086 + return 0;
  2087 + }
  2088 +
  2089 + return ::atoi(conf->arg0().c_str());
  2090 +}
  2091 +
2068 SrsConfDirective* SrsConfig::get_vhost(string vhost) 2092 SrsConfDirective* SrsConfig::get_vhost(string vhost)
2069 { 2093 {
2070 srs_assert(root); 2094 srs_assert(root);
@@ -481,6 +481,14 @@ public: @@ -481,6 +481,14 @@ public:
481 * get the listen port of stream caster. 481 * get the listen port of stream caster.
482 */ 482 */
483 virtual int get_stream_caster_listen(SrsConfDirective* sc); 483 virtual int get_stream_caster_listen(SrsConfDirective* sc);
  484 + /**
  485 + * get the min udp port for rtp of stream caster rtsp.
  486 + */
  487 + virtual int get_stream_caster_rtp_port_min(SrsConfDirective* sc);
  488 + /**
  489 + * get the max udp port for rtp of stream caster rtsp.
  490 + */
  491 + virtual int get_stream_caster_rtp_port_max(SrsConfDirective* sc);
484 // vhost specified section 492 // vhost specified section
485 public: 493 public:
486 /** 494 /**
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_listener.hpp>
  25 +
  26 +#include <sys/types.h>
  27 +#include <sys/socket.h>
  28 +#include <arpa/inet.h>
  29 +#include <signal.h>
  30 +#include <sys/types.h>
  31 +#include <sys/stat.h>
  32 +#include <fcntl.h>
  33 +
  34 +#include <srs_kernel_log.hpp>
  35 +#include <srs_kernel_error.hpp>
  36 +#include <srs_app_server.hpp>
  37 +#include <srs_app_utility.hpp>
  38 +
  39 +// set the max packet size.
  40 +#define SRS_UDP_MAX_PACKET_SIZE 65535
  41 +
  42 +// sleep in ms for udp recv packet.
  43 +#define SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS 0
  44 +
  45 +// nginx also set to 512
  46 +#define SERVER_LISTEN_BACKLOG 512
  47 +
  48 +ISrsUdpHandler::ISrsUdpHandler()
  49 +{
  50 +}
  51 +
  52 +ISrsUdpHandler::~ISrsUdpHandler()
  53 +{
  54 +}
  55 +
  56 +ISrsTcpHandler::ISrsTcpHandler()
  57 +{
  58 +}
  59 +
  60 +ISrsTcpHandler::~ISrsTcpHandler()
  61 +{
  62 +}
  63 +
  64 +SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, int p)
  65 +{
  66 + handler = h;
  67 + port = p;
  68 +
  69 + _fd = -1;
  70 + stfd = NULL;
  71 +
  72 + nb_buf = SRS_UDP_MAX_PACKET_SIZE;
  73 + buf = new char[nb_buf];
  74 +
  75 + pthread = new SrsThread("udp", this, 0, true);
  76 +}
  77 +
  78 +SrsUdpListener::~SrsUdpListener()
  79 +{
  80 + srs_close_stfd(stfd);
  81 +
  82 + pthread->stop();
  83 + srs_freep(pthread);
  84 +
  85 + // st does not close it sometimes,
  86 + // close it manually.
  87 + close(_fd);
  88 +
  89 + srs_freep(buf);
  90 +}
  91 +
  92 +int SrsUdpListener::fd()
  93 +{
  94 + return _fd;
  95 +}
  96 +
  97 +int SrsUdpListener::listen()
  98 +{
  99 + int ret = ERROR_SUCCESS;
  100 +
  101 + if ((_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  102 + ret = ERROR_SOCKET_CREATE;
  103 + srs_error("create linux socket error. port=%d, ret=%d", port, ret);
  104 + return ret;
  105 + }
  106 + srs_verbose("create linux socket success. port=%d, fd=%d", port, _fd);
  107 +
  108 + int reuse_socket = 1;
  109 + if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
  110 + ret = ERROR_SOCKET_SETREUSE;
  111 + srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
  112 + return ret;
  113 + }
  114 + srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, _fd);
  115 +
  116 + sockaddr_in addr;
  117 + addr.sin_family = AF_INET;
  118 + addr.sin_port = htons(port);
  119 + addr.sin_addr.s_addr = INADDR_ANY;
  120 + if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
  121 + ret = ERROR_SOCKET_BIND;
  122 + srs_error("bind socket error. port=%d, ret=%d", port, ret);
  123 + return ret;
  124 + }
  125 + srs_verbose("bind socket success. port=%d, fd=%d", port, _fd);
  126 +
  127 + if ((stfd = st_netfd_open_socket(_fd)) == NULL){
  128 + ret = ERROR_ST_OPEN_SOCKET;
  129 + srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
  130 + return ret;
  131 + }
  132 + srs_verbose("st open socket success. port=%d, fd=%d", port, _fd);
  133 +
  134 + if ((ret = pthread->start()) != ERROR_SUCCESS) {
  135 + srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
  136 + return ret;
  137 + }
  138 + srs_verbose("create st listen thread success, port=%d", port);
  139 +
  140 + return ret;
  141 +}
  142 +
  143 +int SrsUdpListener::cycle()
  144 +{
  145 + int ret = ERROR_SUCCESS;
  146 +
  147 + for (;;) {
  148 + // TODO: FIXME: support ipv6, @see man 7 ipv6
  149 + sockaddr_in from;
  150 + int nb_from = sizeof(sockaddr_in);
  151 + int nread = 0;
  152 +
  153 + if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) {
  154 + srs_warn("ignore recv udp packet failed, nread=%d", nread);
  155 + continue;
  156 + }
  157 +
  158 + if ((ret = handler->on_udp_packet(&from, buf, nread)) != ERROR_SUCCESS) {
  159 + srs_warn("handle udp packet failed. ret=%d", ret);
  160 + continue;
  161 + }
  162 +
  163 + if (SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS > 0) {
  164 + st_usleep(SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS * 1000);
  165 + }
  166 + }
  167 +
  168 + return ret;
  169 +}
  170 +
  171 +SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, int p)
  172 +{
  173 + handler = h;
  174 + port = p;
  175 +
  176 + _fd = -1;
  177 + stfd = NULL;
  178 +
  179 + pthread = new SrsThread("tcp", this, 0, true);
  180 +}
  181 +
  182 +SrsTcpListener::~SrsTcpListener()
  183 +{
  184 + srs_close_stfd(stfd);
  185 +
  186 + pthread->stop();
  187 + srs_freep(pthread);
  188 +
  189 + // st does not close it sometimes,
  190 + // close it manually.
  191 + close(_fd);
  192 +}
  193 +
  194 +int SrsTcpListener::fd()
  195 +{
  196 + return _fd;
  197 +}
  198 +
  199 +int SrsTcpListener::listen()
  200 +{
  201 + int ret = ERROR_SUCCESS;
  202 +
  203 + if ((_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  204 + ret = ERROR_SOCKET_CREATE;
  205 + srs_error("create linux socket error. port=%d, ret=%d", port, ret);
  206 + return ret;
  207 + }
  208 + srs_verbose("create linux socket success. port=%d, fd=%d", port, _fd);
  209 +
  210 + int reuse_socket = 1;
  211 + if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
  212 + ret = ERROR_SOCKET_SETREUSE;
  213 + srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
  214 + return ret;
  215 + }
  216 + srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, _fd);
  217 +
  218 + sockaddr_in addr;
  219 + addr.sin_family = AF_INET;
  220 + addr.sin_port = htons(port);
  221 + addr.sin_addr.s_addr = INADDR_ANY;
  222 + if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
  223 + ret = ERROR_SOCKET_BIND;
  224 + srs_error("bind socket error. port=%d, ret=%d", port, ret);
  225 + return ret;
  226 + }
  227 + srs_verbose("bind socket success. port=%d, fd=%d", port, _fd);
  228 +
  229 + if (::listen(_fd, SERVER_LISTEN_BACKLOG) == -1) {
  230 + ret = ERROR_SOCKET_LISTEN;
  231 + srs_error("listen socket error. port=%d, ret=%d", port, ret);
  232 + return ret;
  233 + }
  234 + srs_verbose("listen socket success. port=%d, fd=%d", port, _fd);
  235 +
  236 + if ((stfd = st_netfd_open_socket(_fd)) == NULL){
  237 + ret = ERROR_ST_OPEN_SOCKET;
  238 + srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);
  239 + return ret;
  240 + }
  241 + srs_verbose("st open socket success. port=%d, fd=%d", port, _fd);
  242 +
  243 + if ((ret = pthread->start()) != ERROR_SUCCESS) {
  244 + srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret);
  245 + return ret;
  246 + }
  247 + srs_verbose("create st listen thread success, port=%d", port);
  248 +
  249 + return ret;
  250 +}
  251 +
  252 +int SrsTcpListener::cycle()
  253 +{
  254 + int ret = ERROR_SUCCESS;
  255 +
  256 + st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
  257 +
  258 + if(client_stfd == NULL){
  259 + // ignore error.
  260 + srs_error("ignore accept thread stoppped for accept client error");
  261 + return ret;
  262 + }
  263 + srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
  264 +
  265 + if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS) {
  266 + srs_warn("accept client error. ret=%d", ret);
  267 + return ret;
  268 + }
  269 +
  270 + return ret;
  271 +}
  272 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_APP_LISTENER_HPP
  25 +#define SRS_APP_LISTENER_HPP
  26 +
  27 +/*
  28 +#include <srs_app_listener.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <srs_app_st.hpp>
  34 +#include <srs_app_thread.hpp>
  35 +
  36 +class sockaddr_in;
  37 +
  38 +/**
  39 +* the udp packet handler.
  40 +*/
  41 +class ISrsUdpHandler
  42 +{
  43 +public:
  44 + ISrsUdpHandler();
  45 + virtual ~ISrsUdpHandler();
  46 +public:
  47 + /**
  48 + * when udp listener got a udp packet, notice server to process it.
  49 + * @param type, the client type, used to create concrete connection,
  50 + * for instance RTMP connection to serve client.
  51 + * @param from, the udp packet from address.
  52 + * @param buf, the udp packet bytes, user should copy if need to use.
  53 + * @param nb_buf, the size of udp packet bytes.
  54 + * @remark user should never use the buf, for it's a shared memory bytes.
  55 + */
  56 + virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) = 0;
  57 +};
  58 +
  59 +/**
  60 +* the tcp connection handler.
  61 +*/
  62 +class ISrsTcpHandler
  63 +{
  64 +public:
  65 + ISrsTcpHandler();
  66 + virtual ~ISrsTcpHandler();
  67 +public:
  68 + /**
  69 + * when got tcp client.
  70 + */
  71 + virtual int on_tcp_client(st_netfd_t stfd) = 0;
  72 +};
  73 +
  74 +/**
  75 +* bind udp port, start thread to recv packet and handler it.
  76 +*/
  77 +class SrsUdpListener : public ISrsThreadHandler
  78 +{
  79 +private:
  80 + int _fd;
  81 + st_netfd_t stfd;
  82 + SrsThread* pthread;
  83 +private:
  84 + char* buf;
  85 + int nb_buf;
  86 +private:
  87 + ISrsUdpHandler* handler;
  88 + int port;
  89 +public:
  90 + SrsUdpListener(ISrsUdpHandler* h, int p);
  91 + virtual ~SrsUdpListener();
  92 +public:
  93 + virtual int fd();
  94 +public:
  95 + virtual int listen();
  96 +// interface ISrsThreadHandler.
  97 +public:
  98 + virtual int cycle();
  99 +};
  100 +
  101 +/**
  102 +* bind and listen tcp port, use handler to process the client.
  103 +*/
  104 +class SrsTcpListener : public ISrsThreadHandler
  105 +{
  106 +private:
  107 + int _fd;
  108 + st_netfd_t stfd;
  109 + SrsThread* pthread;
  110 +private:
  111 + ISrsTcpHandler* handler;
  112 + int port;
  113 +public:
  114 + SrsTcpListener(ISrsTcpHandler* h, int p);
  115 + virtual ~SrsTcpListener();
  116 +public:
  117 + virtual int fd();
  118 +public:
  119 + virtual int listen();
  120 +// interface ISrsThreadHandler.
  121 +public:
  122 + virtual int cycle();
  123 +};
  124 +
  125 +#endif
@@ -49,14 +49,6 @@ using namespace std; @@ -49,14 +49,6 @@ using namespace std;
49 #include <srs_rtmp_amf0.hpp> 49 #include <srs_rtmp_amf0.hpp>
50 #include <srs_raw_avc.hpp> 50 #include <srs_raw_avc.hpp>
51 51
52 -ISrsUdpHandler::ISrsUdpHandler()  
53 -{  
54 -}  
55 -  
56 -ISrsUdpHandler::~ISrsUdpHandler()  
57 -{  
58 -}  
59 -  
60 SrsMpegtsQueue::SrsMpegtsQueue() 52 SrsMpegtsQueue::SrsMpegtsQueue()
61 { 53 {
62 nb_audios = nb_videos = 0; 54 nb_audios = nb_videos = 0;
@@ -50,27 +50,7 @@ class SrsRawAacStreamCodec; @@ -50,27 +50,7 @@ class SrsRawAacStreamCodec;
50 50
51 #include <srs_app_st.hpp> 51 #include <srs_app_st.hpp>
52 #include <srs_kernel_ts.hpp> 52 #include <srs_kernel_ts.hpp>
53 -  
54 -/**  
55 -* the udp packet handler.  
56 -*/  
57 -class ISrsUdpHandler  
58 -{  
59 -public:  
60 - ISrsUdpHandler();  
61 - virtual ~ISrsUdpHandler();  
62 -public:  
63 - /**  
64 - * when udp listener got a udp packet, notice server to process it.  
65 - * @param type, the client type, used to create concrete connection,  
66 - * for instance RTMP connection to serve client.  
67 - * @param from, the udp packet from address.  
68 - * @param buf, the udp packet bytes, user should copy if need to use.  
69 - * @param nb_buf, the size of udp packet bytes.  
70 - * @remark user should never use the buf, for it's a shared memory bytes.  
71 - */  
72 - virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) = 0;  
73 -}; 53 +#include <srs_app_listener.hpp>
74 54
75 /** 55 /**
76 * the queue for mpegts over udp to send packets. 56 * the queue for mpegts over udp to send packets.
@@ -44,9 +44,14 @@ ISrsRtspHandler::~ISrsRtspHandler() @@ -44,9 +44,14 @@ ISrsRtspHandler::~ISrsRtspHandler()
44 { 44 {
45 } 45 }
46 46
47 -SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o) 47 +SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax)
48 { 48 {
49 output = o; 49 output = o;
  50 + local_port_min = lpmin;
  51 + local_port_max = lpmax;
  52 +
  53 + session = "O9EaZ4bf"; // TODO: FIXME: generate session id.
  54 +
50 caster = c; 55 caster = c;
51 stfd = fd; 56 stfd = fd;
52 skt = new SrsStSocket(fd); 57 skt = new SrsStSocket(fd);
@@ -97,12 +102,35 @@ int SrsRtspConn::do_cycle() @@ -97,12 +102,35 @@ int SrsRtspConn::do_cycle()
97 return ret; 102 return ret;
98 } 103 }
99 } else if (req->is_announce()) { 104 } else if (req->is_announce()) {
  105 + srs_assert(req->sdp);
  106 + sps = req->sdp->video_sps;
  107 + pps = req->sdp->video_pps;
  108 + asc = req->sdp->audio_sh;
  109 + srs_trace("rtsp: video(#%s, %s), audio(#%s, %s, %sHZ %schannels)",
  110 + req->sdp->video_stream_id.c_str(), req->sdp->video_codec.c_str(),
  111 + req->sdp->audio_stream_id.c_str(), req->sdp->audio_codec.c_str(),
  112 + req->sdp->audio_sample_rate.c_str(), req->sdp->audio_channel.c_str()
  113 + );
100 if ((ret = rtsp->send_message(new SrsRtspResponse(req->seq))) != ERROR_SUCCESS) { 114 if ((ret = rtsp->send_message(new SrsRtspResponse(req->seq))) != ERROR_SUCCESS) {
101 if (!srs_is_client_gracefully_close(ret)) { 115 if (!srs_is_client_gracefully_close(ret)) {
102 srs_error("rtsp: send ANNOUNCE response failed. ret=%d", ret); 116 srs_error("rtsp: send ANNOUNCE response failed. ret=%d", ret);
103 } 117 }
104 return ret; 118 return ret;
105 } 119 }
  120 + } else if (req->is_setup()) {
  121 + srs_assert(req->transport);
  122 + SrsRtspSetupResponse* res = new SrsRtspSetupResponse(req->seq);
  123 + res->client_port_min = req->transport->client_port_min;
  124 + res->client_port_max = req->transport->client_port_max;
  125 + res->local_port_min = local_port_min;
  126 + res->local_port_max = local_port_max;
  127 + res->session = session;
  128 + if ((ret = rtsp->send_message(res)) != ERROR_SUCCESS) {
  129 + if (!srs_is_client_gracefully_close(ret)) {
  130 + srs_error("rtsp: send SETUP response failed. ret=%d", ret);
  131 + }
  132 + return ret;
  133 + }
106 } 134 }
107 } 135 }
108 136
@@ -144,6 +172,8 @@ SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c) @@ -144,6 +172,8 @@ SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
144 { 172 {
145 // TODO: FIXME: support reload. 173 // TODO: FIXME: support reload.
146 output = _srs_config->get_stream_caster_output(c); 174 output = _srs_config->get_stream_caster_output(c);
  175 + local_port_min = _srs_config->get_stream_caster_rtp_port_min(c);
  176 + local_port_max = _srs_config->get_stream_caster_rtp_port_max(c);
147 } 177 }
148 178
149 SrsRtspCaster::~SrsRtspCaster() 179 SrsRtspCaster::~SrsRtspCaster()
@@ -160,7 +190,11 @@ int SrsRtspCaster::serve_client(st_netfd_t stfd) @@ -160,7 +190,11 @@ int SrsRtspCaster::serve_client(st_netfd_t stfd)
160 { 190 {
161 int ret = ERROR_SUCCESS; 191 int ret = ERROR_SUCCESS;
162 192
163 - SrsRtspConn* conn = new SrsRtspConn(this, stfd, output); 193 + SrsRtspConn* conn = new SrsRtspConn(
  194 + this, stfd,
  195 + output, local_port_min, local_port_max
  196 + );
  197 +
164 if ((ret = conn->serve()) != ERROR_SUCCESS) { 198 if ((ret = conn->serve()) != ERROR_SUCCESS) {
165 srs_error("rtsp: serve client failed. ret=%d", ret); 199 srs_error("rtsp: serve client failed. ret=%d", ret);
166 srs_freep(conn); 200 srs_freep(conn);
@@ -65,13 +65,23 @@ class SrsRtspConn : public ISrsThreadHandler @@ -65,13 +65,23 @@ class SrsRtspConn : public ISrsThreadHandler
65 { 65 {
66 private: 66 private:
67 std::string output; 67 std::string output;
  68 + int local_port_min;
  69 + int local_port_max;
  70 +private:
  71 + std::string session;
  72 + // video sequence header.
  73 + std::string sps;
  74 + std::string pps;
  75 + // audio sequence header.
  76 + std::string asc;
  77 +private:
68 st_netfd_t stfd; 78 st_netfd_t stfd;
69 SrsStSocket* skt; 79 SrsStSocket* skt;
70 SrsRtspStack* rtsp; 80 SrsRtspStack* rtsp;
71 SrsRtspCaster* caster; 81 SrsRtspCaster* caster;
72 SrsThread* trd; 82 SrsThread* trd;
73 public: 83 public:
74 - SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o); 84 + SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax);
75 virtual ~SrsRtspConn(); 85 virtual ~SrsRtspConn();
76 public: 86 public:
77 virtual int serve(); 87 virtual int serve();
@@ -90,6 +100,9 @@ class SrsRtspCaster : public ISrsRtspHandler @@ -90,6 +100,9 @@ class SrsRtspCaster : public ISrsRtspHandler
90 { 100 {
91 private: 101 private:
92 std::string output; 102 std::string output;
  103 + int local_port_min;
  104 + int local_port_max;
  105 +private:
93 std::vector<SrsRtspConn*> clients; 106 std::vector<SrsRtspConn*> clients;
94 public: 107 public:
95 SrsRtspCaster(SrsConfDirective* c); 108 SrsRtspCaster(SrsConfDirective* c);
@@ -24,8 +24,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -24,8 +24,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <srs_app_server.hpp> 24 #include <srs_app_server.hpp>
25 25
26 #include <sys/types.h> 26 #include <sys/types.h>
27 -#include <sys/socket.h>  
28 -#include <arpa/inet.h>  
29 #include <signal.h> 27 #include <signal.h>
30 #include <sys/types.h> 28 #include <sys/types.h>
31 #include <sys/stat.h> 29 #include <sys/stat.h>
@@ -51,15 +49,6 @@ using namespace std; @@ -51,15 +49,6 @@ using namespace std;
51 // signal defines. 49 // signal defines.
52 #define SIGNAL_RELOAD SIGHUP 50 #define SIGNAL_RELOAD SIGHUP
53 51
54 -// nginx also set to 512  
55 -#define SERVER_LISTEN_BACKLOG 512  
56 -  
57 -// sleep in ms for udp recv packet.  
58 -#define SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS 0  
59 -  
60 -// set the max packet size.  
61 -#define SRS_UDP_MAX_PACKET_SIZE 65535  
62 -  
63 // system interval in ms, 52 // system interval in ms,
64 // all resolution times should be times togother, 53 // all resolution times should be times togother,
65 // for example, system-interval is x=1s(1000ms), 54 // for example, system-interval is x=1s(1000ms),
@@ -122,26 +111,13 @@ std::string __srs_listener_type2string(SrsListenerType type) @@ -122,26 +111,13 @@ std::string __srs_listener_type2string(SrsListenerType type)
122 111
123 SrsListener::SrsListener(SrsServer* server, SrsListenerType type) 112 SrsListener::SrsListener(SrsServer* server, SrsListenerType type)
124 { 113 {
125 - fd = -1;  
126 - stfd = NULL;  
127 -  
128 _port = 0; 114 _port = 0;
129 _server = server; 115 _server = server;
130 _type = type; 116 _type = type;
131 -  
132 - pthread = new SrsThread("listen", this, 0, true);  
133 } 117 }
134 118
135 SrsListener::~SrsListener() 119 SrsListener::~SrsListener()
136 { 120 {
137 - srs_close_stfd(stfd);  
138 -  
139 - pthread->stop();  
140 - srs_freep(pthread);  
141 -  
142 - // st does not close it sometimes,  
143 - // close it manually.  
144 - close(fd);  
145 } 121 }
146 122
147 SrsListenerType SrsListener::type() 123 SrsListenerType SrsListener::type()
@@ -149,92 +125,55 @@ SrsListenerType SrsListener::type() @@ -149,92 +125,55 @@ SrsListenerType SrsListener::type()
149 return _type; 125 return _type;
150 } 126 }
151 127
152 -int SrsListener::listen(int port) 128 +SrsStreamListener::SrsStreamListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type)
  129 +{
  130 + listener = NULL;
  131 +}
  132 +
  133 +SrsStreamListener::~SrsStreamListener()
  134 +{
  135 + srs_freep(listener);
  136 +}
  137 +
  138 +int SrsStreamListener::listen(int port)
153 { 139 {
154 int ret = ERROR_SUCCESS; 140 int ret = ERROR_SUCCESS;
155 141
156 _port = port; 142 _port = port;
157 -  
158 - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
159 - ret = ERROR_SOCKET_CREATE;  
160 - srs_error("create linux socket error. port=%d, ret=%d", port, ret);  
161 - return ret;  
162 - }  
163 - srs_verbose("create linux socket success. port=%d, fd=%d", port, fd);  
164 -  
165 - int reuse_socket = 1;  
166 - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {  
167 - ret = ERROR_SOCKET_SETREUSE;  
168 - srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);  
169 - return ret;  
170 - }  
171 - srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);  
172 -  
173 - sockaddr_in addr;  
174 - addr.sin_family = AF_INET;  
175 - addr.sin_port = htons(_port);  
176 - addr.sin_addr.s_addr = INADDR_ANY;  
177 - if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {  
178 - ret = ERROR_SOCKET_BIND;  
179 - srs_error("bind socket error. port=%d, ret=%d", port, ret);  
180 - return ret;  
181 - }  
182 - srs_verbose("bind socket success. port=%d, fd=%d", port, fd);  
183 -  
184 - if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {  
185 - ret = ERROR_SOCKET_LISTEN;  
186 - srs_error("listen socket error. port=%d, ret=%d", port, ret);  
187 - return ret;  
188 - }  
189 - srs_verbose("listen socket success. port=%d, fd=%d", port, fd);  
190 -  
191 - if ((stfd = st_netfd_open_socket(fd)) == NULL){  
192 - ret = ERROR_ST_OPEN_SOCKET;  
193 - srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);  
194 - return ret;  
195 - }  
196 - srs_verbose("st open socket success. port=%d, fd=%d", port, fd);  
197 -  
198 - if ((ret = pthread->start()) != ERROR_SUCCESS) {  
199 - srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret); 143 +
  144 + srs_freep(listener);
  145 + listener = new SrsTcpListener(this, port);
  146 +
  147 + if ((ret = listener->listen()) != ERROR_SUCCESS) {
  148 + srs_error("tcp listen failed. ret=%d", ret);
200 return ret; 149 return ret;
201 } 150 }
202 - srs_verbose("create st listen thread success, port=%d", port);  
203 151
204 srs_info("listen thread cid=%d, current_cid=%d, " 152 srs_info("listen thread cid=%d, current_cid=%d, "
205 "listen at port=%d, type=%d, fd=%d started success, port=%d", 153 "listen at port=%d, type=%d, fd=%d started success, port=%d",
206 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port); 154 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
207 155
208 - srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);  
209 - 156 + srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
  157 +
210 return ret; 158 return ret;
211 } 159 }
212 160
213 -int SrsListener::cycle() 161 +int SrsStreamListener::on_tcp_client(st_netfd_t stfd)
214 { 162 {
215 int ret = ERROR_SUCCESS; 163 int ret = ERROR_SUCCESS;
216 164
217 - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);  
218 -  
219 - if(client_stfd == NULL){  
220 - // ignore error.  
221 - srs_error("ignore accept thread stoppped for accept client error");  
222 - return ret;  
223 - }  
224 - srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));  
225 -  
226 - if ((ret = _server->accept_client(_type, client_stfd)) != ERROR_SUCCESS) { 165 + if ((ret = _server->accept_client(_type, stfd)) != ERROR_SUCCESS) {
227 srs_warn("accept client error. ret=%d", ret); 166 srs_warn("accept client error. ret=%d", ret);
228 return ret; 167 return ret;
229 } 168 }
230 - 169 +
231 return ret; 170 return ret;
232 } 171 }
233 172
234 #ifdef SRS_AUTO_STREAM_CASTER 173 #ifdef SRS_AUTO_STREAM_CASTER
235 SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) 174 SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type)
236 { 175 {
237 - _type = type; 176 + listener = NULL;
238 177
239 // the caller already ensure the type is ok, 178 // the caller already ensure the type is ok,
240 // we just assert here for unknown stream caster. 179 // we just assert here for unknown stream caster.
@@ -247,34 +186,52 @@ SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsCon @@ -247,34 +186,52 @@ SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsCon
247 SrsRtspListener::~SrsRtspListener() 186 SrsRtspListener::~SrsRtspListener()
248 { 187 {
249 srs_freep(caster); 188 srs_freep(caster);
  189 + srs_freep(listener);
250 } 190 }
251 191
252 -int SrsRtspListener::cycle() 192 +int SrsRtspListener::listen(int port)
253 { 193 {
254 int ret = ERROR_SUCCESS; 194 int ret = ERROR_SUCCESS;
  195 +
  196 + // the caller already ensure the type is ok,
  197 + // we just assert here for unknown stream caster.
  198 + srs_assert(_type == SrsListenerRtsp);
255 199
256 - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);  
257 -  
258 - if(client_stfd == NULL){  
259 - // ignore error.  
260 - srs_error("ignore accept thread stoppped for accept client error"); 200 + _port = port;
  201 +
  202 + srs_freep(listener);
  203 + listener = new SrsTcpListener(this, port);
  204 +
  205 + if ((ret = listener->listen()) != ERROR_SUCCESS) {
  206 + srs_error("udp caster listen failed. ret=%d", ret);
261 return ret; 207 return ret;
262 } 208 }
263 - srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));  
264 209
265 - if ((ret = caster->serve_client(client_stfd)) != ERROR_SUCCESS) { 210 + srs_info("listen thread cid=%d, current_cid=%d, "
  211 + "listen at port=%d, type=%d, fd=%d started success, port=%d",
  212 + pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
  213 +
  214 + srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
  215 +
  216 + return ret;
  217 +}
  218 +
  219 +int SrsRtspListener::on_tcp_client(st_netfd_t stfd)
  220 +{
  221 + int ret = ERROR_SUCCESS;
  222 +
  223 + if ((ret = caster->serve_client(stfd)) != ERROR_SUCCESS) {
266 srs_warn("accept client error. ret=%d", ret); 224 srs_warn("accept client error. ret=%d", ret);
267 return ret; 225 return ret;
268 } 226 }
269 - 227 +
270 return ret; 228 return ret;
271 } 229 }
272 230
273 -SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) 231 +SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type)
274 { 232 {
275 _type = type; 233 _type = type;
276 - nb_buf = SRS_UDP_MAX_PACKET_SIZE;  
277 - buf = new char[nb_buf]; 234 + listener = NULL;
278 235
279 // the caller already ensure the type is ok, 236 // the caller already ensure the type is ok,
280 // we just assert here for unknown stream caster. 237 // we just assert here for unknown stream caster.
@@ -284,13 +241,13 @@ SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfD @@ -284,13 +241,13 @@ SrsUdpListener::SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfD
284 } 241 }
285 } 242 }
286 243
287 -SrsUdpListener::~SrsUdpListener() 244 +SrsUdpCasterListener::~SrsUdpCasterListener()
288 { 245 {
289 srs_freep(caster); 246 srs_freep(caster);
290 - srs_freep(buf); 247 + srs_freep(listener);
291 } 248 }
292 249
293 -int SrsUdpListener::listen(int port) 250 +int SrsUdpCasterListener::listen(int port)
294 { 251 {
295 int ret = ERROR_SUCCESS; 252 int ret = ERROR_SUCCESS;
296 253
@@ -299,83 +256,20 @@ int SrsUdpListener::listen(int port) @@ -299,83 +256,20 @@ int SrsUdpListener::listen(int port)
299 srs_assert(_type == SrsListenerMpegTsOverUdp); 256 srs_assert(_type == SrsListenerMpegTsOverUdp);
300 257
301 _port = port; 258 _port = port;
302 -  
303 - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {  
304 - ret = ERROR_SOCKET_CREATE;  
305 - srs_error("create linux socket error. port=%d, ret=%d", port, ret);  
306 - return ret;  
307 - }  
308 - srs_verbose("create linux socket success. port=%d, fd=%d", port, fd);  
309 -  
310 - int reuse_socket = 1;  
311 - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {  
312 - ret = ERROR_SOCKET_SETREUSE;  
313 - srs_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);  
314 - return ret;  
315 - }  
316 - srs_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);  
317 -  
318 - sockaddr_in addr;  
319 - addr.sin_family = AF_INET;  
320 - addr.sin_port = htons(_port);  
321 - addr.sin_addr.s_addr = INADDR_ANY;  
322 - if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {  
323 - ret = ERROR_SOCKET_BIND;  
324 - srs_error("bind socket error. port=%d, ret=%d", port, ret);  
325 - return ret;  
326 - }  
327 - srs_verbose("bind socket success. port=%d, fd=%d", port, fd);  
328 -  
329 - if ((stfd = st_netfd_open_socket(fd)) == NULL){  
330 - ret = ERROR_ST_OPEN_SOCKET;  
331 - srs_error("st_netfd_open_socket open socket failed. port=%d, ret=%d", port, ret);  
332 - return ret;  
333 - }  
334 - srs_verbose("st open socket success. port=%d, fd=%d", port, fd);  
335 -  
336 - if ((ret = pthread->start()) != ERROR_SUCCESS) {  
337 - srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret); 259 +
  260 + srs_freep(listener);
  261 + listener = new SrsUdpListener(caster, port);
  262 +
  263 + if ((ret = listener->listen()) != ERROR_SUCCESS) {
  264 + srs_error("udp caster listen failed. ret=%d", ret);
338 return ret; 265 return ret;
339 } 266 }
340 - srs_verbose("create st listen thread success, port=%d", port);  
341 267
342 srs_info("listen thread cid=%d, current_cid=%d, " 268 srs_info("listen thread cid=%d, current_cid=%d, "
343 "listen at port=%d, type=%d, fd=%d started success, port=%d", 269 "listen at port=%d, type=%d, fd=%d started success, port=%d",
344 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port); 270 pthread->cid(), _srs_context->get_id(), _port, _type, fd, port);
345 271
346 - srs_trace("%s listen at udp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, fd);  
347 -  
348 - return ret;  
349 -}  
350 -  
351 -int SrsUdpListener::cycle()  
352 -{  
353 - int ret = ERROR_SUCCESS;  
354 -  
355 - // the caller already ensure the type is ok,  
356 - // we just assert here for unknown stream caster.  
357 - srs_assert(_type == SrsListenerMpegTsOverUdp);  
358 -  
359 - for (;;) {  
360 - // TODO: FIXME: support ipv6, @see man 7 ipv6  
361 - sockaddr_in from;  
362 - int nb_from = sizeof(sockaddr_in);  
363 - int nread = 0;  
364 -  
365 - if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) {  
366 - srs_warn("ignore recv udp packet failed, nread=%d", nread);  
367 - continue;  
368 - }  
369 -  
370 - if ((ret = caster->on_udp_packet(&from, buf, nread)) != ERROR_SUCCESS) {  
371 - srs_warn("handle udp packet failed. ret=%d", ret);  
372 - continue;  
373 - }  
374 -  
375 - if (SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS > 0) {  
376 - st_usleep(SRS_UDP_PACKET_RECV_CYCLE_INTERVAL_MS * 1000);  
377 - }  
378 - } 272 + srs_trace("%s listen at udp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd());
379 273
380 return ret; 274 return ret;
381 } 275 }
@@ -992,7 +886,7 @@ int SrsServer::listen_rtmp() @@ -992,7 +886,7 @@ int SrsServer::listen_rtmp()
992 close_listeners(SrsListenerRtmpStream); 886 close_listeners(SrsListenerRtmpStream);
993 887
994 for (int i = 0; i < (int)ports.size(); i++) { 888 for (int i = 0; i < (int)ports.size(); i++) {
995 - SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream); 889 + SrsListener* listener = new SrsStreamListener(this, SrsListenerRtmpStream);
996 listeners.push_back(listener); 890 listeners.push_back(listener);
997 891
998 int port = ::atoi(ports[i].c_str()); 892 int port = ::atoi(ports[i].c_str());
@@ -1012,7 +906,7 @@ int SrsServer::listen_http_api() @@ -1012,7 +906,7 @@ int SrsServer::listen_http_api()
1012 #ifdef SRS_AUTO_HTTP_API 906 #ifdef SRS_AUTO_HTTP_API
1013 close_listeners(SrsListenerHttpApi); 907 close_listeners(SrsListenerHttpApi);
1014 if (_srs_config->get_http_api_enabled()) { 908 if (_srs_config->get_http_api_enabled()) {
1015 - SrsListener* listener = new SrsListener(this, SrsListenerHttpApi); 909 + SrsListener* listener = new SrsStreamListener(this, SrsListenerHttpApi);
1016 listeners.push_back(listener); 910 listeners.push_back(listener);
1017 911
1018 int port = _srs_config->get_http_api_listen(); 912 int port = _srs_config->get_http_api_listen();
@@ -1033,7 +927,7 @@ int SrsServer::listen_http_stream() @@ -1033,7 +927,7 @@ int SrsServer::listen_http_stream()
1033 #ifdef SRS_AUTO_HTTP_SERVER 927 #ifdef SRS_AUTO_HTTP_SERVER
1034 close_listeners(SrsListenerHttpStream); 928 close_listeners(SrsListenerHttpStream);
1035 if (_srs_config->get_http_stream_enabled()) { 929 if (_srs_config->get_http_stream_enabled()) {
1036 - SrsListener* listener = new SrsListener(this, SrsListenerHttpStream); 930 + SrsListener* listener = new SrsStreamListener(this, SrsListenerHttpStream);
1037 listeners.push_back(listener); 931 listeners.push_back(listener);
1038 932
1039 int port = _srs_config->get_http_stream_listen(); 933 int port = _srs_config->get_http_stream_listen();
@@ -1067,7 +961,7 @@ int SrsServer::listen_stream_caster() @@ -1067,7 +961,7 @@ int SrsServer::listen_stream_caster()
1067 961
1068 std::string caster = _srs_config->get_stream_caster_engine(stream_caster); 962 std::string caster = _srs_config->get_stream_caster_engine(stream_caster);
1069 if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) { 963 if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) {
1070 - listener = new SrsUdpListener(this, SrsListenerMpegTsOverUdp, stream_caster); 964 + listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster);
1071 } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP) { 965 } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP) {
1072 listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster); 966 listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster);
1073 } else { 967 } else {
@@ -35,9 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -35,9 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 35
36 #include <srs_app_st.hpp> 36 #include <srs_app_st.hpp>
37 #include <srs_app_reload.hpp> 37 #include <srs_app_reload.hpp>
38 -#include <srs_app_thread.hpp>  
39 #include <srs_app_source.hpp> 38 #include <srs_app_source.hpp>
40 #include <srs_app_hls.hpp> 39 #include <srs_app_hls.hpp>
  40 +#include <srs_app_listener.hpp>
41 41
42 class SrsServer; 42 class SrsServer;
43 class SrsConnection; 43 class SrsConnection;
@@ -49,6 +49,8 @@ class SrsKbps; @@ -49,6 +49,8 @@ class SrsKbps;
49 class SrsConfDirective; 49 class SrsConfDirective;
50 class ISrsUdpHandler; 50 class ISrsUdpHandler;
51 class ISrsRtspHandler; 51 class ISrsRtspHandler;
  52 +class SrsUdpListener;
  53 +class SrsTcpListener;
52 54
53 // listener type for server to identify the connection, 55 // listener type for server to identify the connection,
54 // that is, use different type to process the connection. 56 // that is, use different type to process the connection.
@@ -69,60 +71,71 @@ enum SrsListenerType @@ -69,60 +71,71 @@ enum SrsListenerType
69 /** 71 /**
70 * the common tcp listener, for RTMP/HTTP server. 72 * the common tcp listener, for RTMP/HTTP server.
71 */ 73 */
72 -class SrsListener : public ISrsThreadHandler 74 +class SrsListener
73 { 75 {
74 -public: 76 +protected:
75 SrsListenerType _type; 77 SrsListenerType _type;
76 protected: 78 protected:
77 - int fd;  
78 - st_netfd_t stfd;  
79 int _port; 79 int _port;
80 SrsServer* _server; 80 SrsServer* _server;
81 - SrsThread* pthread;  
82 public: 81 public:
83 SrsListener(SrsServer* server, SrsListenerType type); 82 SrsListener(SrsServer* server, SrsListenerType type);
84 virtual ~SrsListener(); 83 virtual ~SrsListener();
85 public: 84 public:
86 virtual SrsListenerType type(); 85 virtual SrsListenerType type();
  86 + virtual int listen(int port) = 0;
  87 +};
  88 +
  89 +/**
  90 +* tcp listener.
  91 +*/
  92 +class SrsStreamListener : virtual public SrsListener, virtual public ISrsTcpHandler
  93 +{
  94 +private:
  95 + SrsTcpListener* listener;
  96 +public:
  97 + SrsStreamListener(SrsServer* server, SrsListenerType type);
  98 + virtual ~SrsStreamListener();
  99 +public:
87 virtual int listen(int port); 100 virtual int listen(int port);
88 -// interface ISrsThreadHandler. 101 +// ISrsTcpHandler
89 public: 102 public:
90 - virtual int cycle(); 103 + virtual int on_tcp_client(st_netfd_t stfd);
91 }; 104 };
92 105
93 #ifdef SRS_AUTO_STREAM_CASTER 106 #ifdef SRS_AUTO_STREAM_CASTER
94 /** 107 /**
95 * the tcp listener, for rtsp server. 108 * the tcp listener, for rtsp server.
96 */ 109 */
97 -class SrsRtspListener : public SrsListener 110 +class SrsRtspListener : virtual public SrsListener, virtual public ISrsTcpHandler
98 { 111 {
99 private: 112 private:
  113 + SrsTcpListener* listener;
  114 +private:
100 ISrsRtspHandler* caster; 115 ISrsRtspHandler* caster;
101 public: 116 public:
102 SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); 117 SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
103 virtual ~SrsRtspListener(); 118 virtual ~SrsRtspListener();
104 -// interface ISrsThreadHandler.  
105 public: 119 public:
106 - virtual int cycle(); 120 + virtual int listen(int port);
  121 +// ISrsTcpHandler
  122 +public:
  123 + virtual int on_tcp_client(st_netfd_t stfd);
107 }; 124 };
108 125
109 /** 126 /**
110 * the udp listener, for udp server. 127 * the udp listener, for udp server.
111 */ 128 */
112 -class SrsUdpListener : public SrsListener 129 +class SrsUdpCasterListener : public SrsListener
113 { 130 {
114 private: 131 private:
115 - char* buf;  
116 - int nb_buf; 132 + SrsUdpListener* listener;
117 ISrsUdpHandler* caster; 133 ISrsUdpHandler* caster;
118 public: 134 public:
119 - SrsUdpListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);  
120 - virtual ~SrsUdpListener(); 135 + SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
  136 + virtual ~SrsUdpCasterListener();
121 public: 137 public:
122 virtual int listen(int port); 138 virtual int listen(int port);
123 -// interface ISrsThreadHandler.  
124 -public:  
125 - virtual int cycle();  
126 }; 139 };
127 #endif 140 #endif
128 141
@@ -231,9 +231,9 @@ int SrsRtspSdp::parse(string token) @@ -231,9 +231,9 @@ int SrsRtspSdp::parse(string token)
231 audio_sample_rate = audio_codec.substr(pos + 1); 231 audio_sample_rate = audio_codec.substr(pos + 1);
232 audio_codec = audio_codec.substr(0, pos); 232 audio_codec = audio_codec.substr(0, pos);
233 } 233 }
234 - if ((pos = audio_codec.find("/")) != string::npos) {  
235 - audio_channel = audio_codec.substr(pos + 1);  
236 - audio_codec = audio_codec.substr(0, pos); 234 + if ((pos = audio_sample_rate.find("/")) != string::npos) {
  235 + audio_channel = audio_sample_rate.substr(pos + 1);
  236 + audio_sample_rate = audio_sample_rate.substr(0, pos);
237 } 237 }
238 } 238 }
239 } else if (desc_key == "fmtp") { 239 } else if (desc_key == "fmtp") {
@@ -283,19 +283,20 @@ int SrsRtspSdp::parse(string token) @@ -283,19 +283,20 @@ int SrsRtspSdp::parse(string token)
283 return ret; 283 return ret;
284 } 284 }
285 285
286 -int SrsRtspSdp::parse_fmtp_attribute(string& attr) 286 +int SrsRtspSdp::parse_fmtp_attribute(string attr)
287 { 287 {
288 int ret = ERROR_SUCCESS; 288 int ret = ERROR_SUCCESS;
289 289
290 size_t pos = string::npos; 290 size_t pos = string::npos;
  291 + std::string token = attr;
291 292
292 - while (!attr.empty()) {  
293 - std::string item = attr; 293 + while (!token.empty()) {
  294 + std::string item = token;
294 if ((pos = item.find(";")) != string::npos) { 295 if ((pos = item.find(";")) != string::npos) {
295 - item = attr.substr(0, pos);  
296 - attr = attr.substr(pos + 1); 296 + item = token.substr(0, pos);
  297 + token = token.substr(pos + 1);
297 } else { 298 } else {
298 - attr = ""; 299 + token = "";
299 } 300 }
300 301
301 std::string item_key = item, item_value; 302 std::string item_key = item, item_value;
@@ -337,19 +338,20 @@ int SrsRtspSdp::parse_fmtp_attribute(string& attr) @@ -337,19 +338,20 @@ int SrsRtspSdp::parse_fmtp_attribute(string& attr)
337 return ret; 338 return ret;
338 } 339 }
339 340
340 -int SrsRtspSdp::parse_control_attribute(string& attr) 341 +int SrsRtspSdp::parse_control_attribute(string attr)
341 { 342 {
342 int ret = ERROR_SUCCESS; 343 int ret = ERROR_SUCCESS;
343 344
344 size_t pos = string::npos; 345 size_t pos = string::npos;
  346 + std::string token = attr;
345 347
346 - while (!attr.empty()) {  
347 - std::string item = attr; 348 + while (!token.empty()) {
  349 + std::string item = token;
348 if ((pos = item.find(";")) != string::npos) { 350 if ((pos = item.find(";")) != string::npos) {
349 - item = attr.substr(0, pos);  
350 - attr = attr.substr(pos + 1); 351 + item = token.substr(0, pos);
  352 + token = token.substr(pos + 1);
351 } else { 353 } else {
352 - attr = ""; 354 + token = "";
353 } 355 }
354 356
355 std::string item_key = item, item_value; 357 std::string item_key = item, item_value;
@@ -392,16 +394,81 @@ string SrsRtspSdp::base64_decode(string value) @@ -392,16 +394,81 @@ string SrsRtspSdp::base64_decode(string value)
392 return plaintext; 394 return plaintext;
393 } 395 }
394 396
  397 +SrsRtspTransport::SrsRtspTransport()
  398 +{
  399 + client_port_min = 0;
  400 + client_port_max = 0;
  401 +}
  402 +
  403 +SrsRtspTransport::~SrsRtspTransport()
  404 +{
  405 +}
  406 +
  407 +int SrsRtspTransport::parse(string attr)
  408 +{
  409 + int ret = ERROR_SUCCESS;
  410 +
  411 + size_t pos = string::npos;
  412 + std::string token = attr;
  413 +
  414 + while (!token.empty()) {
  415 + std::string item = token;
  416 + if ((pos = item.find(";")) != string::npos) {
  417 + item = token.substr(0, pos);
  418 + token = token.substr(pos + 1);
  419 + } else {
  420 + token = "";
  421 + }
  422 +
  423 + std::string item_key = item, item_value;
  424 + if ((pos = item.find("=")) != string::npos) {
  425 + item_key = item.substr(0, pos);
  426 + item_value = item.substr(pos + 1);
  427 + }
  428 +
  429 + if (transport.empty()) {
  430 + transport = item_key;
  431 + if ((pos = transport.find("/")) != string::npos) {
  432 + profile = transport.substr(pos + 1);
  433 + transport = transport.substr(0, pos);
  434 + }
  435 + if ((pos = profile.find("/")) != string::npos) {
  436 + lower_transport = profile.substr(pos + 1);
  437 + profile = profile.substr(0, pos);
  438 + }
  439 + }
  440 +
  441 + if (item_key == "unicast" || item_key == "multicast") {
  442 + cast_type = item_key;
  443 + } else if (item_key == "mode") {
  444 + mode = item_value;
  445 + } else if (item_key == "client_port") {
  446 + std::string sport = item_value;
  447 + std::string eport = item_value;
  448 + if ((pos = eport.find("-")) != string::npos) {
  449 + sport = eport.substr(0, pos);
  450 + eport = eport.substr(pos + 1);
  451 + }
  452 + client_port_min = ::atoi(sport.c_str());
  453 + client_port_max = ::atoi(eport.c_str());
  454 + }
  455 + }
  456 +
  457 + return ret;
  458 +}
  459 +
395 SrsRtspRequest::SrsRtspRequest() 460 SrsRtspRequest::SrsRtspRequest()
396 { 461 {
397 seq = 0; 462 seq = 0;
398 content_length = 0; 463 content_length = 0;
399 sdp = NULL; 464 sdp = NULL;
  465 + transport = NULL;
400 } 466 }
401 467
402 SrsRtspRequest::~SrsRtspRequest() 468 SrsRtspRequest::~SrsRtspRequest()
403 { 469 {
404 srs_freep(sdp); 470 srs_freep(sdp);
  471 + srs_freep(transport);
405 } 472 }
406 473
407 bool SrsRtspRequest::is_options() 474 bool SrsRtspRequest::is_options()
@@ -414,6 +481,11 @@ bool SrsRtspRequest::is_announce() @@ -414,6 +481,11 @@ bool SrsRtspRequest::is_announce()
414 return method == __SRS_METHOD_ANNOUNCE; 481 return method == __SRS_METHOD_ANNOUNCE;
415 } 482 }
416 483
  484 +bool SrsRtspRequest::is_setup()
  485 +{
  486 + return method == __SRS_METHOD_SETUP;
  487 +}
  488 +
417 SrsRtspResponse::SrsRtspResponse(int cseq) 489 SrsRtspResponse::SrsRtspResponse(int cseq)
418 { 490 {
419 seq = cseq; 491 seq = cseq;
@@ -424,8 +496,10 @@ SrsRtspResponse::~SrsRtspResponse() @@ -424,8 +496,10 @@ SrsRtspResponse::~SrsRtspResponse()
424 { 496 {
425 } 497 }
426 498
427 -stringstream& SrsRtspResponse::encode(stringstream& ss) 499 +int SrsRtspResponse::encode(stringstream& ss)
428 { 500 {
  501 + int ret = ERROR_SUCCESS;
  502 +
429 // status line 503 // status line
430 ss << __SRS_VERSION << __SRS_RTSP_SP 504 ss << __SRS_VERSION << __SRS_RTSP_SP
431 << status << __SRS_RTSP_SP 505 << status << __SRS_RTSP_SP
@@ -439,7 +513,20 @@ stringstream& SrsRtspResponse::encode(stringstream& ss) @@ -439,7 +513,20 @@ stringstream& SrsRtspResponse::encode(stringstream& ss)
439 << "Pragma: no-cache" << __SRS_RTSP_CRLF 513 << "Pragma: no-cache" << __SRS_RTSP_CRLF
440 << "Server: " << RTMP_SIG_SRS_SERVER << __SRS_RTSP_CRLF; 514 << "Server: " << RTMP_SIG_SRS_SERVER << __SRS_RTSP_CRLF;
441 515
442 - return ss; 516 + if ((ret = encode_header(ss)) != ERROR_SUCCESS) {
  517 + srs_error("rtsp: encode header failed. ret=%d", ret);
  518 + return ret;
  519 + };
  520 +
  521 + // header EOF.
  522 + ss << __SRS_RTSP_CRLF;
  523 +
  524 + return ret;
  525 +}
  526 +
  527 +int SrsRtspResponse::encode_header(std::stringstream& ss)
  528 +{
  529 + return ERROR_SUCCESS;
443 } 530 }
444 531
445 SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq) 532 SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq)
@@ -453,10 +540,8 @@ SrsRtspOptionsResponse::~SrsRtspOptionsResponse() @@ -453,10 +540,8 @@ SrsRtspOptionsResponse::~SrsRtspOptionsResponse()
453 { 540 {
454 } 541 }
455 542
456 -stringstream& SrsRtspOptionsResponse::encode(stringstream& ss) 543 +int SrsRtspOptionsResponse::encode_header(stringstream& ss)
457 { 544 {
458 - SrsRtspResponse::encode(ss);  
459 -  
460 SrsRtspMethod __methods[] = { 545 SrsRtspMethod __methods[] = {
461 SrsRtspMethodDescribe, 546 SrsRtspMethodDescribe,
462 SrsRtspMethodAnnounce, 547 SrsRtspMethodAnnounce,
@@ -489,10 +574,27 @@ stringstream& SrsRtspOptionsResponse::encode(stringstream& ss) @@ -489,10 +574,27 @@ stringstream& SrsRtspOptionsResponse::encode(stringstream& ss)
489 } 574 }
490 ss << __SRS_RTSP_CRLF; 575 ss << __SRS_RTSP_CRLF;
491 576
492 - // eof header.  
493 - ss << __SRS_RTSP_CRLF; 577 + return ERROR_SUCCESS;
  578 +}
  579 +
  580 +SrsRtspSetupResponse::SrsRtspSetupResponse(int seq) : SrsRtspResponse(seq)
  581 +{
  582 + local_port_min = 0;
  583 + local_port_max = 0;
  584 +}
  585 +
  586 +SrsRtspSetupResponse::~SrsRtspSetupResponse()
  587 +{
  588 +}
494 589
495 - return ss; 590 +int SrsRtspSetupResponse::encode_header(stringstream& ss)
  591 +{
  592 + ss << __SRS_TOKEN_SESSION << ":" << __SRS_RTSP_SP << session << __SRS_RTSP_CRLF;
  593 + ss << __SRS_TOKEN_TRANSPORT << ":" << __SRS_RTSP_SP
  594 + << "RTP/AVP;unicast;client_port=" << client_port_min << "-" << client_port_max << ";"
  595 + << "server_port=" << local_port_min << "-" << local_port_max
  596 + << __SRS_RTSP_CRLF;
  597 + return ERROR_SUCCESS;
496 } 598 }
497 599
498 SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s) 600 SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s)
@@ -613,6 +715,21 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req) @@ -613,6 +715,21 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
613 return ret; 715 return ret;
614 } 716 }
615 req->content_length = ::atol(cl.c_str()); 717 req->content_length = ::atol(cl.c_str());
  718 + } else if (token == __SRS_TOKEN_TRANSPORT) {
  719 + std::string transport;
  720 + if ((ret = recv_token_eof(transport)) != ERROR_SUCCESS) {
  721 + if (!srs_is_client_gracefully_close(ret)) {
  722 + srs_error("rtsp: parse %s failed. ret=%d", __SRS_TOKEN_TRANSPORT, ret);
  723 + }
  724 + return ret;
  725 + }
  726 + if (!req->transport) {
  727 + req->transport = new SrsRtspTransport();
  728 + }
  729 + if ((ret = req->transport->parse(transport)) != ERROR_SUCCESS) {
  730 + srs_error("rtsp: parse transport failed, transport=%s. ret=%d", transport.c_str(), ret);
  731 + return ret;
  732 + }
616 } else { 733 } else {
617 // unknown header name, parse util EOF. 734 // unknown header name, parse util EOF.
618 SrsRtspTokenState state = SrsRtspTokenStateNormal; 735 SrsRtspTokenState state = SrsRtspTokenStateNormal;
@@ -60,6 +60,8 @@ class ISrsProtocolReaderWriter; @@ -60,6 +60,8 @@ class ISrsProtocolReaderWriter;
60 #define __SRS_TOKEN_PUBLIC "Public" 60 #define __SRS_TOKEN_PUBLIC "Public"
61 #define __SRS_TOKEN_CONTENT_TYPE "Content-Type" 61 #define __SRS_TOKEN_CONTENT_TYPE "Content-Type"
62 #define __SRS_TOKEN_CONTENT_LENGTH "Content-Length" 62 #define __SRS_TOKEN_CONTENT_LENGTH "Content-Length"
  63 +#define __SRS_TOKEN_TRANSPORT "Transport"
  64 +#define __SRS_TOKEN_SESSION "Session"
63 65
64 // RTSP methods 66 // RTSP methods
65 #define __SRS_METHOD_OPTIONS "OPTIONS" 67 #define __SRS_METHOD_OPTIONS "OPTIONS"
@@ -98,6 +100,53 @@ enum SrsRtspSdpState @@ -98,6 +100,53 @@ enum SrsRtspSdpState
98 }; 100 };
99 101
100 /** 102 /**
  103 +* 10 Method Definitions
  104 +* The method token indicates the method to be performed on the resource
  105 +* identified by the Request-URI. The method is case-sensitive. New
  106 +* methods may be defined in the future. Method names may not start with
  107 +* a $ character (decimal 24) and must be a token. Methods are
  108 +* summarized in Table 2.
  109 +* Notes on Table 2: PAUSE is recommended, but not required in that a
  110 +* fully functional server can be built that does not support this
  111 +* method, for example, for live feeds. If a server does not support a
  112 +* particular method, it MUST return "501 Not Implemented" and a client
  113 +* SHOULD not try this method again for this server.
  114 +*/
  115 +enum SrsRtspMethod
  116 +{
  117 + SrsRtspMethodDescribe = 0x0001,
  118 + SrsRtspMethodAnnounce = 0x0002,
  119 + SrsRtspMethodGetParameter = 0x0004,
  120 + SrsRtspMethodOptions = 0x0008,
  121 + SrsRtspMethodPause = 0x0010,
  122 + SrsRtspMethodPlay = 0x0020,
  123 + SrsRtspMethodRecord = 0x0040,
  124 + SrsRtspMethodRedirect = 0x0080,
  125 + SrsRtspMethodSetup = 0x0100,
  126 + SrsRtspMethodSetParameter = 0x0200,
  127 + SrsRtspMethodTeardown = 0x0400,
  128 +};
  129 +
  130 +/**
  131 +* the state of rtsp token.
  132 +*/
  133 +enum SrsRtspTokenState
  134 +{
  135 + /**
  136 + * parse token failed, default state.
  137 + */
  138 + SrsRtspTokenStateError = 100,
  139 + /**
  140 + * when SP follow the token.
  141 + */
  142 + SrsRtspTokenStateNormal = 101,
  143 + /**
  144 + * when CRLF follow the token.
  145 + */
  146 + SrsRtspTokenStateEOF = 102,
  147 +};
  148 +
  149 +/**
101 * the sdp in announce. 150 * the sdp in announce.
102 * Appendix C: Use of SDP for RTSP Session Descriptions 151 * Appendix C: Use of SDP for RTSP Session Descriptions
103 * The Session Description Protocol (SDP, RFC 2327 [6]) may be used to 152 * The Session Description Protocol (SDP, RFC 2327 [6]) may be used to
@@ -179,11 +228,11 @@ private: @@ -179,11 +228,11 @@ private:
179 /** 228 /**
180 * generally, the fmtp is the sequence header for video or audio. 229 * generally, the fmtp is the sequence header for video or audio.
181 */ 230 */
182 - virtual int parse_fmtp_attribute(std::string& attr); 231 + virtual int parse_fmtp_attribute(std::string attr);
183 /** 232 /**
184 * generally, the control is the stream info for video or audio. 233 * generally, the control is the stream info for video or audio.
185 */ 234 */
186 - virtual int parse_control_attribute(std::string& attr); 235 + virtual int parse_control_attribute(std::string attr);
187 /** 236 /**
188 * decode the string by base64. 237 * decode the string by base64.
189 */ 238 */
@@ -191,6 +240,53 @@ private: @@ -191,6 +240,53 @@ private:
191 }; 240 };
192 241
193 /** 242 /**
  243 +* the rtsp transport.
  244 +* 12.39 Transport
  245 +* This request header indicates which transport protocol is to be used
  246 +* and configures its parameters such as destination address,
  247 +* compression, multicast time-to-live and destination port for a single
  248 +* stream. It sets those values not already determined by a presentation
  249 +* description.
  250 +*/
  251 +class SrsRtspTransport
  252 +{
  253 +public:
  254 + // The syntax for the transport specifier is
  255 + // transport/profile/lower-transport
  256 + std::string transport;
  257 + std::string profile;
  258 + std::string lower_transport;
  259 + // unicast | multicast
  260 + // mutually exclusive indication of whether unicast or multicast
  261 + // delivery will be attempted. Default value is multicast.
  262 + // Clients that are capable of handling both unicast and
  263 + // multicast transmission MUST indicate such capability by
  264 + // including two full transport-specs with separate parameters
  265 + // for each.
  266 + std::string cast_type;
  267 + // The mode parameter indicates the methods to be supported for
  268 + // this session. Valid values are PLAY and RECORD. If not
  269 + // provided, the default is PLAY.
  270 + std::string mode;
  271 + // This parameter provides the unicast RTP/RTCP port pair on
  272 + // which the client has chosen to receive media data and control
  273 + // information. It is specified as a range, e.g.,
  274 + // client_port=3456-3457.
  275 + // where client will use port in:
  276 + // [client_port_min, client_port_max)
  277 + int client_port_min;
  278 + int client_port_max;
  279 +public:
  280 + SrsRtspTransport();
  281 + virtual ~SrsRtspTransport();
  282 +public:
  283 + /**
  284 + * parse a line of token for transport.
  285 + */
  286 + virtual int parse(std::string attr);
  287 +};
  288 +
  289 +/**
194 * the rtsp request message. 290 * the rtsp request message.
195 * 6 Request 291 * 6 Request
196 * A request message from a client to a server or vice versa includes, 292 * A request message from a client to a server or vice versa includes,
@@ -245,12 +341,17 @@ public: @@ -245,12 +341,17 @@ public:
245 * the sdp in announce, NULL for no sdp. 341 * the sdp in announce, NULL for no sdp.
246 */ 342 */
247 SrsRtspSdp* sdp; 343 SrsRtspSdp* sdp;
  344 + /**
  345 + * the transport in setup, NULL for no transport.
  346 + */
  347 + SrsRtspTransport* transport;
248 public: 348 public:
249 SrsRtspRequest(); 349 SrsRtspRequest();
250 virtual ~SrsRtspRequest(); 350 virtual ~SrsRtspRequest();
251 public: 351 public:
252 virtual bool is_options(); 352 virtual bool is_options();
253 virtual bool is_announce(); 353 virtual bool is_announce();
  354 + virtual bool is_setup();
254 }; 355 };
255 356
256 /** 357 /**
@@ -302,35 +403,12 @@ public: @@ -302,35 +403,12 @@ public:
302 /** 403 /**
303 * encode message to string. 404 * encode message to string.
304 */ 405 */
305 - virtual std::stringstream& encode(std::stringstream& ss);  
306 -};  
307 -  
308 -/**  
309 -* 10 Method Definitions  
310 -* The method token indicates the method to be performed on the resource  
311 -* identified by the Request-URI. The method is case-sensitive. New  
312 -* methods may be defined in the future. Method names may not start with  
313 -* a $ character (decimal 24) and must be a token. Methods are  
314 -* summarized in Table 2.  
315 -* Notes on Table 2: PAUSE is recommended, but not required in that a  
316 -* fully functional server can be built that does not support this  
317 -* method, for example, for live feeds. If a server does not support a  
318 -* particular method, it MUST return "501 Not Implemented" and a client  
319 -* SHOULD not try this method again for this server.  
320 -*/  
321 -enum SrsRtspMethod  
322 -{  
323 - SrsRtspMethodDescribe = 0x0001,  
324 - SrsRtspMethodAnnounce = 0x0002,  
325 - SrsRtspMethodGetParameter = 0x0004,  
326 - SrsRtspMethodOptions = 0x0008,  
327 - SrsRtspMethodPause = 0x0010,  
328 - SrsRtspMethodPlay = 0x0020,  
329 - SrsRtspMethodRecord = 0x0040,  
330 - SrsRtspMethodRedirect = 0x0080,  
331 - SrsRtspMethodSetup = 0x0100,  
332 - SrsRtspMethodSetParameter = 0x0200,  
333 - SrsRtspMethodTeardown = 0x0400, 406 + virtual int encode(std::stringstream& ss);
  407 +protected:
  408 + /**
  409 + * sub classes override this to encode the headers.
  410 + */
  411 + virtual int encode_header(std::stringstream& ss);
334 }; 412 };
335 413
336 /** 414 /**
@@ -349,27 +427,38 @@ public: @@ -349,27 +427,38 @@ public:
349 public: 427 public:
350 SrsRtspOptionsResponse(int cseq); 428 SrsRtspOptionsResponse(int cseq);
351 virtual ~SrsRtspOptionsResponse(); 429 virtual ~SrsRtspOptionsResponse();
352 -public:  
353 - virtual std::stringstream& encode(std::stringstream& ss); 430 +protected:
  431 + virtual int encode_header(std::stringstream& ss);
354 }; 432 };
355 433
356 /** 434 /**
357 -* the state of rtsp token. 435 +* 10.4 SETUP
  436 +* The SETUP request for a URI specifies the transport mechanism to be
  437 +* used for the streamed media. A client can issue a SETUP request for a
  438 +* stream that is already playing to change transport parameters, which
  439 +* a server MAY allow. If it does not allow this, it MUST respond with
  440 +* error "455 Method Not Valid In This State". For the benefit of any
  441 +* intervening firewalls, a client must indicate the transport
  442 +* parameters even if it has no influence over these parameters, for
  443 +* example, where the server advertises a fixed multicast address.
358 */ 444 */
359 -enum SrsRtspTokenState 445 +class SrsRtspSetupResponse : public SrsRtspResponse
360 { 446 {
361 - /**  
362 - * parse token failed, default state.  
363 - */  
364 - SrsRtspTokenStateError = 100,  
365 - /**  
366 - * when SP follow the token.  
367 - */  
368 - SrsRtspTokenStateNormal = 101,  
369 - /**  
370 - * when CRLF follow the token.  
371 - */  
372 - SrsRtspTokenStateEOF = 102, 447 +public:
  448 + // the client specified port.
  449 + int client_port_min;
  450 + int client_port_max;
  451 + // client will use the port in:
  452 + // [local_port_min, local_port_max)
  453 + int local_port_min;
  454 + int local_port_max;
  455 + // session.
  456 + std::string session;
  457 +public:
  458 + SrsRtspSetupResponse(int cseq);
  459 + virtual ~SrsRtspSetupResponse();
  460 +protected:
  461 + virtual int encode_header(std::stringstream& ss);
373 }; 462 };
374 463
375 /** 464 /**