Improved startInput function behaviour and reliability, added streamAlive function.
This commit is contained in:
parent
dcde050143
commit
c3efc1001f
3 changed files with 53 additions and 27 deletions
|
@ -73,50 +73,75 @@ void Util::sanitizeName(std::string & streamname) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts a process for a VoD stream.
|
/// Checks if the given streamname has an active input serving it. Returns true if this is the case.
|
||||||
|
/// Assumes the streamname has already been through sanitizeName()!
|
||||||
|
bool Util::streamAlive(std::string & streamname){
|
||||||
|
IPC::semaphore playerLock(std::string("/lock_" + streamname).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
||||||
|
if (!playerLock.tryWait()) {
|
||||||
|
playerLock.close();
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
playerLock.post();
|
||||||
|
playerLock.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assures the input for the given stream name is active.
|
||||||
|
/// Does stream name sanitizion first, followed by a stream name length check (<= 100 chars).
|
||||||
|
/// Then, checks if an input is already active by running streamAlive(). If yes, aborts.
|
||||||
|
/// If no, loads up the server configuration and attempts to start the given stream according to current config.
|
||||||
|
/// At this point, fails and aborts if MistController isn't running.
|
||||||
bool Util::startInput(std::string streamname, std::string filename, bool forkFirst) {
|
bool Util::startInput(std::string streamname, std::string filename, bool forkFirst) {
|
||||||
|
sanitizeName(streamname);
|
||||||
if (streamname.size() > 100){
|
if (streamname.size() > 100){
|
||||||
FAIL_MSG("Stream opening denied: %s is longer than 100 characters (%lu).", streamname.c_str(), streamname.size());
|
FAIL_MSG("Stream opening denied: %s is longer than 100 characters (%lu).", streamname.c_str(), streamname.size());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
IPC::sharedPage mistConfOut("!mistConfig", DEFAULT_CONF_PAGE_SIZE);
|
//Check if the stream is already active.
|
||||||
IPC::semaphore configLock("!mistConfLock", O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
|
||||||
configLock.wait();
|
|
||||||
DTSC::Scan config = DTSC::Scan(mistConfOut.mapped, mistConfOut.len);
|
|
||||||
|
|
||||||
sanitizeName(streamname);
|
|
||||||
std::string smp = streamname.substr(0, streamname.find_first_of("+ "));
|
|
||||||
//check if smp (everything before + or space) exists
|
|
||||||
DTSC::Scan stream_cfg = config.getMember("streams").getMember(smp);
|
|
||||||
if (!stream_cfg){
|
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Stream %s not configured", streamname.c_str());
|
|
||||||
configLock.post();//unlock the config semaphore
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If starting without filename parameter, check if the stream is already active.
|
|
||||||
//If yes, don't activate again to prevent duplicate inputs.
|
//If yes, don't activate again to prevent duplicate inputs.
|
||||||
//It's still possible a duplicate starts anyway, this is caught in the inputs initializer.
|
//It's still possible a duplicate starts anyway, this is caught in the inputs initializer.
|
||||||
//Note: this uses the _whole_ stream name, including + (if any).
|
//Note: this uses the _whole_ stream name, including + (if any).
|
||||||
//This means "test+a" and "test+b" have separate locks and do not interact with each other.
|
//This means "test+a" and "test+b" have separate locks and do not interact with each other.
|
||||||
|
if (streamAlive(streamname)){
|
||||||
|
DEBUG_MSG(DLVL_MEDIUM, "Stream %s already active; continuing", streamname.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Attempt to load up configuration and find this stream
|
||||||
|
IPC::sharedPage mistConfOut("!mistConfig", DEFAULT_CONF_PAGE_SIZE);
|
||||||
|
IPC::semaphore configLock("!mistConfLock", O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
||||||
|
//Lock the config to prevent race conditions and corruption issues while reading
|
||||||
|
configLock.wait();
|
||||||
|
DTSC::Scan config = DTSC::Scan(mistConfOut.mapped, mistConfOut.len);
|
||||||
|
//Abort if no config available
|
||||||
|
if (!config){
|
||||||
|
FAIL_MSG("Configuration not available, aborting! Is MistController running?");
|
||||||
|
configLock.post();//unlock the config semaphore
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//Find stream base name
|
||||||
|
std::string smp = streamname.substr(0, streamname.find_first_of("+ "));
|
||||||
|
//check if base name (everything before + or space) exists
|
||||||
|
DTSC::Scan stream_cfg = config.getMember("streams").getMember(smp);
|
||||||
|
if (!stream_cfg){
|
||||||
|
DEBUG_MSG(DLVL_HIGH, "Stream %s not configured - attempting to ignore", streamname.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//Only use configured source if not manually overridden. Abort if no config is available.
|
||||||
if (!filename.size()){
|
if (!filename.size()){
|
||||||
IPC::semaphore playerLock(std::string("/lock_" + streamname).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
if (!stream_cfg){
|
||||||
if (!playerLock.tryWait()) {
|
DEBUG_MSG(DLVL_MEDIUM, "Stream %s not configured, no source manually given, cannot start", streamname.c_str());
|
||||||
playerLock.close();
|
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Stream %s already active - not activating again", streamname.c_str());
|
|
||||||
configLock.post();//unlock the config semaphore
|
configLock.post();//unlock the config semaphore
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
playerLock.post();
|
|
||||||
playerLock.close();
|
|
||||||
filename = stream_cfg.getMember("source").asString();
|
filename = stream_cfg.getMember("source").asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check in curConf for capabilities-inputs-<naam>-priority/source_match
|
||||||
std::string player_bin;
|
std::string player_bin;
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
long long int curPrio = -1;
|
long long int curPrio = -1;
|
||||||
//check in curConf for capabilities-inputs-<naam>-priority/source_match
|
|
||||||
DTSC::Scan inputs = config.getMember("capabilities").getMember("inputs");
|
DTSC::Scan inputs = config.getMember("capabilities").getMember("inputs");
|
||||||
DTSC::Scan input;
|
DTSC::Scan input;
|
||||||
unsigned int input_size = inputs.getSize();
|
unsigned int input_size = inputs.getSize();
|
||||||
|
|
|
@ -8,5 +8,6 @@
|
||||||
namespace Util {
|
namespace Util {
|
||||||
std::string getTmpFolder();
|
std::string getTmpFolder();
|
||||||
void sanitizeName(std::string & streamname);
|
void sanitizeName(std::string & streamname);
|
||||||
|
bool streamAlive(std::string & streamname);
|
||||||
bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true);
|
bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace Mist {
|
||||||
return; //abort - no stream to initialize...
|
return; //abort - no stream to initialize...
|
||||||
}
|
}
|
||||||
if (!Util::startInput(streamName)){
|
if (!Util::startInput(streamName)){
|
||||||
DEBUG_MSG(DLVL_FAIL, "Opening stream disallowed - aborting initalization");
|
DEBUG_MSG(DLVL_FAIL, "Opening stream failed - aborting initalization");
|
||||||
onFail();
|
onFail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue