diff --git a/trunk/src/app/srs_app_edge.cpp b/trunk/src/app/srs_app_edge.cpp index 20b0b39ed..9cdbaf5c4 100644 --- a/trunk/src/app/srs_app_edge.cpp +++ b/trunk/src/app/srs_app_edge.cpp @@ -183,6 +183,7 @@ SrsEdgeFlvUpstream::SrsEdgeFlvUpstream(std::string schema) hr_ = NULL; reader_ = NULL; decoder_ = NULL; + req_ = NULL; } SrsEdgeFlvUpstream::~SrsEdgeFlvUpstream() @@ -191,12 +192,24 @@ SrsEdgeFlvUpstream::~SrsEdgeFlvUpstream() } srs_error_t SrsEdgeFlvUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb) +{ + // Because we might modify the r, which cause retry fail, so we must copy it. + SrsRequest* cp = r->copy(); + + // Free the request when close upstream. + srs_freep(req_); + req_ = cp; + + return do_connect(cp, lb, 0); +} + +srs_error_t SrsEdgeFlvUpstream::do_connect(SrsRequest* r, SrsLbRoundRobin* lb, int redirect_depth) { srs_error_t err = srs_success; SrsRequest* req = r; - if (true) { + if (redirect_depth == 0) { SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(req->vhost); // @see https://github.com/ossrs/srs/issues/79 @@ -217,12 +230,20 @@ srs_error_t SrsEdgeFlvUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb) // Remember the current selected server. selected_ip = server; selected_port = port; + } else { + // If HTTP redirect, use the server in location. + schema_ = req->schema; + selected_ip = req->host; + selected_port = req->port; } srs_freep(sdk_); sdk_ = new SrsHttpClient(); - string path = "/" + req->app + "/" + req->stream + ".flv"; + string path = "/" + req->app + "/" + req->stream; + if (!srs_string_ends_with(req->stream, ".flv")) { + path += ".flv"; + } if (!req->param.empty()) { path += req->param; } @@ -240,7 +261,36 @@ srs_error_t SrsEdgeFlvUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb) return srs_error_wrap(err, "edge get %s failed, path=%s", url.c_str(), path.c_str()); } - srs_trace("Edge: Connect to %s ok", url.c_str()); + if (hr_->status_code() == 404) { + return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "Connect to %s, status=%d", url.c_str(), hr_->status_code()); + } + + string location; + if (hr_->status_code() == 302) { + location = hr_->header()->get("Location"); + } + srs_trace("Edge: Connect to %s ok, status=%d, location=%s", url.c_str(), hr_->status_code(), location.c_str()); + + if (hr_->status_code() == 302) { + if (redirect_depth >= 3) { + return srs_error_new(ERROR_HTTP_302_INVALID, "redirect to %s fail, depth=%d", location.c_str(), redirect_depth); + } + + string app; + string stream_name; + if (true) { + string tcUrl; + srs_parse_rtmp_url(location, tcUrl, stream_name); + + int port; + string schema, host, vhost, param; + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream_name, port, param); + + r->schema = schema; r->host = host; r->port = port; + r->app = app; r->stream = stream_name; r->param = param; + } + return do_connect(r, lb, redirect_depth + 1); + } srs_freep(reader_); reader_ = new SrsHttpFileReader(hr_->body_reader()); @@ -332,6 +382,7 @@ void SrsEdgeFlvUpstream::close() srs_freep(hr_); srs_freep(reader_); srs_freep(decoder_); + srs_freep(req_); } void SrsEdgeFlvUpstream::selected(string& server, int& port) diff --git a/trunk/src/app/srs_app_edge.hpp b/trunk/src/app/srs_app_edge.hpp index 80d9a1b31..6c50814d2 100644 --- a/trunk/src/app/srs_app_edge.hpp +++ b/trunk/src/app/srs_app_edge.hpp @@ -127,6 +127,8 @@ private: SrsHttpFileReader* reader_; SrsFlvDecoder* decoder_; private: + // We might modify the request by HTTP redirect. + SrsRequest* req_; // Current selected server, the ip:port. std::string selected_ip; int selected_port; @@ -135,6 +137,9 @@ public: virtual ~SrsEdgeFlvUpstream(); public: virtual srs_error_t connect(SrsRequest* r, SrsLbRoundRobin* lb); +private: + virtual srs_error_t do_connect(SrsRequest* r, SrsLbRoundRobin* lb, int redirect_depth); +public: virtual srs_error_t recv_message(SrsCommonMessage** pmsg); virtual srs_error_t decode_message(SrsCommonMessage* msg, SrsPacket** ppacket); virtual void close(); diff --git a/trunk/src/protocol/srs_protocol_utility.cpp b/trunk/src/protocol/srs_protocol_utility.cpp index ece4ef0bc..6b61aceb5 100644 --- a/trunk/src/protocol/srs_protocol_utility.cpp +++ b/trunk/src/protocol/srs_protocol_utility.cpp @@ -106,6 +106,10 @@ void srs_discovery_tc_url(string tcUrl, string& schema, string& host, string& vh } port = SRS_CONSTS_RTMP_DEFAULT_PORT; + if (schema == "https") { + port = SRS_DEFAULT_HTTPS_PORT; + } + if ((pos = host.find(":")) != std::string::npos) { srs_parse_hostport(host, host, port); srs_info("discovery host=%s, port=%d", host.c_str(), port);