From 251dc5f171fd5e6e56b2336f0be6701fd53a5ca4 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 13 Nov 2018 16:34:30 +0100 Subject: [PATCH] Better onFail handling, better HTTP failure handling --- src/output/output.cpp | 43 ++++++++++------------------- src/output/output.h | 2 +- src/output/output_hls.cpp | 8 ++---- src/output/output_http.cpp | 9 +++--- src/output/output_http.h | 2 +- src/output/output_http_internal.cpp | 7 ++--- src/output/output_http_internal.h | 2 +- src/output/output_json.cpp | 4 +-- src/output/output_json.h | 2 +- 9 files changed, 30 insertions(+), 49 deletions(-) diff --git a/src/output/output.cpp b/src/output/output.cpp index a182207b..60049c71 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -130,8 +130,12 @@ namespace Mist{ /// Called when stream initialization has failed. /// The standard implementation will set isInitialized to false and close the client connection, /// thus causing the process to exit cleanly. - void Output::onFail(){ - MEDIUM_MSG("onFail"); + void Output::onFail(const std::string & msg, bool critical){ + if (critical){ + FAIL_MSG("onFail '%s': %s", streamName.c_str(), msg.c_str()); + }else{ + MEDIUM_MSG("onFail '%s': %s", streamName.c_str(), msg.c_str()); + } isInitialized = false; wantRequest = true; parseData= false; @@ -153,7 +157,7 @@ namespace Mist{ reconnect(); //if the connection failed, fail if (streamName.size() < 1){ - onFail(); + onFail("Could not connect to stream", true); return; } sought = false; @@ -216,14 +220,12 @@ namespace Mist{ if (config->hasOption("noinput") && config->getBool("noinput")){ Util::sanitizeName(streamName); if (!Util::streamAlive(streamName)){ - FAIL_MSG("Stream %s not already active - aborting initialization", streamName.c_str()); - onFail(); + onFail("Stream not active already, aborting"); return; } }else{ if (!Util::startInput(streamName, "", true, isPushing())){ - FAIL_MSG("Opening stream %s failed - aborting initialization", streamName.c_str()); - onFail(); + onFail("Stream open failed", true); return; } } @@ -236,16 +238,14 @@ namespace Mist{ nProxy.userClient = IPC::sharedClient(userPageName, PLAY_EX_SIZE, true); } if (!nProxy.userClient.isAlive()){ - FAIL_MSG("Could not register as client for %s", streamName.c_str()); - onFail(); + onFail("Could not register as client", true); return; } char pageId[NAME_BUFFER_SIZE]; snprintf(pageId, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str()); nProxy.metaPages[0].init(pageId, DEFAULT_STRM_PAGE_SIZE); if (!nProxy.metaPages[0].mapped){ - FAIL_MSG("Could not connect to data for %s", streamName.c_str()); - onFail(); + onFail("Could not connect to stream data", true); return; } isInitialized = true; @@ -1173,12 +1173,7 @@ namespace Mist{ snprintf(userPageName, NAME_BUFFER_SIZE, SHM_USERS, streamName.c_str()); nProxy.userClient = IPC::sharedClient(userPageName, PLAY_EX_SIZE, true); if (!nProxy.userClient.getData()){ - WARN_MSG("Player connection failure - aborting output"); - if (!onFinish()){ - myConn.close(); - }else{ - disconnect(); - } + onFail("Player connection failure - aborting output", true); return; } } @@ -1186,21 +1181,11 @@ namespace Mist{ if (isPushing() && !pushIsOngoing){ waitForStreamPushReady(); if (!nProxy.userClient.isAlive()){ - WARN_MSG("Failed to wait for buffer, aborting incoming push"); - if (!onFinish()){ - myConn.close(); - }else{ - disconnect(); - } + onFail("Failed to wait for buffer, aborting incoming push", true); return; } }else{ - INFO_MSG("Received disconnect request from input"); - if (!onFinish()){ - myConn.close(); - }else{ - disconnect(); - } + onFail("Received disconnect request from input"); return; } } diff --git a/src/output/output.h b/src/output/output.h index cd83b61b..cfe5def3 100644 --- a/src/output/output.h +++ b/src/output/output.h @@ -73,7 +73,7 @@ namespace Mist { void disconnect(); virtual void initialize(); virtual void sendHeader(); - virtual void onFail(); + virtual void onFail(const std::string & msg, bool critical = false); virtual void requestHandler(); static Util::Config * config; void playbackSleep(uint64_t millis); diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp index 35bc7121..1f15082e 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -197,7 +197,7 @@ namespace Mist { } if (H.url.find("hls") == std::string::npos){ - onFail(); + onFail("HLS handler active, but this is not a HLS URL. Eh... What...?"); return; } @@ -213,11 +213,7 @@ namespace Mist { } initialize(); - - if (!keepGoing()){ - onFail(); - return; - } + if (!keepGoing()){return;} if (H.url.find(".m3u") == std::string::npos){ std::string tmpStr = H.getUrl().substr(5 + streamName.size()); diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index 5bd8e435..14bdfa7a 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -39,13 +39,14 @@ namespace Mist { config = cfg; } - void HTTPOutput::onFail(){ + void HTTPOutput::onFail(const std::string & msg, bool critical){ + INFO_MSG("Failing '%s': %s: %s", streamName.c_str(), H.url.c_str(), msg.c_str()); if (!webSock){ H.Clean(); //make sure no parts of old requests are left in any buffers - H.SetBody("Stream not found. Sorry, we tried."); - H.SendResponse("404", "Stream not found", myConn); + H.SetBody("Could not retrieve stream: "+msg); + H.SendResponse("404", "Error opening stream", myConn); } - Output::onFail(); + Output::onFail(msg, critical); } bool isMatch(const std::string & url, const std::string & m, std::string & streamname){ diff --git a/src/output/output_http.h b/src/output/output_http.h index 9cf37718..1418c5a2 100644 --- a/src/output/output_http.h +++ b/src/output/output_http.h @@ -12,7 +12,7 @@ namespace Mist { virtual ~HTTPOutput(); static void init(Util::Config * cfg); void onRequest(); - virtual void onFail(); + virtual void onFail(const std::string & msg, bool critical = false); virtual void onHTTP(){}; virtual void onIdle(){}; virtual void onWebsocketFrame(){}; diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp index a2bdcc62..54cdb0ab 100644 --- a/src/output/output_http_internal.cpp +++ b/src/output/output_http_internal.cpp @@ -60,7 +60,7 @@ namespace Mist { return !(config->getString("ip").size()); } - void OutHTTP::onFail(){ + void OutHTTP::onFail(const std::string & msg, bool critical){ std::string method = H.method; // send logo icon if (H.url.length() > 4 && H.url.substr(H.url.length() - 4, 4) == ".ico"){ @@ -75,6 +75,7 @@ namespace Mist { if (websocketHandler()){return;} JSON::Value json_resp; json_resp["error"] = "Could not retrieve stream. Sorry."; + json_resp["error_guru"] = msg; if (H.url.size() >= 5 && H.url.substr(0, 5) == "/json"){ H.Clean(); H.SetBody(json_resp.toString()); @@ -92,9 +93,7 @@ namespace Mist { H.Clean(); return; } - INFO_MSG("Failing: %s", H.url.c_str()); - HTTPOutput::onFail(); - Output::onFail(); + HTTPOutput::onFail(msg, critical); } void OutHTTP::init(Util::Config * cfg){ diff --git a/src/output/output_http_internal.h b/src/output/output_http_internal.h index 49f37d72..f0342f68 100644 --- a/src/output/output_http_internal.h +++ b/src/output/output_http_internal.h @@ -8,7 +8,7 @@ namespace Mist { ~OutHTTP(); static void init(Util::Config * cfg); static bool listenMode(); - virtual void onFail(); + virtual void onFail(const std::string & msg, bool critical = false); ///preHTTP is disabled in the internal HTTP output, since most don't need the stream alive to work virtual void preHTTP(){}; void HTMLResponse(); diff --git a/src/output/output_json.cpp b/src/output/output_json.cpp index 12345fca..d118da53 100644 --- a/src/output/output_json.cpp +++ b/src/output/output_json.cpp @@ -81,10 +81,10 @@ namespace Mist { sentHeader = true; } - void OutJSON::onFail(){ + void OutJSON::onFail(const std::string & msg, bool critical){ //Only run failure handle if we're not being persistent if (!keepReselecting){ - HTTPOutput::onFail(); + HTTPOutput::onFail(msg, critical); }else{ onFinish(); } diff --git a/src/output/output_json.h b/src/output/output_json.h index 6010d2c5..35fe3ae4 100644 --- a/src/output/output_json.h +++ b/src/output/output_json.h @@ -12,7 +12,7 @@ namespace Mist { virtual void onWebsocketConnect(); virtual void preWebsocketConnect(); bool onFinish(); - void onFail(); + void onFail(const std::string & msg, bool critical = false); void sendNext(); void sendHeader(); bool doesWebsockets(){return true;}