/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Manuel Mausz (manuel@mausz.at) * Christian Raschko (c.raschko@netcore.at) */ //Header #include "tsapp.h" #include "tsheaders.h" //Libraries #include #include #include #include #include #if defined(__UNIX__) # include #endif //------------------------------------------------------------------------------ // OnInit bool TSApp::OnInit() { m_pLog = NULL; m_pLogFile = NULL; m_pConfig = NULL; m_pClient = NULL; m_pQuery = NULL; m_ConfigFileName = CONFIG_FILE_NAME; if (!wxAppConsole::OnInit()) return false; return true; } //------------------------------------------------------------------------------ // OnExit int TSApp::OnExit() { //cleanup wxAppConsole::OnExit(); if(m_pLogFile != NULL && m_pLogFile->IsOpened()) m_pLogFile->Close(); if(m_pLogFile != NULL) delete m_pLogFile; m_pLogFile = NULL; if(m_pQuery != NULL) delete m_pQuery; m_pQuery = NULL; if(m_pClient != NULL) delete m_pClient; m_pClient = NULL; if(m_pConfig != NULL) delete m_pConfig; m_pConfig = NULL; if(m_pLog != NULL) delete m_pLog; m_pLog = NULL; if(m_pQuery != NULL) delete m_pQuery; m_pQuery = NULL; return true; } //------------------------------------------------------------------------------ // Program entry point, replacment for main() int TSApp::OnRun() { wxStringOutputStream out; //UNIX stuff #if defined(__UNIX__) if(!m_Foreground && !m_Interactive) { int pid = fork(); if(pid < 0) { wxLogError(_T("can't fork")); return EXIT_FAILURE; } else if(pid != 0) return EXIT_SUCCESS; //detach from tty if (!m_Logtostderr) { //close existing file descriptors for (int fd = getdtablesize() - 1; fd >= 0; fd--) close(fd); //open stdin on /dev/null open("/dev/null", O_RDWR); } } #endif //welcome message wxPrintf(_T("TeamSpeak Client v0.3 (c)2006-2013 Clan-Server.at\n")); m_pLog->SetTimestamp(_T("[%x %X]")); wxLog::SetActiveTarget(m_pLog); wxSocketBase::Initialize(); m_pClient = new TSClient; m_pQuery = new TSQueryThread(m_pClient); //load config if(!LoadConfig(m_ConfigFileName)) { wxLogError(_T("can't open config file %s"), m_ConfigFileName.c_str()); return EXIT_FAILURE; } //open logfile if(m_pLogFileStr.Length() > 0 && !m_Logtostderr && (m_pLogFile == NULL || !m_pLogFile->IsOpened())) { m_pLogFile = new wxFFile(m_pLogFileStr.c_str(), _T("a+")); if(!m_pLogFile->IsOpened()) { wxLogError(_T("can't open logfile '%s'."), m_pLogFileStr.c_str()); return false; } if (m_pLog != NULL) delete m_pLog; m_pLog = new wxLogStderr((FILE *)m_pLogFile->fp()); } //start query thread m_pQuery->Start(); //check for interactive mode if(m_Interactive) Interactive(); else { while(m_pClient->IsReconnectActive()) { if(!m_pClient->IsConnected()) { m_pClient->Disconnect(); //some status info wxLogMessage(_T("TSServer: connecting to %s:%d..."), m_pClient->GetServer()->GetServerAddress().c_str(), m_pClient->GetServer()->GetPort()); //connect if(!m_pClient->Connect()) { wxLogError(_T("%s, error connecting."), m_pClient->GetLastError().c_str()); wxSleep(RECONNECT_TIMEOUT); } else wxLogMessage(_T("TSServer: connection established...")); } wxSleep(1); } } wxLogMessage(_T("TSServer: disconnecting...")); m_pClient->Disconnect(); m_pQuery->Stop(); wxSocketBase::Shutdown(); wxLogMessage(_T("TSServer: shutting down successful.")); wxLog::SetActiveTarget(NULL); return EXIT_SUCCESS; } //------------------------------------------------------------------------------ // Load config bool TSApp::LoadConfig(wxString const &filename) { wxString str; if(!wxFileExists(filename)) return false; m_pConfig = new wxFileConfig(_T("TSDaemon"), wxEmptyString, filename, filename, wxCONFIG_USE_RELATIVE_PATH); m_pConfig->Read(_T("LogFile"), &str, _T("")); if(m_pLogFileStr.Length() <= 0) m_pLogFileStr = str; //TSClient m_pConfig->Read(_T("TSPlatform"), &str, _T("Windows XP")); m_pClient->SetPlatform(str); m_pConfig->Read(_T("TSVersionNumber"), &str, _T("2.0.32.60")); m_pClient->SetVersionNumber(str); TSPlayer *pTSP = new TSPlayer; m_pConfig->Read(_T("TSLoginName"), &str, _T("")); pTSP->SetLoginName(str); m_pConfig->Read(_T("TSLoginPassword"), &str, _T("")); pTSP->SetLoginPassword(str); m_pConfig->Read(_T("TSNickname"), &str, _T("")); pTSP->SetNickname(str); //now the TSClient takes care of the pointer. m_pClient->SetPlayer(pTSP); TSServer *pTSS = new TSServer; m_pConfig->Read(_T("TSServerAddress"), &str, _T("")); pTSS->SetServerAddress(str); long l; m_pConfig->Read(_T("TSPort"), &l, 0); if(!pTSS->SetPort(l)) wxLogError(_T("port, %s"), pTSS->GetLastError().c_str()); //now the TSClient takes care of the pointer. m_pClient->SetServer(pTSS); m_pConfig->Read(_T("ServerAddress"), &str, _T("")); m_pQuery->SetServerAddress(str); m_pConfig->Read(_T("AllowedAddresses"), &str, _T("")); m_pQuery->SetAllowedAddresses(str); m_pConfig->Read(_T("Port"), &l, 0); if(!m_pQuery->SetPort(l)) wxLogError(_T("port, %s"), m_pQuery->GetLastError().c_str()); m_pConfig->Read(_T("Password"), &str, _T("")); if(!m_pQuery->SetPassword(str)) wxLogError(_T("password, %s"), m_pQuery->GetLastError().c_str()); return true; } //------------------------------------------------------------------------------ // Set parser line description void TSApp::OnInitCmdLine(wxCmdLineParser &parser) { //declare CmdLineParser static const wxCmdLineEntryDesc cmdLineDesc[] = { { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show this help message"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, { wxCMD_LINE_SWITCH, _T("i"), _T("interactive"), _T("interactive mode"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, _T("v"), _T("verbose"), _T("be verbose") , wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL}, { wxCMD_LINE_SWITCH, _T("q"), _T("quiet"), _T("be quiet") , wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL}, #if defined(__UNIX__) { wxCMD_LINE_SWITCH, _T("f"), _T("foreground"), _T("run in foreground mode"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL}, #endif { wxCMD_LINE_SWITCH, _T("g"), _T("logtostderr"), _T("log everything to stderr"), wxCMD_LINE_VAL_NONE,wxCMD_LINE_PARAM_OPTIONAL}, { wxCMD_LINE_OPTION, _T("c"), _T("config"), _T("path to config file"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, _T("l"), _T("logfile"), _T("path to log file"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_NONE, NULL, NULL, NULL, (wxCmdLineParamType)0, 0 } //ends list }; parser.SetDesc(cmdLineDesc); //no long options on windows #ifdef __WINDOWS__ parser.DisableLongOptions(); #endif } //------------------------------------------------------------------------------ // Process command line options bool TSApp::OnCmdLineParsed(wxCmdLineParser &parser) { m_Interactive = false; m_Foreground = false; m_Logtostderr = false; /* Create and hook logtarget in */ if (m_pLog != NULL) delete m_pLog; m_pLog = new wxLogStderr(stdout); #if defined __UNIX__ if(parser.Found(_T("f"))) m_Foreground = true; else m_Foreground = false; #endif if(parser.Found(_T("i"))) { m_Interactive = true; #if defined __UNIX__ m_Foreground = true; #endif } if(parser.Found(_T("g"))) { if (m_pLog != NULL) delete m_pLog; m_pLog = new wxLogStderr(stderr); m_Logtostderr = true; } if(parser.Found(_T("q"))) m_pLog->SetLogLevel(wxLOG_FatalError); if(parser.Found(_T("v"))) m_pLog->SetVerbose(true); wxString str; if(parser.Found(_T("c"), &str)) m_ConfigFileName = str; if(parser.Found(_T("l"), &str) && m_pLogFileStr.Length() <= 0) m_pLogFileStr = str; return true; } //------------------------------------------------------------------------------ // Process help (-h) command line option bool TSApp::OnCmdLineHelp(wxCmdLineParser &parser) { parser.Usage(); return false; } //------------------------------------------------------------------------------ // Process command line options errors bool TSApp::OnCmdLineError(wxCmdLineParser &parser) { parser.Usage(); return false; } //------------------------------------------------------------------------------ // ReadString wxString TSApp::ReadString(wxString const &str) { wxChar cstr[80]; wxString s; wxPrintf(_T("%s: "), str.c_str()); wxScanf(_T("%s"), cstr); s = cstr; return s; } //------------------------------------------------------------------------------ // Interactive mode bool TSApp::Interactive() { wxStringOutputStream out; wxChar cstr[80]; wxString str; wxPrintf(_T("Type \"help\" for all commands.\n")); do { wxPrintf(_T(">")); wxScanf(_T("%s"), cstr); str = cstr; //-------------------------------------------------------- if(str == _T("cl")) { wxPrintf(wxString(_T("-"), 40).c_str()); wxPrintf(_T("\ndumping channels...\n")); wxPrintf(_T(" total: %d\n"), m_pClient->GetChannels()->GetCount()); for(size_t i = 0; i < m_pClient->GetChannels()->GetCount(); i++) wxPrintf(_T("%.3d %s\n"), i, m_pClient->GetChannels()->Item(i)->GetName().c_str()); wxPrintf(_T(" total: %d channels\n"), m_pClient->GetChannels()->GetCount()); } //-------------------------------------------------------- else if(str == _T("pl")) { wxPrintf(wxString(_T("-"), 40).c_str()); wxPrintf(_T("\ndumping players...\n")); wxPrintf(_T(" total: %d\n"), m_pClient->GetPlayers()->GetCount()); for(size_t i = 0; i < m_pClient->GetPlayers()->GetCount(); i++) wxPrintf(_T("%.3d %s\n"), i, m_pClient->GetPlayers()->Item(i)->GetNickname().c_str()); wxPrintf(_T(" total: %d players\n"), m_pClient->GetPlayers()->GetCount()); } //-------------------------------------------------------- else if(str == _T("pcl")) { wxPrintf(wxString(_T("-"), 40).c_str()); wxPrintf(_T("\ndumping players with channels...\n")); wxPrintf(_T(" total: %d\n"), m_pClient->GetPlayers()->GetCount()); for(size_t i = 0; i < m_pClient->GetPlayers()->GetCount(); i++) { wxUint32 chid = m_pClient->GetPlayers()->Item(i)->GetChannelId(); wxString nick = m_pClient->GetPlayers()->Item(i)->GetNickname(); wxString chl = _T("error"); for(size_t j = 0; j < m_pClient->GetChannels()->GetCount(); j++) { if(m_pClient->GetChannels()->Item(j)->GetId() == chid) { chl = m_pClient->GetChannels()->Item(j)->GetName(); break; } } wxPrintf(_T("%.3d %s \t\t %s\n"), i, nick.c_str(), chl.c_str()); } wxPrintf(_T(" total: %d players\n"), m_pClient->GetPlayers()->GetCount()); } //-------------------------------------------------------- else if(str == _T("cc")) { TSChannel ch; wxString str; wxPrintf(_T("create channel...\n")); ch.SetName(ReadString(_T("Name"))); ch.SetTopic(ReadString(_T("Topic"))); ch.SetDescription(ReadString(_T("Description"))); str = ReadString(_T("Password ('.' no pass)")); if(str != _T(".")) ch.SetPassword(str); ch.SetFlags(ReadString(_T("Flags"))); if(m_pClient->CreateChannel(&ch)) wxPrintf(_T("channel created\n")); else wxLogError(_T("%s"),m_pClient->GetLastError().c_str()); } //-------------------------------------------------------- else if(str == _T("mc")) { TSChannel ch; TSChannel *pChl; wxString s,str; wxPrintf(_T("modify channel...\n")); s = ReadString(_T("Name")); pChl = m_pClient->FindChannel(s); if(pChl == NULL) { wxPrintf(_T("channel not found\n")); } else { wxPrintf(_T("edit channel\n")); ch.SetId(pChl->GetId()); ch.SetName(ReadString(_T("Name"))); ch.SetTopic(ReadString(_T("Topic"))); ch.SetDescription(ReadString(_T("Description"))); str = ReadString(_T("Password ('.' no pass)")); if(str != _T(".")) ch.SetPassword(str); ch.SetFlags(ReadString(_T("Flags"))); if(m_pClient->ModifyChannel(&ch)) wxPrintf(_T("channel modified\n")); else wxLogError(_T("%s"),m_pClient->GetLastError().c_str()); } } //-------------------------------------------------------- else if(str == _T("dc")) { wxString s; TSChannel *pChl; wxPrintf(_T("delete channel...\n")); s = ReadString(_T("Name")); pChl = m_pClient->FindChannel(s); if(pChl == NULL) { wxPrintf(_T("channel not found\n")); } else { if(m_pClient->DeleteChannel(pChl)) wxPrintf(_T("channel deleted\n")); else wxLogError(_T("%s"),m_pClient->GetLastError().c_str()); } } //-------------------------------------------------------- else if(str == _T("mv")) { wxString s; TSPlayer ply; TSPlayer *pPly; TSChannel *pChl; wxPrintf(_T("move player...\n")); s = ReadString(_T("Name")); pPly = m_pClient->FindPlayer(s); if(pPly == NULL) { wxPrintf(_T("player not found\n")); } else { s = ReadString(_T("Channel")); pChl = m_pClient->FindChannel(s); if(pChl == NULL) { wxPrintf(_T("channel not found\n")); } else { ply.SetId(pPly->GetId()); ply.SetChannelId(pChl->GetId()); if(m_pClient->MovePlayer(&ply)) wxPrintf(_T("player moved\n")); else wxLogError(_T("%s"),m_pClient->GetLastError().c_str()); } } } //-------------------------------------------------------- else if(str == _T("kick")) { wxString s; TSPlayer ply; TSPlayer *pPly; wxPrintf(_T("kick player...\n")); s = ReadString(_T("Name")); pPly = m_pClient->FindPlayer(s); if(pPly == NULL) { wxPrintf(_T("player not found\n")); } else { s = ReadString(_T("Message")); ply.SetId(pPly->GetId()); if(m_pClient->KickPlayer(&ply,s)) wxPrintf(_T("player kicked\n")); else wxLogError(_T("%s"),m_pClient->GetLastError().c_str()); } } //-------------------------------------------------------- else if(str == _T("exit")) break; //-------------------------------------------------------- else if(str == _T("dump")) { m_pClient->Dump(out); wxPrintf(_T("%s"), out.GetString().c_str()); } //-------------------------------------------------------- else if(str == _T("connect")) { m_pClient->Disconnect(); wxPrintf(_T("connecting...\n")); if(!m_pClient->Connect()) wxLogError(_T("%s, terminating."), m_pClient->GetLastError().c_str()); else wxPrintf(_T("connected\n")); } //-------------------------------------------------------- else if(str == _T("disconnect")) { if(!m_pClient->Disconnect()) wxLogError(_T("%s, terminating."), m_pClient->GetLastError().c_str()); else wxPrintf(_T("disconnected\n")); } //-------------------------------------------------------- else if(str == _T("help")) { wxPrintf(_T("pl show player list\n")); wxPrintf(_T("cl show channel list\n")); wxPrintf(_T("pcl player with channel list\n")); wxPrintf(_T("cc create channel\n")); wxPrintf(_T("dc delete channel\n")); wxPrintf(_T("mv move player\n")); wxPrintf(_T("kick kick player\n")); wxPrintf(_T("mc modify channel\n")); wxPrintf(_T("connect connect to server\n")); wxPrintf(_T("disconnect disconnect from server\n")); wxPrintf(_T("dump full object dump\n")); wxPrintf(_T("exit exit application\n")); } } while(1); return true; } //makes the application class known to wxWidgets for dynamic construction IMPLEMENT_APP_CONSOLE(TSApp)