winlin

for #133, alloc and free rtp port.

@@ -77,6 +77,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, int p) @@ -77,6 +77,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, int p)
77 77
78 SrsUdpListener::~SrsUdpListener() 78 SrsUdpListener::~SrsUdpListener()
79 { 79 {
  80 + // close the stfd to trigger thread to interrupted.
80 srs_close_stfd(stfd); 81 srs_close_stfd(stfd);
81 82
82 pthread->stop(); 83 pthread->stop();
@@ -144,7 +145,7 @@ int SrsUdpListener::cycle() @@ -144,7 +145,7 @@ int SrsUdpListener::cycle()
144 { 145 {
145 int ret = ERROR_SUCCESS; 146 int ret = ERROR_SUCCESS;
146 147
147 - for (;;) { 148 + while (pthread->can_loop()) {
148 // TODO: FIXME: support ipv6, @see man 7 ipv6 149 // TODO: FIXME: support ipv6, @see man 7 ipv6
149 sockaddr_in from; 150 sockaddr_in from;
150 int nb_from = sizeof(sockaddr_in); 151 int nb_from = sizeof(sockaddr_in);
@@ -181,6 +182,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, int p) @@ -181,6 +182,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, int p)
181 182
182 SrsTcpListener::~SrsTcpListener() 183 SrsTcpListener::~SrsTcpListener()
183 { 184 {
  185 + // close the stfd to trigger thread to interrupted.
184 srs_close_stfd(stfd); 186 srs_close_stfd(stfd);
185 187
186 pthread->stop(); 188 pthread->stop();
@@ -36,21 +36,41 @@ using namespace std; @@ -36,21 +36,41 @@ using namespace std;
36 36
37 #ifdef SRS_AUTO_STREAM_CASTER 37 #ifdef SRS_AUTO_STREAM_CASTER
38 38
39 -ISrsRtspHandler::ISrsRtspHandler() 39 +SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p)
40 { 40 {
  41 + rtsp = r;
  42 + _port = p;
  43 + listener = new SrsUdpListener(this, p);
41 } 44 }
42 45
43 -ISrsRtspHandler::~ISrsRtspHandler() 46 +SrsRtpConn::~SrsRtpConn()
44 { 47 {
  48 + srs_freep(listener);
45 } 49 }
46 50
47 -SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax) 51 +int SrsRtpConn::port()
  52 +{
  53 + return _port;
  54 +}
  55 +
  56 +int SrsRtpConn::listen()
  57 +{
  58 + return listener->listen();
  59 +}
  60 +
  61 +int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
  62 +{
  63 + int ret = ERROR_SUCCESS;
  64 + return ret;
  65 +}
  66 +
  67 +SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o)
48 { 68 {
49 output = o; 69 output = o;
50 - local_port_min = lpmin;  
51 - local_port_max = lpmax;  
52 70
53 session = "O9EaZ4bf"; // TODO: FIXME: generate session id. 71 session = "O9EaZ4bf"; // TODO: FIXME: generate session id.
  72 + video_rtp = NULL;
  73 + audio_rtp = NULL;
54 74
55 caster = c; 75 caster = c;
56 stfd = fd; 76 stfd = fd;
@@ -64,6 +84,9 @@ SrsRtspConn::~SrsRtspConn() @@ -64,6 +84,9 @@ SrsRtspConn::~SrsRtspConn()
64 srs_close_stfd(stfd); 84 srs_close_stfd(stfd);
65 trd->stop(); 85 trd->stop();
66 86
  87 + srs_freep(video_rtp);
  88 + srs_freep(audio_rtp);
  89 +
67 srs_freep(trd); 90 srs_freep(trd);
68 srs_freep(skt); 91 srs_freep(skt);
69 srs_freep(rtsp); 92 srs_freep(rtsp);
@@ -103,6 +126,8 @@ int SrsRtspConn::do_cycle() @@ -103,6 +126,8 @@ int SrsRtspConn::do_cycle()
103 } 126 }
104 } else if (req->is_announce()) { 127 } else if (req->is_announce()) {
105 srs_assert(req->sdp); 128 srs_assert(req->sdp);
  129 + video_id = req->sdp->video_stream_id;
  130 + audio_id = req->sdp->audio_stream_id;
106 sps = req->sdp->video_sps; 131 sps = req->sdp->video_sps;
107 pps = req->sdp->video_pps; 132 pps = req->sdp->video_pps;
108 asc = req->sdp->audio_sh; 133 asc = req->sdp->audio_sh;
@@ -119,11 +144,31 @@ int SrsRtspConn::do_cycle() @@ -119,11 +144,31 @@ int SrsRtspConn::do_cycle()
119 } 144 }
120 } else if (req->is_setup()) { 145 } else if (req->is_setup()) {
121 srs_assert(req->transport); 146 srs_assert(req->transport);
  147 + int lpm = 0;
  148 + if ((ret = caster->alloc_port(&lpm)) != ERROR_SUCCESS) {
  149 + srs_error("rtsp: alloc port failed. ret=%d", ret);
  150 + return ret;
  151 + }
  152 +
  153 + SrsRtpConn* rtp = NULL;
  154 + if (req->stream_id == video_id) {
  155 + srs_freep(video_rtp);
  156 + rtp = video_rtp = new SrsRtpConn(this, lpm);
  157 + } else {
  158 + srs_freep(audio_rtp);
  159 + rtp = audio_rtp = new SrsRtpConn(this, lpm);
  160 + }
  161 + if ((ret = rtp->listen()) != ERROR_SUCCESS) {
  162 + srs_error("rtsp: rtp listen at port=%d failed. ret=%d", lpm, ret);
  163 + return ret;
  164 + }
  165 + srs_trace("rtsp: rtp listen at port=%d ok.", lpm);
  166 +
122 SrsRtspSetupResponse* res = new SrsRtspSetupResponse(req->seq); 167 SrsRtspSetupResponse* res = new SrsRtspSetupResponse(req->seq);
123 res->client_port_min = req->transport->client_port_min; 168 res->client_port_min = req->transport->client_port_min;
124 res->client_port_max = req->transport->client_port_max; 169 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; 170 + res->local_port_min = lpm;
  171 + res->local_port_max = lpm + 1;
127 res->session = session; 172 res->session = session;
128 if ((ret = rtsp->send_message(res)) != ERROR_SUCCESS) { 173 if ((ret = rtsp->send_message(res)) != ERROR_SUCCESS) {
129 if (!srs_is_client_gracefully_close(ret)) { 174 if (!srs_is_client_gracefully_close(ret)) {
@@ -165,6 +210,14 @@ int SrsRtspConn::cycle() @@ -165,6 +210,14 @@ int SrsRtspConn::cycle()
165 210
166 void SrsRtspConn::on_thread_stop() 211 void SrsRtspConn::on_thread_stop()
167 { 212 {
  213 + if (video_rtp) {
  214 + caster->free_port(video_rtp->port(), video_rtp->port() + 1);
  215 + }
  216 +
  217 + if (audio_rtp) {
  218 + caster->free_port(audio_rtp->port(), audio_rtp->port() + 1);
  219 + }
  220 +
168 caster->remove(this); 221 caster->remove(this);
169 } 222 }
170 223
@@ -184,16 +237,40 @@ SrsRtspCaster::~SrsRtspCaster() @@ -184,16 +237,40 @@ SrsRtspCaster::~SrsRtspCaster()
184 srs_freep(conn); 237 srs_freep(conn);
185 } 238 }
186 clients.clear(); 239 clients.clear();
  240 + used_ports.clear();
187 } 241 }
188 242
189 -int SrsRtspCaster::serve_client(st_netfd_t stfd) 243 +int SrsRtspCaster::alloc_port(int* pport)
190 { 244 {
191 int ret = ERROR_SUCCESS; 245 int ret = ERROR_SUCCESS;
192 246
193 - SrsRtspConn* conn = new SrsRtspConn(  
194 - this, stfd,  
195 - output, local_port_min, local_port_max  
196 - ); 247 + // use a pair of port.
  248 + for (int i = local_port_min; i < local_port_max - 1; i += 2) {
  249 + if (!used_ports[i]) {
  250 + used_ports[i] = true;
  251 + used_ports[i + 1] = true;
  252 + *pport = i;
  253 + break;
  254 + }
  255 + }
  256 + srs_info("rtsp: alloc port=%d-%d", *pport, *pport + 1);
  257 +
  258 + return ret;
  259 +}
  260 +
  261 +void SrsRtspCaster::free_port(int lpmin, int lpmax)
  262 +{
  263 + for (int i = lpmin; i < lpmax; i++) {
  264 + used_ports[i] = false;
  265 + }
  266 + srs_trace("rtsp: free rtp port=%d-%d", lpmin, lpmax);
  267 +}
  268 +
  269 +int SrsRtspCaster::on_tcp_client(st_netfd_t stfd)
  270 +{
  271 + int ret = ERROR_SUCCESS;
  272 +
  273 + SrsRtspConn* conn = new SrsRtspConn(this, stfd, output);
197 274
198 if ((ret = conn->serve()) != ERROR_SUCCESS) { 275 if ((ret = conn->serve()) != ERROR_SUCCESS) {
199 srs_error("rtsp: serve client failed. ret=%d", ret); 276 srs_error("rtsp: serve client failed. ret=%d", ret);
@@ -32,30 +32,38 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -32,30 +32,38 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 32
33 #include <string> 33 #include <string>
34 #include <vector> 34 #include <vector>
  35 +#include <map>
35 36
36 #include <srs_app_st.hpp> 37 #include <srs_app_st.hpp>
37 #include <srs_app_thread.hpp> 38 #include <srs_app_thread.hpp>
  39 +#include <srs_app_listener.hpp>
38 40
39 #ifdef SRS_AUTO_STREAM_CASTER 41 #ifdef SRS_AUTO_STREAM_CASTER
40 42
41 -class SrsConfDirective;  
42 class SrsStSocket; 43 class SrsStSocket;
  44 +class SrsRtspConn;
43 class SrsRtspStack; 45 class SrsRtspStack;
44 class SrsRtspCaster; 46 class SrsRtspCaster;
  47 +class SrsConfDirective;
45 48
46 /** 49 /**
47 -* the handler for rtsp handler. 50 +* a rtp connection which transport a stream.
48 */ 51 */
49 -class ISrsRtspHandler 52 +class SrsRtpConn: public ISrsUdpHandler
50 { 53 {
  54 +private:
  55 + SrsUdpListener* listener;
  56 + SrsRtspConn* rtsp;
  57 + int _port;
51 public: 58 public:
52 - ISrsRtspHandler();  
53 - virtual ~ISrsRtspHandler(); 59 + SrsRtpConn(SrsRtspConn* r, int p);
  60 + virtual ~SrsRtpConn();
54 public: 61 public:
55 - /**  
56 - * serve the rtsp connection.  
57 - */  
58 - virtual int serve_client(st_netfd_t stfd) = 0; 62 + virtual int port();
  63 + virtual int listen();
  64 +// interface ISrsUdpHandler
  65 +public:
  66 + virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf);
59 }; 67 };
60 68
61 /** 69 /**
@@ -65,10 +73,14 @@ class SrsRtspConn : public ISrsThreadHandler @@ -65,10 +73,14 @@ class SrsRtspConn : public ISrsThreadHandler
65 { 73 {
66 private: 74 private:
67 std::string output; 75 std::string output;
68 - int local_port_min;  
69 - int local_port_max;  
70 private: 76 private:
71 std::string session; 77 std::string session;
  78 + // video stream.
  79 + std::string video_id;
  80 + SrsRtpConn* video_rtp;
  81 + // audio stream.
  82 + std::string audio_id;
  83 + SrsRtpConn* audio_rtp;
72 // video sequence header. 84 // video sequence header.
73 std::string sps; 85 std::string sps;
74 std::string pps; 86 std::string pps;
@@ -81,7 +93,7 @@ private: @@ -81,7 +93,7 @@ private:
81 SrsRtspCaster* caster; 93 SrsRtspCaster* caster;
82 SrsThread* trd; 94 SrsThread* trd;
83 public: 95 public:
84 - SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o, int lpmin, int lpmax); 96 + SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o);
85 virtual ~SrsRtspConn(); 97 virtual ~SrsRtspConn();
86 public: 98 public:
87 virtual int serve(); 99 virtual int serve();
@@ -96,19 +108,32 @@ public: @@ -96,19 +108,32 @@ public:
96 /** 108 /**
97 * the caster for rtsp. 109 * the caster for rtsp.
98 */ 110 */
99 -class SrsRtspCaster : public ISrsRtspHandler 111 +class SrsRtspCaster : public ISrsTcpHandler
100 { 112 {
101 private: 113 private:
102 std::string output; 114 std::string output;
103 int local_port_min; 115 int local_port_min;
104 int local_port_max; 116 int local_port_max;
  117 + // key: port, value: whether used.
  118 + std::map<int, bool> used_ports;
105 private: 119 private:
106 std::vector<SrsRtspConn*> clients; 120 std::vector<SrsRtspConn*> clients;
107 public: 121 public:
108 SrsRtspCaster(SrsConfDirective* c); 122 SrsRtspCaster(SrsConfDirective* c);
109 virtual ~SrsRtspCaster(); 123 virtual ~SrsRtspCaster();
110 public: 124 public:
111 - virtual int serve_client(st_netfd_t stfd); 125 + /**
  126 + * alloc a rtp port from local ports pool.
  127 + * @param pport output the rtp port.
  128 + */
  129 + virtual int alloc_port(int* pport);
  130 + /**
  131 + * free the alloced rtp port.
  132 + */
  133 + virtual void free_port(int lpmin, int lpmax);
  134 +// interface ISrsTcpHandler
  135 +public:
  136 + virtual int on_tcp_client(st_netfd_t stfd);
112 // internal methods. 137 // internal methods.
113 public: 138 public:
114 virtual void remove(SrsRtspConn* conn); 139 virtual void remove(SrsRtspConn* conn);
@@ -220,7 +220,7 @@ int SrsRtspListener::on_tcp_client(st_netfd_t stfd) @@ -220,7 +220,7 @@ int SrsRtspListener::on_tcp_client(st_netfd_t stfd)
220 { 220 {
221 int ret = ERROR_SUCCESS; 221 int ret = ERROR_SUCCESS;
222 222
223 - if ((ret = caster->serve_client(stfd)) != ERROR_SUCCESS) { 223 + if ((ret = caster->on_tcp_client(stfd)) != ERROR_SUCCESS) {
224 srs_warn("accept client error. ret=%d", ret); 224 srs_warn("accept client error. ret=%d", ret);
225 return ret; 225 return ret;
226 } 226 }
@@ -47,8 +47,8 @@ class SrsIngester; @@ -47,8 +47,8 @@ class SrsIngester;
47 class SrsHttpHeartbeat; 47 class SrsHttpHeartbeat;
48 class SrsKbps; 48 class SrsKbps;
49 class SrsConfDirective; 49 class SrsConfDirective;
  50 +class ISrsTcpHandler;
50 class ISrsUdpHandler; 51 class ISrsUdpHandler;
51 -class ISrsRtspHandler;  
52 class SrsUdpListener; 52 class SrsUdpListener;
53 class SrsTcpListener; 53 class SrsTcpListener;
54 54
@@ -111,8 +111,7 @@ class SrsRtspListener : virtual public SrsListener, virtual public ISrsTcpHandle @@ -111,8 +111,7 @@ class SrsRtspListener : virtual public SrsListener, virtual public ISrsTcpHandle
111 { 111 {
112 private: 112 private:
113 SrsTcpListener* listener; 113 SrsTcpListener* listener;
114 -private:  
115 - ISrsRtspHandler* caster; 114 + ISrsTcpHandler* caster;
116 public: 115 public:
117 SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); 116 SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);
118 virtual ~SrsRtspListener(); 117 virtual ~SrsRtspListener();
@@ -62,6 +62,7 @@ SrsThread::SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_ @@ -62,6 +62,7 @@ SrsThread::SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_
62 62
63 tid = NULL; 63 tid = NULL;
64 loop = false; 64 loop = false;
  65 + really_terminated = true;
65 _cid = -1; 66 _cid = -1;
66 _joinable = joinable; 67 _joinable = joinable;
67 68
@@ -120,10 +121,27 @@ void SrsThread::stop() @@ -120,10 +121,27 @@ void SrsThread::stop()
120 // which will terminate the cycle thread. 121 // which will terminate the cycle thread.
121 st_thread_interrupt(tid); 122 st_thread_interrupt(tid);
122 123
  124 + // when joinable, wait util quit.
  125 + if (_joinable) {
123 // wait the thread to exit. 126 // wait the thread to exit.
124 int ret = st_thread_join(tid, NULL); 127 int ret = st_thread_join(tid, NULL);
125 - // TODO: FIXME: the join maybe failed, should use a variable to ensure thread terminated.  
126 - srs_assert(ret == 0); 128 + if (ret) {
  129 + srs_warn("core: ignore join thread failed.");
  130 + }
  131 +
  132 + // wait the thread actually terminated.
  133 + // sometimes the thread join return -1, for example,
  134 + // when thread use st_recvfrom, the thread join return -1.
  135 + // so here, we use a variable to ensure the thread stopped.
  136 + while (!really_terminated) {
  137 + st_usleep(10 * 1000);
  138 +
  139 + if (really_terminated) {
  140 + break;
  141 + }
  142 + srs_warn("core: wait thread to actually terminated");
  143 + }
  144 + }
127 145
128 tid = NULL; 146 tid = NULL;
129 } 147 }
@@ -151,6 +169,9 @@ void SrsThread::thread_cycle() @@ -151,6 +169,9 @@ void SrsThread::thread_cycle()
151 srs_assert(handler); 169 srs_assert(handler);
152 handler->on_thread_start(); 170 handler->on_thread_start();
153 171
  172 + // thread is running now.
  173 + really_terminated = false;
  174 +
154 // wait for cid to ready, for parent thread to get the cid. 175 // wait for cid to ready, for parent thread to get the cid.
155 while (!can_run && loop) { 176 while (!can_run && loop) {
156 st_usleep(10 * 1000); 177 st_usleep(10 * 1000);
@@ -191,6 +212,9 @@ failed: @@ -191,6 +212,9 @@ failed:
191 212
192 handler->on_thread_stop(); 213 handler->on_thread_stop();
193 srs_info("thread %s cycle finished", _name); 214 srs_info("thread %s cycle finished", _name);
  215 +
  216 + // readly terminated now.
  217 + really_terminated = true;
194 } 218 }
195 219
196 void* SrsThread::thread_fun(void* arg) 220 void* SrsThread::thread_fun(void* arg)
@@ -143,6 +143,7 @@ private: @@ -143,6 +143,7 @@ private:
143 int _cid; 143 int _cid;
144 bool loop; 144 bool loop;
145 bool can_run; 145 bool can_run;
  146 + bool really_terminated;
146 bool _joinable; 147 bool _joinable;
147 const char* _name; 148 const char* _name;
148 private: 149 private:
@@ -746,6 +746,18 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req) @@ -746,6 +746,18 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
746 } 746 }
747 } 747 }
748 748
  749 + // for setup, parse the stream id from uri.
  750 + if (req->is_setup()) {
  751 + size_t pos = string::npos;
  752 + if ((pos = req->uri.rfind("/")) != string::npos) {
  753 + req->stream_id = req->uri.substr(pos + 1);
  754 + }
  755 + if ((pos = req->stream_id.find("=")) != string::npos) {
  756 + req->stream_id = req->stream_id.substr(pos + 1);
  757 + }
  758 + srs_info("rtsp: setup stream id=%s", req->stream_id.c_str());
  759 + }
  760 +
749 // parse rdp body. 761 // parse rdp body.
750 long consumed = 0; 762 long consumed = 0;
751 while (consumed < req->content_length) { 763 while (consumed < req->content_length) {
@@ -337,6 +337,7 @@ public: @@ -337,6 +337,7 @@ public:
337 * assumed. It is interpreted according to [H14.14]. 337 * assumed. It is interpreted according to [H14.14].
338 */ 338 */
339 long content_length; 339 long content_length;
  340 +
340 /** 341 /**
341 * the sdp in announce, NULL for no sdp. 342 * the sdp in announce, NULL for no sdp.
342 */ 343 */
@@ -345,6 +346,10 @@ public: @@ -345,6 +346,10 @@ public:
345 * the transport in setup, NULL for no transport. 346 * the transport in setup, NULL for no transport.
346 */ 347 */
347 SrsRtspTransport* transport; 348 SrsRtspTransport* transport;
  349 + /**
  350 + * for setup message, parse the stream id from uri.
  351 + */
  352 + std::string stream_id;
348 public: 353 public:
349 SrsRtspRequest(); 354 SrsRtspRequest();
350 virtual ~SrsRtspRequest(); 355 virtual ~SrsRtspRequest();