Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/comms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ namespace Comms{
Socket::hostBytesToStr(ip.data(), ip.size(), host);
pid_t thisPid;
std::deque<std::string> args;
args.push_back(Util::getMyPath() + "MistSession");
args.push_back("MistSession");
args.push_back(sessionId);

// First bit defines whether to include stream name
Expand Down Expand Up @@ -393,7 +393,7 @@ namespace Comms{
}
setenv("SESSION_REQURL", reqUrl.c_str(), 1);
int err = fileno(stderr);
thisPid = Util::Procs::StartPiped(args, 0, 0, &err);
thisPid = Util::Procs::StartPipedMist(args, 0, 0, &err);
Util::Procs::forget(thisPid);
unsetenv("SESSION_STREAM");
unsetenv("SESSION_IP");
Expand Down
66 changes: 0 additions & 66 deletions lib/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,72 +890,6 @@ void Util::Config::addStandardPushCapabilities(JSON::Value &cap){

}

/// Gets directory the current executable is stored in.
std::string Util::getMyPath(){
char mypath[500];
#ifdef __CYGWIN__
GetModuleFileName(0, mypath, 500);
#else
#ifdef __APPLE__
memset(mypath, 0, 500);
unsigned int refSize = 500;
_NSGetExecutablePath(mypath, &refSize);
#else
int ret = readlink("/proc/self/exe", mypath, 500);
if (ret != -1){
mypath[ret] = 0;
}else{
mypath[0] = 0;
}
#endif
#endif
std::string tPath = mypath;
size_t slash = tPath.rfind('/');
if (slash == std::string::npos){
slash = tPath.rfind('\\');
if (slash == std::string::npos){return "";}
}
tPath.resize(slash + 1);
return tPath;
}

/// Gets all executables in getMyPath that start with "Mist".
void Util::getMyExec(std::deque<std::string> &execs){
std::string path = Util::getMyPath();
#ifdef __CYGWIN__
path += "\\Mist*";
WIN32_FIND_DATA FindFileData;
HANDLE hdl = FindFirstFile(path.c_str(), &FindFileData);
while (hdl != INVALID_HANDLE_VALUE){
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
execs.push_back(FindFileData.cFileName);
}
if (!FindNextFile(hdl, &FindFileData)){
FindClose(hdl);
hdl = INVALID_HANDLE_VALUE;
}
}
#else
DIR *d = opendir(path.c_str());
if (!d){return;}
struct dirent *dp;
do{
errno = 0;
if ((dp = readdir(d))){
if (dp->d_type != DT_DIR && strncmp(dp->d_name, "Mist", 4) == 0){
if (dp->d_type != DT_REG) {
struct stat st = {};
stat(dp->d_name, &st);
if (!S_ISREG(st.st_mode))
continue;
}
execs.push_back(dp->d_name);}
}
}while (dp != NULL);
closedir(d);
#endif
}

/// Sets the current process' running user
void Util::setUser(std::string username){
if (username != "root"){
Expand Down
6 changes: 0 additions & 6 deletions lib/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ namespace Util{
/// The port the current serveSocket function is listening on
extern uint32_t listenPort;

/// Gets directory the current executable is stored in.
std::string getMyPath();

/// Gets all executables in getMyPath that start with "Mist".
void getMyExec(std::deque<std::string> &execs);

/// Will set the active user to the named username.
void setUser(std::string user);

Expand Down
92 changes: 92 additions & 0 deletions lib/procs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>

std::set<pid_t> Util::Procs::plist;
std::set<int> Util::Procs::socketList;
Expand Down Expand Up @@ -353,6 +354,31 @@ pid_t Util::Procs::StartPiped(std::deque<std::string> &argDeq, int *fdin, int *f
return ret;
}

// Create a new deque with a rewritten first element to reflect the correct path
void mistifyDeque(std::deque<std::string> &argDeq) {
argDeq[0] = Util::getMyPath() + argDeq[0];
}

// Start one of our Mist* processes, resolving our path automatically and such.
pid_t Util::Procs::StartPipedMist(std::deque<std::string> &argDeq, int *fdin, int *fdout, int *fderr){
mistifyDeque(argDeq);
return Util::Procs::StartPiped(argDeq, fdin, fdout, fderr);
}

// Exec to one of our Mist* processes, resolving our path automatically and such.
int Util::Procs::ExecMist(std::deque<std::string> &argDeq){
mistifyDeque(argDeq);
char *const *argv = dequeToArgv(argDeq);
return execvp(argv[0], argv);
}

// Check whether a given Mist* binary is available for us to run
bool Util::Procs::HasMistBinary(std::string binName){
std::string tmparg = Util::getMyPath() + binName;
struct stat buf;
return ::stat(tmparg.c_str(), &buf) == 0;
}

/// Starts a new process with given fds if the name is not already active.
/// \return 0 if process was not started, process PID otherwise.
/// \arg argv Command for this process.
Expand Down Expand Up @@ -558,3 +584,69 @@ void Util::Procs::remember(pid_t pid){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
plist.insert(pid);
}

/// Gets directory the current executable is stored in.
std::string Util::getMyPath(){
char mypath[500];
#ifdef __CYGWIN__
GetModuleFileName(0, mypath, 500);
#else
#ifdef __APPLE__
memset(mypath, 0, 500);
unsigned int refSize = 500;
_NSGetExecutablePath(mypath, &refSize);
#else
int ret = readlink("/proc/self/exe", mypath, 500);
if (ret != -1){
mypath[ret] = 0;
}else{
mypath[0] = 0;
}
#endif
#endif
std::string tPath = mypath;
size_t slash = tPath.rfind('/');
if (slash == std::string::npos){
slash = tPath.rfind('\\');
if (slash == std::string::npos){return "";}
}
tPath.resize(slash + 1);
return tPath;
}

/// Gets all executables in getMyPath that start with "Mist".
void Util::getMyExec(std::deque<std::string> &execs){
std::string path = Util::getMyPath();
#ifdef __CYGWIN__
path += "\\Mist*";
WIN32_FIND_DATA FindFileData;
HANDLE hdl = FindFirstFile(path.c_str(), &FindFileData);
while (hdl != INVALID_HANDLE_VALUE){
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
execs.push_back(FindFileData.cFileName);
}
if (!FindNextFile(hdl, &FindFileData)){
FindClose(hdl);
hdl = INVALID_HANDLE_VALUE;
}
}
#else
DIR *d = opendir(path.c_str());
if (!d){return;}
struct dirent *dp;
do{
errno = 0;
if ((dp = readdir(d))){
if (dp->d_type != DT_DIR && strncmp(dp->d_name, "Mist", 4) == 0){
if (dp->d_type != DT_REG) {
struct stat st = {};
stat(dp->d_name, &st);
if (!S_ISREG(st.st_mode))
continue;
}
execs.push_back(dp->d_name);}
}
}while (dp != NULL);
closedir(d);
#endif
}
9 changes: 9 additions & 0 deletions lib/procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
/// Contains utility code, not directly related to streaming media
namespace Util{

/// Gets directory the current executable is stored in.
std::string getMyPath();

/// Gets all executables in getMyPath that start with "Mist".
void getMyExec(std::deque<std::string> &execs);

/// Deals with spawning, monitoring and stopping child processes
class Procs{
private:
Expand All @@ -35,6 +41,9 @@ namespace Util{
static std::string getLimitedOutputOf(char *const *argv, uint64_t maxWait, uint32_t maxValBytes);
static pid_t StartPiped(const char *const *argv, int *fdin, int *fdout, int *fderr);
static pid_t StartPiped(std::deque<std::string> &argDeq, int *fdin, int *fdout, int *fderr);
static pid_t StartPipedMist(std::deque<std::string> &argDeq, int *fdin, int *fdout, int *fderr);
static int ExecMist(std::deque<std::string> &argDeq);
static bool HasMistBinary(std::string binName);
static void Stop(pid_t name);
static void Murder(pid_t name);
static void StopAll();
Expand Down
27 changes: 13 additions & 14 deletions lib/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,21 +640,21 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir
setenv("MISTPROVIDER", "1", 1);
}

std::string player_bin = Util::getMyPath() + "MistIn" + input["name"].asStringRef();
char *argv[30] ={(char *)player_bin.c_str(), (char *)"-s", (char *)streamname.c_str(),
(char *)filename.c_str()};
int argNum = 3;
std::deque<std::string> argDeq;
argDeq.push_back("MistIn" + input["name"].asStringRef());
argDeq.push_back("-s");
argDeq.push_back(streamname);
argDeq.push_back(filename);
std::string debugLvl;
if (Util::printDebugLevel != DEBUG && !str_args.count("--debug")){
debugLvl = JSON::Value(Util::printDebugLevel).asString();
argv[++argNum] = (char *)"--debug";
argv[++argNum] = (char *)debugLvl.c_str();
argDeq.push_back("--debug");
argDeq.push_back(debugLvl);
}
for (std::map<std::string, std::string>::iterator it = str_args.begin(); it != str_args.end(); ++it){
argv[++argNum] = (char *)it->first.c_str();
if (it->second.size()){argv[++argNum] = (char *)it->second.c_str();}
argDeq.push_back(it->first);
if (it->second.size()){argDeq.push_back(it->second);}
}
argv[++argNum] = (char *)0;

Util::Procs::setHandler();

Expand Down Expand Up @@ -683,13 +683,12 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir
Socket::Connection io(0, 1);
io.drop();
std::stringstream args;
for (size_t i = 0; i < 30; ++i){
if (!argv[i] || !argv[i][0]){break;}
args << argv[i] << " ";
for (int i = 0; i < argDeq.size(); i++){
args << argDeq[i] << " ";
}
INFO_MSG("Starting %s", args.str().c_str());
execvp(argv[0], argv);
FAIL_MSG("Starting process %s failed: %s", argv[0], strerror(errno));
Util::Procs::ExecMist(argDeq);
FAIL_MSG("Starting process %s failed: %s", argDeq[0].c_str(), strerror(errno));
_exit(42);
}else if (spawn_pid != NULL){
*spawn_pid = pid;
Expand Down
44 changes: 20 additions & 24 deletions src/controller/controller_connectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ namespace Controller{
currentConnectors.clear();
}

static inline void builPipedPart(JSON::Value &p, char *argarr[], int &argnum, const JSON::Value &argset){
static inline void buildPipedPart(JSON::Value &p, std::deque<std::string> &argDeq, const JSON::Value &argset){
jsonForEachConst(argset, it){
if (it->isMember("option") && p.isMember(it.key())){
if (!it->isMember("type")){
if (JSON::Value(p[it.key()]).asBool()){
argarr[argnum++] = (char *)((*it)["option"].c_str());
argDeq.push_back((*it)["option"]);
}
continue;
}
Expand All @@ -109,35 +109,34 @@ namespace Controller{
}
if ((*it)["type"].asStringRef() == "inputlist" && p[it.key()].isArray()){
jsonForEach(p[it.key()], iVal){
(*iVal) = iVal->asString();
argarr[argnum++] = (char *)((*it)["option"].c_str());
argarr[argnum++] = (char *)((*iVal).c_str());
argDeq.push_back((*it)["option"]);
argDeq.push_back(iVal->asString());
}
continue;
}
if (p[it.key()].asStringRef().size() > 0){
argarr[argnum++] = (char *)((*it)["option"].c_str());
argarr[argnum++] = (char *)(p[it.key()].c_str());
argDeq.push_back((*it)["option"]);
argDeq.push_back(p[it.key()].asString());
}else{
argarr[argnum++] = (char *)((*it)["option"].c_str());
argDeq.push_back((*it)["option"]);
}
}
}
}

static inline void buildPipedArguments(JSON::Value &p, char *argarr[], const JSON::Value &capabilities){
int argnum = 0;
static inline void buildPipedArguments(JSON::Value &p, std::deque<std::string> &argDeq, const JSON::Value &capabilities){
static std::string tmparg;
tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef();
struct stat buf;
if (::stat(tmparg.c_str(), &buf) != 0){
tmparg = Util::getMyPath() + std::string("MistConn") + p["connector"].asStringRef();
tmparg = std::string("MistOut") + p["connector"].asStringRef();
if (!Util::Procs::HasMistBinary(tmparg)){
tmparg = std::string("MistConn") + p["connector"].asStringRef();
if (!Util::Procs::HasMistBinary(tmparg)) {
return;
}
}
if (::stat(tmparg.c_str(), &buf) != 0){return;}
argarr[argnum++] = (char *)tmparg.c_str();
argDeq.push_back(tmparg);
const JSON::Value &pipedCapa = capabilities["connectors"][p["connector"].asStringRef()];
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
if (pipedCapa.isMember("required")){buildPipedPart(p, argDeq, pipedCapa["required"]);}
if (pipedCapa.isMember("optional")){buildPipedPart(p, argDeq, pipedCapa["optional"]);}
}

///\brief Checks current protocol configuration, updates state of enabled connectors if
Expand All @@ -160,8 +159,6 @@ namespace Controller{

// used for building args
int err = fileno(stderr);
char *argarr[15]; // approx max # of args (with a wide margin)
int i;

std::string tmp;

Expand Down Expand Up @@ -254,13 +251,12 @@ namespace Controller{
!Util::Procs::isActive(currentConnectors[*runningConns.begin()])){
Log("CONF", "Starting connector: " + *runningConns.begin());
action = true;
// clear out old args
for (i = 0; i < 15; i++){argarr[i] = 0;}
std::deque<std::string> argDeq;
// get args for this connector
JSON::Value p = JSON::fromString(*runningConns.begin());
buildPipedArguments(p, (char **)&argarr, capabilities);
buildPipedArguments(p, argDeq, capabilities);
// start piped w/ generated args
currentConnectors[*runningConns.begin()] = Util::Procs::StartPiped(argarr, 0, 0, &err);
currentConnectors[*runningConns.begin()] = Util::Procs::StartPipedMist(argDeq, 0, 0, &err);
Triggers::doTrigger("OUTPUT_START", *runningConns.begin()); // LTS
}
runningConns.erase(runningConns.begin());
Expand Down