16#include <unordered_set>
18#include <mx/ioutils/fileUtils.hpp>
20#include "../../libMagAOX/libMagAOX.hpp"
21#include "../../magaox_git_version.h"
41#define SSHTUNNEL_E_NOTUNNELS (-10)
51typedef std::unordered_map<std::string, sshTunnel>
tunnelMapT;
60 mx::app::appConfigurator & config
63 std::vector<std::string> sections;
65 config.unusedSections(sections);
67 if( sections.size() == 0 )
75 for(
size_t i=0; i< sections.size(); ++i)
78 if( config.isSetUnused(mx::app::iniFile::makeKey(sections[i],
"remoteHost" )) &&
79 config.isSetUnused(mx::app::iniFile::makeKey(sections[i],
"localPort" )) &&
80 config.isSetUnused(mx::app::iniFile::makeKey(sections[i],
"remotePort" )) )
83 std::string remoteHost;
85 bool compress =
false;
87 config.configUnused( remoteHost, mx::app::iniFile::makeKey(sections[i],
"remoteHost" ) );
88 config.configUnused( localPort, mx::app::iniFile::makeKey(sections[i],
"localPort" ) );
89 config.configUnused( compress, mx::app::iniFile::makeKey(sections[i],
"compress" ) );
91 tmap[sections[i]] =
sshTunnel({remoteHost, localPort});
103#define XINDISERVER_E_BADDRIVERSPEC (-100)
104#define XINDISERVER_E_DUPLICATEDRIVER (-101)
105#define XINDISERVER_E_VECTOREXCEPT (-102)
106#define XINDISERVER_E_NOTUNNELS (-103)
107#define XINDISERVER_E_TUNNELNOTFOUND (-104)
108#define XINDISERVER_E_BADSERVERSPEC (-110)
245 config.add(
"indiserver.m",
"m",
"", argType::Required,
"indiserver",
"m",
false,
"int",
"indiserver kills client if it gets more than this many MB behind, default 50");
246 config.add(
"indiserver.N",
"N",
"", argType::True,
"indiserver",
"N",
false,
"bool",
"indiserver: ignore /tmp/noindi. Capitalized to avoid conflict with --name");
247 config.add(
"indiserver.p",
"p",
"", argType::Required,
"indiserver",
"p",
false,
"int",
"indiserver: alternate IP port, default 7624");
248 config.add(
"indiserver.v",
"v",
"", argType::True,
"indiserver",
"v",
false,
"int",
"indiserver: log verbosity, -v, -vv or -vvv");
249 config.add(
"indiserver.x",
"x",
"", argType::True,
"indiserver",
"x",
false,
"bool",
"exit after last client disconnects -- FOR PROFILING ONLY");
251 config.add(
"local.drivers",
"L",
"local.drivers" , argType::Required,
"local",
"drivers",
false,
"vector string",
"List of local drivers to start.");
252 config.add(
"remote.drivers",
"R",
"remote.drivers" , argType::Required,
"remote",
"drivers",
false,
"vector string",
"List of remote drivers to start, in the form of name@tunnel, where tunnel is the name of a tunnel specified in sshTunnels.conf.");
254 config.add(
"remote.servers",
"",
"remote.servers" , argType::Required,
"remote",
"servers",
false,
"vector string",
"List of servers to load remote drivers for, in the form of name@tunnel. Name is used to load the name.conf configuration file, and tunnel is the name of a tunnel specified in sshTunnels.conf.");
272 config(
m_local,
"local.drivers");
329 if(
bad != std::string::npos)
370 if(p == 0 || p == std::string::npos)
385 std::ostringstream
oss;
428 if(p == 0 || p == std::string::npos)
452 rsconfig.add(
"local.drivers",
"",
"" , argType::Required,
"local",
"drivers",
false,
"",
"");
458 std::vector<std::string>
local;
462 for(
size_t i=0;
i <
local.size(); ++
i)
464 size_t bad =
local[
i].find_first_of(
"@:/", 0);
466 if(
bad != std::string::npos)
481 std::ostringstream
oss;
507 std::string
coml =
"Starting indiserver with command: ";
515 std::cerr <<
coml << std::endl;
565 std::string
coml =
"indiserver started with PID " + mx::ioutils::convertToString(
m_isPID);
575 l->isLogThreadExec();
585 catch(
const std::exception &
e )
644 if(
logs.back() ==
'\n')
650 if(
eol == std::string::npos)
break;
669 if(
ed != std::string::npos)
ed =
logs.find(
':',
ed+1);
670 if(
ed != std::string::npos)
ed =
logs.find(
':',
ed+1);
672 if(
ed == std::string::npos)
684 mx::sys::ISO8601dateBreakdown(
bdt.tm_year,
bdt.tm_mon,
bdt.tm_mday,
bdt.tm_hour,
bdt.tm_min,
dsec,
ts);
698 st =
logs.find_first_not_of(
" ",
ed);
700 if(
st == std::string::npos)
st =
ed;
712 if(
logstr.find(
"xindidriver") != std::string::npos)
714 if(
logstr.find(
"failed to lock") != std::string::npos)
719 else if(
logstr.find(
"bind: Address already in use") != std::string::npos)
765 std::string
path1 =
"/opt/MagAOX/bin/xindidriver";
768 elevatedPrivileges
elPriv(
this);
The base-class for MagAO-X applications.
stateCodes::stateCodeT state()
Get the current state code.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::string m_configDir
The path to configuration files for MagAOX.
std::string m_configBase
The name of a base config class for this app (minus .conf).
int addRemoteServers(std::vector< std::string > &driverArgs)
Validate the remote server entries, read the associated config files for local drivers,...
std::vector< std::string > m_indiserverCommand
The command line arguments to indiserver.
int isLogThreadStart()
Start the log capture.
int indiserver_m
The indiserver MB behind setting (passed to indiserver)
int m_isSTDERR
The output of stderr of the indiserver process.
virtual int appLogic()
Implementation of the FSM for xindiserver.
int addRemoteDrivers(std::vector< std::string > &driverArgs)
Validate the remote driver entries, and append them to the indi server command line arguments.
std::vector< std::string > m_local
List of local drivers passed in by config.
void isLogThreadExec()
Execute the log capture.
virtual void setupConfig()
virtual int appShutdown()
Kills indiserver, and wakes up the log capture thread.
~xindiserver() noexcept
D'tor, declared and defined for noexcept.
static void _isLogThreadStart(xindiserver *l)
Thread starter, called by isLogThreadStart on thread construction. Calls isLogThreadExec.
pid_t m_isPID
The PID of the indiserver process.
xindiserver()
Default c'tor.
int forkIndiserver()
Forks and exec's the indiserver process with the command constructed from local, remote,...
bool indiserver_n
The indiserver ignore /tmp/noindi flag (passed to indiserver)
int addLocalDrivers(std::vector< std::string > &driverArgs)
Validate the local driver strings, and append them to the indi server command line arguments.
bool indiserver_x
The indiserver terminate after last exit flag (passed to indiserver)
std::string m_driverPath
The path to the local drivers.
std::vector< std::string > m_remote
List of remote drivers passed in by config.
std::vector< std::string > m_remoteServers
List of other INDI server config files to read remote drivers from.
std::unordered_set< std::string > m_driverNames
List of driver names processed for command line, used to prevent duplication.
int m_isSTDERR_input
The input end of stderr, used to wake up the log thread on shutdown.
std::thread m_isLogThread
A separate thread for capturing indiserver logs.
int m_isLogThreadPrio
Priority of the indiserver log capture thread, should normally be 0.
tunnelMapT m_tunnels
Map of the ssh tunnels, used for processing the remote drivers in m_remote.
int indiserver_v
The indiserver verbosity (passed to indiserver)
virtual int appStartup()
Startup functions.
int indiserver_p
The indiserver port (passed to indiserver)
virtual void loadConfig()
int constructIndiserverCommand(std::vector< std::string > &indiserverCommand)
Construct the vector of indiserver arguments for exec.
int processISLog(std::string logs)
Process a log entry from indiserver, putting it into MagAO-X standard form.
#define MAGAOX_path
The path to the MagAO-X system files.
#define MAGAOX_driverRelPath
The relative path to the INDI drivers.
int8_t logPrioT
The type of the log priority code.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ CONNECTED
The application has connected to the device or service.
std::unordered_map< std::string, sshTunnel > tunnelMapT
The map used to hold tunnel specifications.
int loadSSHTunnelConfigs(tunnelMapT &tmap, mx::app::appConfigurator &config)
Create the tunnel map from a configurator.
Structure to hold an sshTunnel specification, used for created command line args for indiserver.
static constexpr logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
uint32_t nanosecT
The type used for nanoseconds.
void log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry, including a message.
int logLevel(logPrioT newLev)
Set a new value of logLevel.
A simple text log, a string-type log.
A fixed-width timespec structure.
secT time_s
Time since the Unix epoch.
#define XINDISERVER_E_BADDRIVERSPEC
#define XINDISERVER_E_NOTUNNELS
#define XINDISERVER_E_DUPLICATEDRIVER
#define XINDISERVER_E_BADSERVERSPEC
#define XINDISERVER_E_VECTOREXCEPT
#define SSHTUNNEL_E_NOTUNNELS
#define XINDISERVER_E_TUNNELNOTFOUND