Merge branch 'development' into LTS_development

# Conflicts:
#	src/output/output_http_internal.cpp
This commit is contained in:
Thulinma 2018-11-13 16:35:12 +01:00
commit 109995809d
13 changed files with 85 additions and 73 deletions

View file

@ -607,37 +607,51 @@ bool JSON::Value::operator!=(const JSON::Value & rhs) const {
}
bool JSON::Value::compareExcept(const Value & rhs, const std::set<std::string> & skip) const {
if (myType != OBJECT) {
return ((*this) == rhs);
}
jsonForEachConst(*this, it){
if (skip.count(it.key())){continue;}
if (!rhs.isMember(it.key()) || !(*it).compareExcept(rhs[it.key()], skip)) {
return false;
if (myType == OBJECT) {
jsonForEachConst(*this, it){
if (skip.count(it.key())){continue;}
if (!rhs.isMember(it.key()) || !(*it).compareExcept(rhs[it.key()], skip)) {
return false;
}
}
jsonForEachConst(rhs, it){
if (skip.count(it.key())){continue;}
if (!(*this).isMember(it.key())){return false;}
}
return true;
}
jsonForEachConst(rhs, it){
if (skip.count(it.key())){continue;}
if (!(*this).isMember(it.key())){return false;}
if (myType == ARRAY) {
if (size() != rhs.size()){return false;}
jsonForEachConst(*this, it){
if (!(*it).compareExcept(rhs[it.num()], skip)){return false;}
}
return true;
}
return true;
return ((*this) == rhs);
}
bool JSON::Value::compareOnly(const Value & rhs, const std::set<std::string> & check) const {
if (myType != OBJECT) {
return ((*this) == rhs);
}
jsonForEachConst(*this, it){
if (!check.count(it.key())){continue;}
if (!rhs.isMember(it.key()) || !(*it).compareOnly(rhs[it.key()], check)) {
return false;
if (myType == OBJECT) {
jsonForEachConst(*this, it){
if (!check.count(it.key())){continue;}
if (!rhs.isMember(it.key()) || !(*it).compareOnly(rhs[it.key()], check)) {
return false;
}
}
jsonForEachConst(rhs, it){
if (!check.count(it.key())){continue;}
if (!(*this).isMember(it.key())){return false;}
}
return true;
}
jsonForEachConst(rhs, it){
if (!check.count(it.key())){continue;}
if (!(*this).isMember(it.key())){return false;}
if (myType == ARRAY) {
if (size() != rhs.size()){return false;}
jsonForEachConst(*this, it){
if (!(*it).compareOnly(rhs[it.num()], check)){return false;}
}
return true;
}
return true;
return ((*this) == rhs);
}
/// Completely clears the contents of this value,

View file

@ -4,14 +4,30 @@
void AnalyserDTSC::init(Util::Config &conf){
Analyser::init(conf);
JSON::Value opt;
opt["long"] = "headless";
opt["short"] = "H";
opt["help"] = "Parse entire file or streams as a single headless DTSC packet";
conf.addOption("headless", opt);
opt.null();
}
AnalyserDTSC::AnalyserDTSC(Util::Config &conf) : Analyser(conf){
conn = Socket::Connection(0, fileno(stdin));
totalBytes = 0;
headLess = conf.getBool("headless");
}
bool AnalyserDTSC::parsePacket(){
if (headLess){
while (conn){
if (!conn.spool()){Util::sleep(50);}
}
std::string dataBuf = conn.Received().remove(conn.Received().bytes(0xFFFFFFFFul));
DTSC::Scan S((char*)dataBuf.data(), dataBuf.size());
std::cout << S.toPrettyString() << std::endl;
return false;
}
P.reInit(conn);
if (conn && !P){
FAIL_MSG("Invalid DTSC packet @ byte %llu", totalBytes)

View file

@ -8,6 +8,7 @@ public:
static void init(Util::Config &conf);
private:
bool headLess;
DTSC::Packet P;
Socket::Connection conn;
uint64_t totalBytes;

View file

@ -173,8 +173,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;
@ -196,7 +200,7 @@ namespace Mist{
reconnect();
//if the connection failed, fail
if (streamName.size() < 1){
onFail();
onFail("Could not connect to stream", true);
return;
}
sought = false;
@ -365,14 +369,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;
}
}
@ -385,16 +387,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;
@ -1710,12 +1710,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;
}
}
@ -1723,21 +1718,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;
}
}

View file

@ -78,7 +78,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);

View file

@ -418,7 +418,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;
}
@ -434,11 +434,7 @@ namespace Mist {
}
initialize();
if (!keepGoing()){
onFail();
return;
}
if (!keepGoing()){return;}
if (H.url.substr(5 + streamName.size(), 5) == "/push"){
std::string relPushUrl = H.url.substr(10 + streamName.size());

View file

@ -41,13 +41,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){

View file

@ -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(){};

View file

@ -66,7 +66,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"){
@ -81,6 +81,7 @@ namespace Mist {
if (websocketHandler()){return;}
JSON::Value json_resp;
json_resp["error"] = "Could not retrieve stream. Sorry.";
json_resp["error_guru"] = msg;
if (config->getString("nostreamtext") != ""){
json_resp["on_error"] = config->getString("nostreamtext");
}
@ -101,9 +102,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){

View file

@ -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();

View file

@ -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();
}

View file

@ -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;}

View file

@ -583,7 +583,7 @@ namespace Mist{
myConn.SendNow(RTMPStream::SendCTL(1, RTMPStream::chunk_snd_max)); //send chunk size max (msg 1)
myConn.SendNow(RTMPStream::SendCTL(5, RTMPStream::snd_window_size)); //send window acknowledgement size (msg 5)
myConn.SendNow(RTMPStream::SendCTL(6, RTMPStream::rec_window_size)); //send rec window acknowledgement size (msg 6)
myConn.SendNow(RTMPStream::SendUSR(0, 1)); //send UCM StreamBegin (0), stream 1
//myConn.SendNow(RTMPStream::SendUSR(0, 1)); //send UCM StreamBegin (0), stream 1
//send onBWDone packet - no clue what it is, but real server sends it...
//amfReply = AMF::Object("container", AMF::AMF0_DDV_CONTAINER);
//amfReply.addContent(AMF::Object("", "onBWDone"));//result
@ -600,7 +600,7 @@ namespace Mist{
amfReply.addContent(AMF::Object("", (double)0, AMF::AMF0_NULL)); //null - command info
amfReply.addContent(AMF::Object("", (double)1)); //stream ID - we use 1
sendCommand(amfReply, messageType, streamId);
myConn.SendNow(RTMPStream::SendUSR(0, 1)); //send UCM StreamBegin (0), stream 1
//myConn.SendNow(RTMPStream::SendUSR(0, 1)); //send UCM StreamBegin (0), stream 1
return;
}//createStream
if (amfData.getContentP(0)->StrValue() == "ping"){