#include // cout, cerr #include #include // strcpy #include //stat #include #include #include #include #include #include #include "controller_storage.h" #include "controller_connectors.h" #include #include ///\brief Holds everything unique to the controller. namespace Controller { static std::map currentConnectors; ///::iterator iter; for (iter = currentConnectors.begin(); iter != currentConnectors.end(); iter++){ if (iter->second.substr(0, protocol.size()) == protocol){ Log("CONF", "Killing connector for update: " + iter->second); Util::Procs::Stop(toConn(iter->first)); } } } static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){ for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){ if (it->second.isMember("option")){ if (p.isMember(it->first)){ if (it->second.isMember("type")){ if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){ p[it->first] = p[it->first].asString(); } if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){ p[it->first] = p[it->first].asString(); } } if (p[it->first].asStringRef().size() > 0){ argarr[argnum++] = (char*)(it->second["option"].c_str()); argarr[argnum++] = (char*)(p[it->first].c_str()); } }else{ if (it->first == "debug"){ static std::string debugLvlStr; debugLvlStr = JSON::Value((long long)Util::Config::printDebugLevel).asString(); argarr[argnum++] = (char*)(it->second["option"].c_str()); argarr[argnum++] = (char*)debugLvlStr.c_str(); } } } } } static inline void buildPipedArguments(JSON::Value & p, char * argarr[], JSON::Value & capabilities){ int argnum = 0; 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(); } if (::stat(tmparg.c_str(), &buf) != 0){ return; } argarr[argnum++] = (char*)tmparg.c_str(); 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"]);} } ///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary. ///\param p An object containing all protocols. ///\param capabilities An object containing the detected capabilities. void CheckProtocols(JSON::Value & p, JSON::Value & capabilities){ std::map new_connectors; std::map::iterator iter; // used for building args int zero = 0; int out = fileno(stdout); int err = fileno(stderr); char * argarr[15]; // approx max # of args (with a wide margin) int i; std::string tmp; long long counter = 0; for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){ counter = ait - p.ArrBegin(); std::string prevOnline = ( *ait)["online"].asString(); #define connName (*ait)["connector"].asStringRef() if ( !(*ait).isMember("connector") || connName == ""){ ( *ait)["online"] = "Missing connector name"; continue; } if ( !capabilities["connectors"].isMember(connName)){ ( *ait)["online"] = "Not installed"; if (( *ait)["online"].asString() != prevOnline){ Log("WARN", connName + " connector is enabled but doesn't exist on system! Ignoring connector."); } continue; } #define connCapa capabilities["connectors"][connName] if (connCapa.isMember("socket") || (connCapa.isMember("deps") && connCapa["deps"].asStringRef() == "HTTP")){ ( *ait)["online"] = "Enabled"; continue; } if (connCapa.isMember("required")){ bool gotAll = true; for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){ if ( !(*ait).isMember(it->first) || (*ait)[it->first].asStringRef().size() < 1){ gotAll = false; ( *ait)["online"] = "Invalid configuration"; if (( *ait)["online"].asString() != prevOnline){ Log("WARN", connName + " connector is missing required parameter " + it->first + "! Ignoring connector."); } break; } } if (!gotAll){continue;} } ( *ait).removeMember("online"); /// \todo Check dependencies? new_connectors[counter] = (*ait).toString(); if (Util::Procs::isActive(toConn(counter))){ ( *ait)["online"] = 1; }else{ ( *ait)["online"] = 0; } } //shut down deleted/changed connectors for (iter = currentConnectors.begin(); iter != currentConnectors.end(); iter++){ if (new_connectors.count(iter->first) != 1 || new_connectors[iter->first] != iter->second){ Log("CONF", "Stopping connector " + iter->second); Util::Procs::Stop(toConn(iter->first)); } } //start up new/changed connectors for (iter = new_connectors.begin(); iter != new_connectors.end(); iter++){ if (currentConnectors.count(iter->first) != 1 || currentConnectors[iter->first] != iter->second || !Util::Procs::isActive(toConn(iter->first))){ Log("CONF", "Starting connector: " + iter->second); // clear out old args for (i=0; i<15; i++){argarr[i] = 0;} // get args for this connector buildPipedArguments(p[(long long unsigned)iter->first], (char **)&argarr, capabilities); // start piped w/ generated args Util::Procs::StartPiped(toConn(iter->first), argarr, &zero, &out, &err);//redirects output to out. Must make a new pipe, redirect std err } } //store new state currentConnectors = new_connectors; } }