diff --git a/src/controller/controller_capabilities.cpp b/src/controller/controller_capabilities.cpp index 1b4382fe..319b9779 100644 --- a/src/controller/controller_capabilities.cpp +++ b/src/controller/controller_capabilities.cpp @@ -125,6 +125,16 @@ namespace Controller{ "If non-empty, overrides the full RTMP url to the response value. If empty, denies the " "incoming RTMP push."; + trgs["PUSH_REWRITE"]["when"] = + "On all incoming pushes on any protocol, allows parsing the push URL to/from custom formatting to an internal stream name"; + trgs["PUSH_REWRITE"]["stream_specific"] = false; + trgs["PUSH_REWRITE"]["payload"] = + "full current push url (string)\nconnection hostname (string)\ncurrently parsed stream name (string)"; + trgs["PUSH_REWRITE"]["response"] = "when-blocking"; + trgs["PUSH_REWRITE"]["response_action"] = + "If non-empty, overrides the parsed stream name to the response value. If empty, denies the " + "incoming push."; + trgs["PUSH_OUT_START"]["when"] = "Before a push out (to file or other target type) is started"; trgs["PUSH_OUT_START"]["stream_specific"] = true; trgs["PUSH_OUT_START"]["payload"] = "stream name (string)\npush target (string)"; diff --git a/src/output/output_dtsc.cpp b/src/output/output_dtsc.cpp index d8abd71f..45ec0f36 100644 --- a/src/output/output_dtsc.cpp +++ b/src/output/output_dtsc.cpp @@ -295,7 +295,13 @@ namespace Mist{ void OutDTSC::handlePlay(DTSC::Scan &dScan){ streamName = dScan.getMember("stream").asString(); Util::sanitizeName(streamName); - Util::streamName = streamName; + Util::setStreamName(streamName); + HTTP::URL qUrl; + qUrl.protocol = "dtsc"; + qUrl.host = myConn.getBoundAddress(); + qUrl.port = config->getOption("port").asString(); + qUrl.path = streamName; + reqUrl = qUrl.getUrl(); parseData = true; INFO_MSG("Handled play for stream %s", streamName.c_str()); setBlocking(false); @@ -305,7 +311,32 @@ namespace Mist{ streamName = dScan.getMember("stream").asString(); std::string passString = dScan.getMember("password").asString(); Util::sanitizeName(streamName); - Util::streamName = streamName; + Util::setStreamName(streamName); + HTTP::URL qUrl; + qUrl.protocol = "dtsc"; + qUrl.host = myConn.getBoundAddress(); + qUrl.port = config->getOption("port").asString(); + qUrl.path = streamName; + qUrl.pass = passString; + reqUrl = qUrl.getUrl(); + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = reqUrl + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + Util::logExitReason( + "Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + onFail("Push not allowed - rejected by trigger"); + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } if (!allowPush(passString)){ onFail("Push not allowed - stream and/or password incorrect", true); return; diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index 8a1c3bd1..47ebe400 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -234,7 +235,12 @@ namespace Mist{ } /*LTS-START*/ - reqUrl = H.url + H.allVars(); + { + HTTP::URL qUrl("http://"+H.GetHeader("Host")+"/"+H.url + H.allVars()); + if (!qUrl.host.size()){qUrl.host = myConn.getBoundAddress();} + if (!qUrl.port.size() && config->hasOption("port")){qUrl.port = config->getOption("port").asString();} + reqUrl = qUrl.getUrl(); + } /*LTS-END*/ if (H.hasHeader("User-Agent")){UA = H.GetHeader("User-Agent");} if (hasSessionIDs()){ diff --git a/src/output/output_json.cpp b/src/output/output_json.cpp index ef126e89..2737e7ce 100644 --- a/src/output/output_json.cpp +++ b/src/output/output_json.cpp @@ -1,6 +1,7 @@ #include "output_json.h" #include #include +#include namespace Mist{ OutJSON::OutJSON(Socket::Connection &conn) : HTTPOutput(conn){ @@ -150,6 +151,21 @@ namespace Mist{ void OutJSON::onWebsocketFrame(){ if (!isPushing()){ + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = reqUrl + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + onFinish(); + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } if (!allowPush(pushPass)){ onFinish(); return; diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp index 5c26f5a0..f433ff99 100644 --- a/src/output/output_rtmp.cpp +++ b/src/output/output_rtmp.cpp @@ -876,6 +876,25 @@ namespace Mist{ Util::sanitizeName(streamName); + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = reqUrl + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + Util::logExitReason( + "Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + onFinish(); + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } + if (!allowPush(app_name)){ onFinish(); return; diff --git a/src/output/output_rtsp.cpp b/src/output/output_rtsp.cpp index 4acd29fc..8e09c10a 100644 --- a/src/output/output_rtsp.cpp +++ b/src/output/output_rtsp.cpp @@ -431,6 +431,27 @@ namespace Mist{ continue; } if (HTTP_R.method == "ANNOUNCE"){ + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + HTTP::URL qUrl("rtsp://"+HTTP_R.GetHeader("Host")+"/"+HTTP_R.url); + if (!qUrl.host.size()){qUrl.host = myConn.getBoundAddress();} + if (!qUrl.port.size()){qUrl.port = config->getOption("port").asString();} + std::string payload = qUrl.getUrl() + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), qUrl.getUrl().c_str()); + Util::logExitReason( + "Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), qUrl.getUrl().c_str()); + onFinish(); + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } if (!allowPush(HTTP_R.GetVar("pass"))){ onFinish(); return; diff --git a/src/output/output_ts.cpp b/src/output/output_ts.cpp index efcc643c..f3ef6c8b 100644 --- a/src/output/output_ts.cpp +++ b/src/output/output_ts.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include namespace Mist{ OutTS::OutTS(Socket::Connection &conn) : TSOutput(conn){ @@ -48,6 +50,21 @@ namespace Mist{ wantRequest = pushing; parseData = !pushing; if (pushing){ + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = "ts-tcp://" + myConn.getBoundAddress() + ":" + config->getOption("port").asString() + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + config->is_active = false; + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } if (!allowPush("")){ FAIL_MSG("Pushing not allowed"); config->is_active = false; @@ -164,6 +181,21 @@ namespace Mist{ } if (parseData){ parseData = false; + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = "ts-tcp://" + myConn.getBoundAddress() + ":" + config->getOption("port").asString() + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = ""; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + onFinish(); + return; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } if (!allowPush("")){ onFinish(); return; diff --git a/src/output/output_tssrt.cpp b/src/output/output_tssrt.cpp index 0abdc09d..32a31f40 100644 --- a/src/output/output_tssrt.cpp +++ b/src/output/output_tssrt.cpp @@ -94,10 +94,10 @@ namespace Mist{ reqUrl.port = config->getString("port"); reqUrl.host = config->getString("interface"); reqUrl.args = "streamid="+Encodings::URL::encode(sName); - std::string payload = reqUrl.getUrl() + "\n" + getConnectedHost(); - std::string newUrl = ""; - Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newUrl); - if (!newUrl.size()){ + std::string payload = reqUrl.getUrl() + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", getConnectedHost().c_str(), reqUrl.getUrl().c_str()); Util::logExitReason( @@ -105,16 +105,9 @@ namespace Mist{ getConnectedHost().c_str(), reqUrl.getUrl().c_str()); onFinish(); return; - } - reqUrl = HTTP::URL(newUrl); - if (reqUrl.args.size()){ - std::map args; - HTTP::parseVars(reqUrl.args, args); - if (args.count("streamid")){ - streamName = args["streamid"]; - Util::sanitizeName(streamName); - Util::setStreamName(streamName); - } + }else{ + streamName = newStream; + Util::sanitizeName(streamName); } } myConn.setHost(srtConn.remotehost); diff --git a/src/output/output_webrtc.cpp b/src/output/output_webrtc.cpp index 2dbd4de1..35a337f5 100644 --- a/src/output/output_webrtc.cpp +++ b/src/output/output_webrtc.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include // ifaddr, listing ip addresses. #include @@ -820,6 +822,22 @@ namespace Mist{ } } + + if (Triggers::shouldTrigger("PUSH_REWRITE")){ + std::string payload = reqUrl + "\n" + getConnectedHost() + "\n" + streamName; + std::string newStream = streamName; + Triggers::doTrigger("PUSH_REWRITE", payload, "", false, newStream); + if (!newStream.size()){ + FAIL_MSG("Push from %s to URL %s rejected - PUSH_REWRITE trigger blanked the URL", + getConnectedHost().c_str(), reqUrl.c_str()); + return false; + }else{ + streamName = newStream; + Util::sanitizeName(streamName); + Util::setStreamName(streamName); + } + } + // allow peer to push video/audio if (!allowPush("")){ FAIL_MSG("Failed to allow push");