#include "SocketThreadMonitord.h" #include "config.h" #include "Monitor.h" #include <algorithm> #include <iostream> #include "MonitorLogging.h" const std::string welcomeString="100;" +std::string(PACKAGE_STRING)+ " READY\r\n"; const std::string authenticateString="101:001\r\n" ; const std::string illegalFormatString="101:004\r\n" ; const std::string CAPABILITY_MONITORD_VERSION="0020" ; const std::string CAPABILITY_MONITORD_PROTOCOLVERSION="0004" ; using namespace std; SocketThreadMonitord::SocketThreadMonitord(MonitorConfiguration *config, int LOCKNUM, int PortNum) : SocketThread(config, LOCKNUM, PortNum, monitord) { } SocketThreadMonitord::~SocketThreadMonitord() { } void SocketThreadMonitord::sayWelcome() { say(welcomeString) ; } bool SocketThreadMonitord::parseCommand() { m_paramCount=0 ; std::string parserTemp =m_CommandBuffer ; std::string item ; // Aktueller Teil zwischen den Doppelpunkten size_t len = 0 ; // Laenge bis zum naechsten Doppelpunkt int itemCount=0; // Wievielter Parameter ? bool lastItem=false ; // letzter Eintrag ? (fuer CR/LF interessant) bool illegalCommand=false ; int i ; for (i=0;i<MAX_PARAMS;i++) { m_cmdParam[i].clear() ; } // übergebene Zeichenkette in die einzelnen Parameter zerlegen. Kommentare am Ende ( Durch ";" abgetrennt ) entfernen len=parserTemp.find_last_of(";", 0) ; if (len!=std::string::npos) // Kein ";" gefunden ? - sonst abschneiden { parserTemp=parserTemp.substr(0,len) ; } do { len=parserTemp.find(":", 0) ; if (len==std::string::npos) // Kein ":" gefunden { if (!parserTemp.empty()) { // CR/LF entfernen // TODO: Hier eigentlich noch auf CRLF prüfen ! lastItem=true ; len=parserTemp.length(); // war: len=parserTemp.length()-2; } } if (len!= std::string::npos) { item=parserTemp.substr(0,len) ; if (lastItem) { parserTemp.erase(0,parserTemp.length()) ; } else { parserTemp.erase(0,len+1) ; } switch (itemCount) { case 0: // 3stelliges Kommando zwingend zu beginn ! if (len!=3) { illegalCommand=true ; } m_cmdString=item ; break ; default: if (itemCount < MAX_PARAMS) { m_cmdParam[itemCount-1]=item ; } break; } itemCount++ ; } if (illegalCommand) { len=std::string::npos ; m_paramCount=0 ; } else { m_paramCount=itemCount ; } } while ((len!= std::string::npos) && (itemCount<=MAX_PARAMS)); return true ; } void SocketThreadMonitord::processInput() { bool isProcessed=false ; if (parseCommand()) { int cmd ; try { LOG_DEBUG("command from client: " << m_cmdString) cmd = convertToInt(m_cmdString) ; } catch (std::runtime_error err) { LOG_ERROR("Fehler bei der Cmd Konvertierung: " << m_cmdString) cmd=-1 ; say(illegalFormatString) ; } // Bevor wir pruefen, ob eine Anmeldung vorliegt gibt es zwei Kommandos, // die trotzdem ausgefuehrt werden: 299 (bye) und 220 (Login) switch (cmd) { case 299: isProcessed=true ; say ("199\r\n") ; // Logout doLogout() ; break ; case 220: isProcessed=true ; checkLogin() ; break ; case 210: // Inquiery isProcessed=true ; tellCapabilites() ; break ; /* case 999: // Stop Server say ("going down...\r\n") ; m_monitor.m_bWantStop=true ; */ default: // Nichts tun ... break ; } if (isProcessed==false) { if (!m_authenticated) { say (authenticateString) ; } else { // Sonst alle anderen Kommandos jetzt pruefen ... switch (cmd) { case 202: // Keepalive say ("100\r\n") ; // OK break ; case 203: // ChannelInfo tellChannels() ; break ; case 204: // Record say ("101:005\r\n") ; // 005:Not implemented // auskommentiert, weil die Recording-Funktionalität nicht stabil/sicher ist. // Rückmeldung an den Client: not implemented // startRecording() ; break ; default: say(illegalFormatString); break; } } } } else { say(illegalFormatString) ; } } void SocketThreadMonitord::tellCapabilites() { std::string hexOS ; //std::string hexChannelname; std::string hexProgramName ; std::string hexProgramVersion ; std::string hexModules ; #ifdef WIN32 convertStringToHex("WINDOWS",hexOS) ; #else convertStringToHex("LINUX",hexOS) ; #endif hexProgramName=convertStringToHex(PACKAGE_NAME) ; //hexProgramVersion=convertStringToHex(CAPABILITY_MONITORD_VERSION) ; //hexModules=convertStringToHex(std::string("REC")) ; say ("111:1:" + hexProgramName + "\r\n") ; say ("111:2:" + hexOS+ "\r\n") ; say ("111:3:" + CAPABILITY_MONITORD_VERSION+ "\r\n") ; say ("111:4:" + CAPABILITY_MONITORD_PROTOCOLVERSION+ "\r\n") ; say (std::string("111:5:") + "\r\n") ; say (std::string("111:0") + "\r\n") ; } void SocketThreadMonitord::tellChannels() { #if 1 /* FIXME */ // FIXME done: monitord_config scheinbar wieder "richtig drin", es kommen jedenfalls Antworten gemäß der Konfiguration... mdi 29032011 std::string hexString ; int summe ; for (int i=3; i>=0;i--) { if (m_MonitorConfiguration->m_sndConfig[i].iAktiv==1) { convertStringToHex(m_MonitorConfiguration->m_sndConfig[i].sChannelName0,hexString) ; summe= 1*(m_MonitorConfiguration->m_sndConfig[i].iZVEI[0]) + 2*(m_MonitorConfiguration->m_sndConfig[i].iFMS[0]) + 4*(m_MonitorConfiguration->m_sndConfig[i].iPOC512[0]) + 8*(m_MonitorConfiguration->m_sndConfig[i].iPOC1200[0]) ; say ("103:" + convertIntToString(2*i+1) + ":" + hexString + ":" + convertIntToString(summe) +"\r\n") ; convertStringToHex(m_MonitorConfiguration->m_sndConfig[i].sChannelName1,hexString) ; summe= 1*(m_MonitorConfiguration->m_sndConfig[i].iZVEI[1]) + 2*(m_MonitorConfiguration->m_sndConfig[i].iFMS[1]) + 4*(m_MonitorConfiguration->m_sndConfig[i].iPOC512[1]) + 8*(m_MonitorConfiguration->m_sndConfig[i].iPOC1200[1]) ; say ("103:" + convertIntToString(2*i) + ":" + hexString + ":" + convertIntToString(summe) +"\r\n") ; } } #endif } void SocketThreadMonitord::startRecording(int seconds, int channel) { int tempSeconds=0; int tempChannel=0; bool bErrConversion=false ; try { tempChannel=convertToInt(m_cmdParam[0]) ; tempSeconds=convertToInt(m_cmdParam[1]) ; } catch (BadConversion e) { bErrConversion=true ; } if (bErrConversion==false) { seconds=tempSeconds ; channel=tempChannel ; } int sndCardNum =channel / 2 ; int sndCardLeftRight=channel % 2 ; LOG_DEBUG( "Starte Aufnahme mit" << seconds << " Sekunden" << " auf Karte " << sndCardNum << ", Kanal=" << sndCardLeftRight << endl) std::string command=std::string("RECORD:" + convertIntToString(seconds)+ ":") + convertIntToString(channel) ; #if 0 /* FIXME muß noch umstrukturiert werden */ std::string resultString =m_monitor.m_sndIn[sndCardNum].PluginCommand(sndCardLeftRight,command,this); if (resultString=="not accepted") { say ("101:009\r\n") ; }; if (resultString=="not implemented") { say ("101:005\r\n") ; }; #endif } void SocketThreadMonitord::checkLogin() { // if (m_authenticated==false) // Auskommentiert: Auch bei freigeschalteter IP noch eine // Anmeldung zulassen. Auth-Status wird bei falschem Benutzernamen aber // nicht zurückgesetzt. Dient eher für Filter u.ä. um ggf. höhere Rechte // zu erlangen. Nur: Was antwortet man dem Client dann, wenn er das falsche PW ausgibt ? // { if (m_paramCount>3) { std::string loginname,password ; std::string protocol ; try { HexToString(0,loginname) ; HexToString(1,password) ; protocol= m_cmdParam[2] ; //HexToString(2,protocol) ; } catch (std::runtime_error err) { return ; } if (protocol==CAPABILITY_MONITORD_PROTOCOLVERSION) { if (m_MonitorConfiguration->IsValidLogin(loginname,password,m_sClientIP)) { m_authenticated=true ; m_loginname=loginname ; LOG_INFO("login accepted (user allowed): " << m_loginname << " from ip " << m_sClientIP) say ("100\r\n") ; // Login OK } else { say ("101:003\r\n") ; // Benutzername falsch LOG_INFO("login denied: " << m_loginname << " from ip " << m_sClientIP) } } else { say ("101:008\r\n") ; // Falsche Protokollversion LOG_INFO("login denied, incorrect protocol version: " << protocol << " from ip: " << m_sClientIP << " with username: " << loginname) } } else { LOG_INFO("login with too few arguments detected") say ("101:004;TOO FEW ARGUMENTS\r\n") ; // Fehler: Anfrage nicht verstanden ! } } /* } else { say ("100\r\n") ; // Login OK } */ } std::string SocketThreadMonitord::createFMSOutputString(ModuleResultBase Result) { std::string socketText ; std::string text ; convertStringToHex(Result["textuebertragung"],text) ; socketText = std::string("310") + ":" + Result["timestamp"] //+ ":" + Result["servernamehex"] //+ ":" + Result["channelnamehex"] + ":" + Result["channelnum"] + ":" + Result["fmskennung"] + ":" + Result["status"] + ":" + Result["baustufe"] + ":" + Result["richtung"] + ":" + Result["tki"] ; if (text.size()>0) { socketText+= ":" + text ; } ; std::transform ( socketText.begin(), socketText.end(), socketText.begin(), (int(*)(int)) toupper); return socketText ; } std::string SocketThreadMonitord::createZVEIOutputString(ModuleResultBase Result) { std::string socketText="" ; std::string hexText; convertStringToHex(Result["text"],hexText) ; socketText = std::string("300") + ":" + Result["timestamp"] //+ ":" + Result["servernamehex"] //+ ":" + Result["channelnamehex"] + ":" + Result["channelnum"] + ":" + Result["zvei"] + ":" + Result["weckton"] + ":" + hexText ; ; std::transform (socketText.begin(), socketText.end(), socketText.begin(), (int(*)(int)) toupper); return socketText ; } std::string SocketThreadMonitord::createPOCSAGOutputString(ModuleResultBase Result) { std::string socketText="" ; std::string hexText; convertStringToHex(Result["text"],hexText) ; socketText = std::string("320") + ":" + Result["timestamp"] //+ ":" + Result["servernamehex"] //+ ":" + Result["channelnamehex"] + ":" + Result["channelnum"] + ":" + Result["ric"] + ":" + Result["sub"] + ":" + hexText ; ; std::transform (socketText.begin(), socketText.end(), socketText.begin(), (int(*)(int)) toupper); return socketText ; }