正在显示
7 个修改的文件
包含
86 行增加
和
3 行删除
| @@ -137,7 +137,7 @@ package | @@ -137,7 +137,7 @@ package | ||
| 137 | var ms:NetStream = this.media_stream; | 137 | var ms:NetStream = this.media_stream; |
| 138 | 138 | ||
| 139 | if (!ms) { | 139 | if (!ms) { |
| 140 | - log("stream is null, ignore timer event."); | 140 | + //log("stream is null, ignore timer event."); |
| 141 | return; | 141 | return; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| @@ -395,6 +395,26 @@ package | @@ -395,6 +395,26 @@ package | ||
| 395 | } | 395 | } |
| 396 | update_context_items(); | 396 | update_context_items(); |
| 397 | } | 397 | } |
| 398 | + | ||
| 399 | + // reject by server, maybe redirect. | ||
| 400 | + if (evt.info.code == "NetConnection.Connect.Rejected") { | ||
| 401 | + // RTMP 302 redirect. | ||
| 402 | + if (evt.info.hasOwnProperty("ex") && evt.info.ex.code == 302) { | ||
| 403 | + var streamName:String = url.substr(url.lastIndexOf("/") + 1); | ||
| 404 | + url = evt.info.ex.redirect + "/" + streamName; | ||
| 405 | + log("Async RTMP 302 Redirect to: " + url); | ||
| 406 | + | ||
| 407 | + // notify server. | ||
| 408 | + media_conn.call("Redirected", null, evt.info.ex.redirect); | ||
| 409 | + | ||
| 410 | + // do 302. | ||
| 411 | + setTimeout(function(){ | ||
| 412 | + log("Async RTMP 302 Redirected."); | ||
| 413 | + js_call_play(url, _width, _height, buffer_time, max_buffer_time, volume); | ||
| 414 | + }, 1000); | ||
| 415 | + return; | ||
| 416 | + } | ||
| 417 | + } | ||
| 398 | 418 | ||
| 399 | // TODO: FIXME: failed event. | 419 | // TODO: FIXME: failed event. |
| 400 | if (evt.info.code != "NetConnection.Connect.Success") { | 420 | if (evt.info.code != "NetConnection.Connect.Success") { |
| @@ -26,7 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -26,7 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | bool srs_is_system_control_error(int error_code) | 26 | bool srs_is_system_control_error(int error_code) |
| 27 | { | 27 | { |
| 28 | return error_code == ERROR_CONTROL_RTMP_CLOSE | 28 | return error_code == ERROR_CONTROL_RTMP_CLOSE |
| 29 | - || error_code == ERROR_CONTROL_REPUBLISH; | 29 | + || error_code == ERROR_CONTROL_REPUBLISH |
| 30 | + || error_code == ERROR_CONTROL_REDIRECT; | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | bool srs_is_client_gracefully_close(int error_code) | 33 | bool srs_is_client_gracefully_close(int error_code) |
| @@ -161,6 +161,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -161,6 +161,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 161 | // | 161 | // |
| 162 | // system control message, | 162 | // system control message, |
| 163 | // not an error, but special control logic. | 163 | // not an error, but special control logic. |
| 164 | +// | ||
| 165 | +// connection is redirect to another server. | ||
| 166 | +#define ERROR_CONTROL_REDIRECT 2997 | ||
| 164 | // sys ctl: rtmp close stream, support replay. | 167 | // sys ctl: rtmp close stream, support replay. |
| 165 | #define ERROR_CONTROL_RTMP_CLOSE 2998 | 168 | #define ERROR_CONTROL_RTMP_CLOSE 2998 |
| 166 | // FMLE stop publish and republish. | 169 | // FMLE stop publish and republish. |
| @@ -306,7 +306,9 @@ string srs_generate_rtmp_url(string server, int port, string vhost, string app, | @@ -306,7 +306,9 @@ string srs_generate_rtmp_url(string server, int port, string vhost, string app, | ||
| 306 | ss << "...vhost..." << vhost; | 306 | ss << "...vhost..." << vhost; |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | - ss << "/" << stream; | 309 | + if (!stream.empty()) { |
| 310 | + ss << "/" << stream; | ||
| 311 | + } | ||
| 310 | 312 | ||
| 311 | return ss.str(); | 313 | return ss.str(); |
| 312 | } | 314 | } |
| @@ -2575,6 +2575,57 @@ int SrsRtmpServer::response_connect_app(SrsRequest *req, const char* server_ip) | @@ -2575,6 +2575,57 @@ int SrsRtmpServer::response_connect_app(SrsRequest *req, const char* server_ip) | ||
| 2575 | return ret; | 2575 | return ret; |
| 2576 | } | 2576 | } |
| 2577 | 2577 | ||
| 2578 | +#define SRS_RTMP_REDIRECT_TIMEOUT 3000 | ||
| 2579 | +int SrsRtmpServer::redirect(SrsRequest* r, string host, int port, bool& accepted) | ||
| 2580 | +{ | ||
| 2581 | + int ret = ERROR_SUCCESS; | ||
| 2582 | + | ||
| 2583 | + if (true) { | ||
| 2584 | + string url = srs_generate_rtmp_url(host, port, r->vhost, r->app, ""); | ||
| 2585 | + | ||
| 2586 | + SrsAmf0Object* ex = SrsAmf0Any::object(); | ||
| 2587 | + ex->set("code", SrsAmf0Any::number(302)); | ||
| 2588 | + ex->set("redirect", SrsAmf0Any::str(url.c_str())); | ||
| 2589 | + | ||
| 2590 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 2591 | + | ||
| 2592 | + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelError)); | ||
| 2593 | + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectRejected)); | ||
| 2594 | + pkt->data->set(StatusDescription, SrsAmf0Any::str("RTMP 302 Redirect")); | ||
| 2595 | + pkt->data->set("ex", ex); | ||
| 2596 | + | ||
| 2597 | + if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { | ||
| 2598 | + srs_error("send redirect/rejected message failed. ret=%d", ret); | ||
| 2599 | + return ret; | ||
| 2600 | + } | ||
| 2601 | + srs_info("send redirect/rejected message success."); | ||
| 2602 | + } | ||
| 2603 | + | ||
| 2604 | + // client must response a call message. | ||
| 2605 | + // or we never know whether the client is ok to redirect. | ||
| 2606 | + protocol->set_recv_timeout(SRS_RTMP_REDIRECT_TIMEOUT * 1000); | ||
| 2607 | + if (true) { | ||
| 2608 | + SrsCommonMessage* msg = NULL; | ||
| 2609 | + SrsCallPacket* pkt = NULL; | ||
| 2610 | + if ((ret = expect_message<SrsCallPacket>(&msg, &pkt)) != ERROR_SUCCESS) { | ||
| 2611 | + // ignore any error of redirect response. | ||
| 2612 | + return ERROR_SUCCESS; | ||
| 2613 | + } | ||
| 2614 | + SrsAutoFree(SrsCommonMessage, msg); | ||
| 2615 | + SrsAutoFree(SrsCallPacket, pkt); | ||
| 2616 | + | ||
| 2617 | + string message; | ||
| 2618 | + if (pkt->arguments && pkt->arguments->is_string()) { | ||
| 2619 | + message = pkt->arguments->to_str(); | ||
| 2620 | + srs_info("confirm redirected to %s", message.c_str()); | ||
| 2621 | + accepted = true; | ||
| 2622 | + } | ||
| 2623 | + srs_info("get redirect response message"); | ||
| 2624 | + } | ||
| 2625 | + | ||
| 2626 | + return ret; | ||
| 2627 | +} | ||
| 2628 | + | ||
| 2578 | void SrsRtmpServer::response_connect_reject(SrsRequest* /*req*/, const char* desc) | 2629 | void SrsRtmpServer::response_connect_reject(SrsRequest* /*req*/, const char* desc) |
| 2579 | { | 2630 | { |
| 2580 | int ret = ERROR_SUCCESS; | 2631 | int ret = ERROR_SUCCESS; |
| @@ -930,6 +930,12 @@ public: | @@ -930,6 +930,12 @@ public: | ||
| 930 | */ | 930 | */ |
| 931 | virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL); | 931 | virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL); |
| 932 | /** | 932 | /** |
| 933 | + * redirect the connection to another rtmp server. | ||
| 934 | + * @param the hostname or ip of target. | ||
| 935 | + * @param whether the client accept the redirect. | ||
| 936 | + */ | ||
| 937 | + virtual int redirect(SrsRequest* r, std::string host, int port, bool& accepted); | ||
| 938 | + /** | ||
| 933 | * reject the connect app request. | 939 | * reject the connect app request. |
| 934 | */ | 940 | */ |
| 935 | virtual void response_connect_reject(SrsRequest* req, const char* desc); | 941 | virtual void response_connect_reject(SrsRequest* req, const char* desc); |
-
请 注册 或 登录 后发表评论