正在显示
17 个修改的文件
包含
864 行增加
和
288 行删除
| @@ -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 | /** |
trunk/src/app/srs_app_listener.cpp
0 → 100644
| 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 | + |
trunk/src/app/srs_app_listener.hpp
0 → 100644
| 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,81 +125,44 @@ SrsListenerType SrsListener::type() | @@ -149,81 +125,44 @@ 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) |
| 153 | { | 129 | { |
| 154 | - int ret = ERROR_SUCCESS; | ||
| 155 | - | ||
| 156 | - _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); | 130 | + listener = NULL; |
| 131 | +} | ||
| 164 | 132 | ||
| 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); | 133 | +SrsStreamListener::~SrsStreamListener() |
| 134 | +{ | ||
| 135 | + srs_freep(listener); | ||
| 136 | +} | ||
| 172 | 137 | ||
| 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); | 138 | +int SrsStreamListener::listen(int port) |
| 139 | +{ | ||
| 140 | + int ret = ERROR_SUCCESS; | ||
| 183 | 141 | ||
| 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); | 142 | + _port = port; |
| 190 | 143 | ||
| 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); | 144 | + srs_freep(listener); |
| 145 | + listener = new SrsTcpListener(this, port); | ||
| 197 | 146 | ||
| 198 | - if ((ret = pthread->start()) != ERROR_SUCCESS) { | ||
| 199 | - srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret); | 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); | 156 | + srs_trace("%s listen at tcp://%d, fd=%d", __srs_listener_type2string(_type).c_str(), _port, listener->fd()); |
| 209 | 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 | } |
| @@ -234,7 +173,7 @@ int SrsListener::cycle() | @@ -234,7 +173,7 @@ int SrsListener::cycle() | ||
| 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,22 +186,41 @@ SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsCon | @@ -247,22 +186,41 @@ 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; |
| 255 | 195 | ||
| 256 | - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); | 196 | + // the caller already ensure the type is ok, |
| 197 | + // we just assert here for unknown stream caster. | ||
| 198 | + srs_assert(_type == SrsListenerRtsp); | ||
| 199 | + | ||
| 200 | + _port = port; | ||
| 201 | + | ||
| 202 | + srs_freep(listener); | ||
| 203 | + listener = new SrsTcpListener(this, port); | ||
| 257 | 204 | ||
| 258 | - if(client_stfd == NULL){ | ||
| 259 | - // ignore error. | ||
| 260 | - srs_error("ignore accept thread stoppped for accept client error"); | 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 | } |
| @@ -270,11 +228,10 @@ int SrsRtspListener::cycle() | @@ -270,11 +228,10 @@ int SrsRtspListener::cycle() | ||
| 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 | ||
| @@ -300,82 +257,19 @@ int SrsUdpListener::listen(int port) | @@ -300,82 +257,19 @@ int SrsUdpListener::listen(int port) | ||
| 300 | 257 | ||
| 301 | _port = port; | 258 | _port = port; |
| 302 | 259 | ||
| 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); | 260 | + srs_freep(listener); |
| 261 | + listener = new SrsUdpListener(caster, port); | ||
| 335 | 262 | ||
| 336 | - if ((ret = pthread->start()) != ERROR_SUCCESS) { | ||
| 337 | - srs_error("st_thread_create listen thread error. port=%d, ret=%d", port, ret); | 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 | +} | ||
| 494 | 579 | ||
| 495 | - return ss; | 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 | +} | ||
| 589 | + | ||
| 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 | /** |
-
请 注册 或 登录 后发表评论