summaryrefslogtreecommitdiffstats
path: root/tsapp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tsapp.cpp')
-rw-r--r--tsapp.cpp617
1 files changed, 617 insertions, 0 deletions
diff --git a/tsapp.cpp b/tsapp.cpp
new file mode 100644
index 0000000..3818b4c
--- /dev/null
+++ b/tsapp.cpp
@@ -0,0 +1,617 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * Authors: Manuel Mausz (manuel@mausz.at)
16 * Christian Raschko (c.raschko@netcore.at)
17 */
18
19//Header
20#include "tsapp.h"
21#include "tsheaders.h"
22
23//Libraries
24#include <wx/wx.h>
25#include <wx/cmdline.h>
26#include <wx/wfstream.h>
27#include <wx/txtstrm.h>
28#include <wx/sstream.h>
29#if defined(__UNIX__)
30# include <sys/ioctl.h>
31#endif
32
33//------------------------------------------------------------------------------
34// OnInit
35bool TSApp::OnInit()
36{
37 m_pLog = NULL;
38 m_pLogFile = NULL;
39 m_pConfig = NULL;
40 m_pClient = NULL;
41 m_pQuery = NULL;
42 m_ConfigFileName = CONFIG_FILE_NAME;
43
44 if (!wxAppConsole::OnInit())
45 return false;
46
47 return true;
48}
49
50//------------------------------------------------------------------------------
51// OnExit
52int TSApp::OnExit()
53{
54 //cleanup
55 wxAppConsole::OnExit();
56
57 if(m_pLogFile != NULL && m_pLogFile->IsOpened())
58 m_pLogFile->Close();
59
60 if(m_pLogFile != NULL)
61 delete m_pLogFile;
62 m_pLogFile = NULL;
63
64 if(m_pQuery != NULL)
65 delete m_pQuery;
66 m_pQuery = NULL;
67
68 if(m_pClient != NULL)
69 delete m_pClient;
70 m_pClient = NULL;
71
72 if(m_pConfig != NULL)
73 delete m_pConfig;
74 m_pConfig = NULL;
75
76 if(m_pLog != NULL)
77 delete m_pLog;
78 m_pLog = NULL;
79
80 if(m_pQuery != NULL)
81 delete m_pQuery;
82 m_pQuery = NULL;
83
84 return true;
85}
86
87//------------------------------------------------------------------------------
88// Program entry point, replacment for main()
89int TSApp::OnRun()
90{
91 wxStringOutputStream out;
92
93 //UNIX stuff
94 #if defined(__UNIX__)
95 if(!m_Foreground && !m_Interactive)
96 {
97 int pid = fork();
98 if(pid < 0)
99 {
100 wxLogError(_T("can't fork"));
101 return EXIT_FAILURE;
102 }
103 else if(pid != 0)
104 return EXIT_SUCCESS;
105
106 //detach from tty
107 if (!m_Logtostderr)
108 {
109 //close existing file descriptors
110 for (int fd = getdtablesize() - 1; fd >= 0; fd--)
111 close(fd);
112
113 //open stdin on /dev/null
114 open("/dev/null", O_RDWR);
115 }
116 }
117 #endif
118
119 //welcome message
120 wxPrintf(_T("TeamSpeak Client v0.3 (c)2006-2013 Clan-Server.at\n"));
121
122 m_pLog->SetTimestamp(_T("[%x %X]"));
123 wxLog::SetActiveTarget(m_pLog);
124 wxSocketBase::Initialize();
125
126 m_pClient = new TSClient;
127 m_pQuery = new TSQueryThread(m_pClient);
128
129 //load config
130 if(!LoadConfig(m_ConfigFileName))
131 {
132 wxLogError(_T("can't open config file %s"), m_ConfigFileName.c_str());
133 return EXIT_FAILURE;
134 }
135
136 //open logfile
137 if(m_pLogFileStr.Length() > 0 && !m_Logtostderr && (m_pLogFile == NULL || !m_pLogFile->IsOpened()))
138 {
139 m_pLogFile = new wxFFile(m_pLogFileStr.c_str(), _T("a+"));
140 if(!m_pLogFile->IsOpened())
141 {
142 wxLogError(_T("can't open logfile '%s'."), m_pLogFileStr.c_str());
143 return false;
144 }
145 if (m_pLog != NULL)
146 delete m_pLog;
147 m_pLog = new wxLogStderr((FILE *)m_pLogFile->fp());
148 }
149
150 //start query thread
151 m_pQuery->Start();
152
153 //check for interactive mode
154 if(m_Interactive)
155 Interactive();
156 else
157 {
158 while(m_pClient->IsReconnectActive())
159 {
160 if(!m_pClient->IsConnected())
161 {
162 m_pClient->Disconnect();
163 //some status info
164 wxLogMessage(_T("TSServer: connecting to %s:%d..."),
165 m_pClient->GetServer()->GetServerAddress().c_str(),
166 m_pClient->GetServer()->GetPort());
167
168 //connect
169 if(!m_pClient->Connect())
170 {
171 wxLogError(_T("%s, error connecting."), m_pClient->GetLastError().c_str());
172 wxSleep(RECONNECT_TIMEOUT);
173 }
174 else
175 wxLogMessage(_T("TSServer: connection established..."));
176 }
177 wxSleep(1);
178 }
179 }
180
181 wxLogMessage(_T("TSServer: disconnecting..."));
182 m_pClient->Disconnect();
183 m_pQuery->Stop();
184 wxSocketBase::Shutdown();
185 wxLogMessage(_T("TSServer: shutting down successful."));
186 wxLog::SetActiveTarget(NULL);
187 return EXIT_SUCCESS;
188}
189
190//------------------------------------------------------------------------------
191// Load config
192bool TSApp::LoadConfig(wxString const &filename)
193{
194 wxString str;
195 if(!wxFileExists(filename))
196 return false;
197
198 m_pConfig = new wxFileConfig(_T("TSDaemon"),
199 wxEmptyString,
200 filename,
201 filename,
202 wxCONFIG_USE_RELATIVE_PATH);
203
204 m_pConfig->Read(_T("LogFile"), &str, _T(""));
205 if(m_pLogFileStr.Length() <= 0)
206 m_pLogFileStr = str;
207
208 //TSClient
209 m_pConfig->Read(_T("TSPlatform"), &str, _T("Windows XP"));
210 m_pClient->SetPlatform(str);
211
212 m_pConfig->Read(_T("TSVersionNumber"), &str, _T("2.0.32.60"));
213 m_pClient->SetVersionNumber(str);
214
215 TSPlayer *pTSP = new TSPlayer;
216 m_pConfig->Read(_T("TSLoginName"), &str, _T(""));
217 pTSP->SetLoginName(str);
218 m_pConfig->Read(_T("TSLoginPassword"), &str, _T(""));
219 pTSP->SetLoginPassword(str);
220 m_pConfig->Read(_T("TSNickname"), &str, _T(""));
221 pTSP->SetNickname(str);
222 //now the TSClient takes care of the pointer.
223 m_pClient->SetPlayer(pTSP);
224
225 TSServer *pTSS = new TSServer;
226 m_pConfig->Read(_T("TSServerAddress"), &str, _T(""));
227 pTSS->SetServerAddress(str);
228 long l;
229 m_pConfig->Read(_T("TSPort"), &l, 0);
230 if(!pTSS->SetPort(l))
231 wxLogError(_T("port, %s"), pTSS->GetLastError().c_str());
232
233 //now the TSClient takes care of the pointer.
234 m_pClient->SetServer(pTSS);
235
236 m_pConfig->Read(_T("ServerAddress"), &str, _T(""));
237 m_pQuery->SetServerAddress(str);
238
239 m_pConfig->Read(_T("AllowedAddresses"), &str, _T(""));
240 m_pQuery->SetAllowedAddresses(str);
241
242 m_pConfig->Read(_T("Port"), &l, 0);
243 if(!m_pQuery->SetPort(l))
244 wxLogError(_T("port, %s"), m_pQuery->GetLastError().c_str());
245
246 m_pConfig->Read(_T("Password"), &str, _T(""));
247 if(!m_pQuery->SetPassword(str))
248 wxLogError(_T("password, %s"), m_pQuery->GetLastError().c_str());
249
250 return true;
251}
252
253//------------------------------------------------------------------------------
254// Set parser line description
255void TSApp::OnInitCmdLine(wxCmdLineParser &parser)
256{
257 //declare CmdLineParser
258 static const wxCmdLineEntryDesc cmdLineDesc[] =
259 {
260 { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show this help message"),
261 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
262 { wxCMD_LINE_SWITCH, _T("i"), _T("interactive"), _T("interactive mode"),
263 wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
264 { wxCMD_LINE_SWITCH, _T("v"), _T("verbose"), _T("be verbose") ,
265 wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL},
266 { wxCMD_LINE_SWITCH, _T("q"), _T("quiet"), _T("be quiet") ,
267 wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL},
268 #if defined(__UNIX__)
269 { wxCMD_LINE_SWITCH, _T("f"), _T("foreground"), _T("run in foreground mode"),
270 wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL},
271 #endif
272 { wxCMD_LINE_SWITCH, _T("g"), _T("logtostderr"), _T("log everything to stderr"),
273 wxCMD_LINE_VAL_NONE,wxCMD_LINE_PARAM_OPTIONAL},
274 { wxCMD_LINE_OPTION, _T("c"), _T("config"), _T("path to config file"),
275 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
276 { wxCMD_LINE_OPTION, _T("l"), _T("logfile"), _T("path to log file"),
277 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
278 { wxCMD_LINE_NONE, NULL, NULL, NULL, (wxCmdLineParamType)0, 0 } //ends list
279 };
280 parser.SetDesc(cmdLineDesc);
281
282 //no long options on windows
283 #ifdef __WINDOWS__
284 parser.DisableLongOptions();
285 #endif
286}
287
288//------------------------------------------------------------------------------
289// Process command line options
290bool TSApp::OnCmdLineParsed(wxCmdLineParser &parser)
291{
292 m_Interactive = false;
293 m_Foreground = false;
294 m_Logtostderr = false;
295
296 /* Create and hook logtarget in */
297 if (m_pLog != NULL)
298 delete m_pLog;
299 m_pLog = new wxLogStderr(stdout);
300
301 #if defined __UNIX__
302 if(parser.Found(_T("f")))
303 m_Foreground = true;
304 else
305 m_Foreground = false;
306 #endif
307
308 if(parser.Found(_T("i")))
309 {
310 m_Interactive = true;
311 #if defined __UNIX__
312 m_Foreground = true;
313 #endif
314 }
315
316 if(parser.Found(_T("g")))
317 {
318 if (m_pLog != NULL)
319 delete m_pLog;
320 m_pLog = new wxLogStderr(stderr);
321 m_Logtostderr = true;
322 }
323
324 if(parser.Found(_T("q")))
325 m_pLog->SetLogLevel(wxLOG_FatalError);
326
327 if(parser.Found(_T("v")))
328 m_pLog->SetVerbose(true);
329
330 wxString str;
331 if(parser.Found(_T("c"), &str))
332 m_ConfigFileName = str;
333
334 if(parser.Found(_T("l"), &str) && m_pLogFileStr.Length() <= 0)
335 m_pLogFileStr = str;
336
337 return true;
338}
339
340//------------------------------------------------------------------------------
341// Process help (-h) command line option
342bool TSApp::OnCmdLineHelp(wxCmdLineParser &parser)
343{
344 parser.Usage();
345 return false;
346}
347
348//------------------------------------------------------------------------------
349// Process command line options errors
350bool TSApp::OnCmdLineError(wxCmdLineParser &parser)
351{
352 parser.Usage();
353 return false;
354}
355
356//------------------------------------------------------------------------------
357// ReadString
358wxString TSApp::ReadString(wxString const &str)
359{
360 wxChar cstr[80];
361 wxString s;
362 wxPrintf(_T("%s: "), str.c_str());
363 wxScanf(_T("%s"), cstr);
364 s = cstr;
365 return s;
366}
367
368//------------------------------------------------------------------------------
369// Interactive mode
370bool TSApp::Interactive()
371{
372 wxStringOutputStream out;
373 wxChar cstr[80];
374 wxString str;
375
376 wxPrintf(_T("Type \"help\" for all commands.\n"));
377 do
378 {
379 wxPrintf(_T(">"));
380 wxScanf(_T("%s"), cstr);
381 str = cstr;
382 //--------------------------------------------------------
383 if(str == _T("cl"))
384 {
385 wxPrintf(wxString(_T("-"), 40).c_str());
386 wxPrintf(_T("\ndumping channels...\n"));
387 wxPrintf(_T(" total: %d\n"), m_pClient->GetChannels()->GetCount());
388
389 for(size_t i = 0; i < m_pClient->GetChannels()->GetCount(); i++)
390 wxPrintf(_T("%.3d %s\n"), i, m_pClient->GetChannels()->Item(i)->GetName().c_str());
391 wxPrintf(_T(" total: %d channels\n"), m_pClient->GetChannels()->GetCount());
392 }
393 //--------------------------------------------------------
394 else if(str == _T("pl"))
395 {
396 wxPrintf(wxString(_T("-"), 40).c_str());
397 wxPrintf(_T("\ndumping players...\n"));
398 wxPrintf(_T(" total: %d\n"), m_pClient->GetPlayers()->GetCount());
399
400 for(size_t i = 0; i < m_pClient->GetPlayers()->GetCount(); i++)
401 wxPrintf(_T("%.3d %s\n"), i, m_pClient->GetPlayers()->Item(i)->GetNickname().c_str());
402 wxPrintf(_T(" total: %d players\n"), m_pClient->GetPlayers()->GetCount());
403 }
404 //--------------------------------------------------------
405 else if(str == _T("pcl"))
406 {
407 wxPrintf(wxString(_T("-"), 40).c_str());
408 wxPrintf(_T("\ndumping players with channels...\n"));
409 wxPrintf(_T(" total: %d\n"), m_pClient->GetPlayers()->GetCount());
410
411 for(size_t i = 0; i < m_pClient->GetPlayers()->GetCount(); i++)
412 {
413 wxUint32 chid = m_pClient->GetPlayers()->Item(i)->GetChannelId();
414 wxString nick = m_pClient->GetPlayers()->Item(i)->GetNickname();
415 wxString chl = _T("error");
416
417 for(size_t j = 0; j < m_pClient->GetChannels()->GetCount(); j++)
418 {
419 if(m_pClient->GetChannels()->Item(j)->GetId() == chid)
420 {
421 chl = m_pClient->GetChannels()->Item(j)->GetName();
422 break;
423 }
424 }
425 wxPrintf(_T("%.3d %s \t\t %s\n"), i, nick.c_str(), chl.c_str());
426 }
427 wxPrintf(_T(" total: %d players\n"), m_pClient->GetPlayers()->GetCount());
428 }
429 //--------------------------------------------------------
430 else if(str == _T("cc"))
431 {
432 TSChannel ch;
433 wxString str;
434
435 wxPrintf(_T("create channel...\n"));
436 ch.SetName(ReadString(_T("Name")));
437 ch.SetTopic(ReadString(_T("Topic")));
438 ch.SetDescription(ReadString(_T("Description")));
439 str = ReadString(_T("Password ('.' no pass)"));
440 if(str != _T("."))
441 ch.SetPassword(str);
442 ch.SetFlags(ReadString(_T("Flags")));
443
444 if(m_pClient->CreateChannel(&ch))
445 wxPrintf(_T("channel created\n"));
446 else
447 wxLogError(_T("%s"),m_pClient->GetLastError().c_str());
448 }
449 //--------------------------------------------------------
450 else if(str == _T("mc"))
451 {
452 TSChannel ch;
453 TSChannel *pChl;
454 wxString s,str;
455 wxPrintf(_T("modify channel...\n"));
456
457 s = ReadString(_T("Name"));
458 pChl = m_pClient->FindChannel(s);
459 if(pChl == NULL)
460 {
461 wxPrintf(_T("channel not found\n"));
462 }
463 else
464 {
465 wxPrintf(_T("edit channel\n"));
466 ch.SetId(pChl->GetId());
467 ch.SetName(ReadString(_T("Name")));
468 ch.SetTopic(ReadString(_T("Topic")));
469 ch.SetDescription(ReadString(_T("Description")));
470 str = ReadString(_T("Password ('.' no pass)"));
471 if(str != _T("."))
472 ch.SetPassword(str);
473 ch.SetFlags(ReadString(_T("Flags")));
474
475 if(m_pClient->ModifyChannel(&ch))
476 wxPrintf(_T("channel modified\n"));
477 else
478 wxLogError(_T("%s"),m_pClient->GetLastError().c_str());
479 }
480 }
481 //--------------------------------------------------------
482 else if(str == _T("dc"))
483 {
484 wxString s;
485 TSChannel *pChl;
486
487 wxPrintf(_T("delete channel...\n"));
488 s = ReadString(_T("Name"));
489
490 pChl = m_pClient->FindChannel(s);
491 if(pChl == NULL)
492 {
493 wxPrintf(_T("channel not found\n"));
494 }
495 else
496 {
497 if(m_pClient->DeleteChannel(pChl))
498 wxPrintf(_T("channel deleted\n"));
499 else
500 wxLogError(_T("%s"),m_pClient->GetLastError().c_str());
501 }
502 }
503 //--------------------------------------------------------
504 else if(str == _T("mv"))
505 {
506 wxString s;
507 TSPlayer ply;
508 TSPlayer *pPly;
509 TSChannel *pChl;
510
511 wxPrintf(_T("move player...\n"));
512 s = ReadString(_T("Name"));
513
514 pPly = m_pClient->FindPlayer(s);
515 if(pPly == NULL)
516 {
517 wxPrintf(_T("player not found\n"));
518 }
519 else
520 {
521 s = ReadString(_T("Channel"));
522 pChl = m_pClient->FindChannel(s);
523 if(pChl == NULL)
524 {
525 wxPrintf(_T("channel not found\n"));
526 }
527 else
528 {
529 ply.SetId(pPly->GetId());
530 ply.SetChannelId(pChl->GetId());
531
532 if(m_pClient->MovePlayer(&ply))
533 wxPrintf(_T("player moved\n"));
534 else
535 wxLogError(_T("%s"),m_pClient->GetLastError().c_str());
536 }
537 }
538 }
539 //--------------------------------------------------------
540 else if(str == _T("kick"))
541 {
542 wxString s;
543 TSPlayer ply;
544 TSPlayer *pPly;
545
546 wxPrintf(_T("kick player...\n"));
547 s = ReadString(_T("Name"));
548
549 pPly = m_pClient->FindPlayer(s);
550 if(pPly == NULL)
551 {
552 wxPrintf(_T("player not found\n"));
553 }
554 else
555 {
556 s = ReadString(_T("Message"));
557
558 ply.SetId(pPly->GetId());
559
560 if(m_pClient->KickPlayer(&ply,s))
561 wxPrintf(_T("player kicked\n"));
562 else
563 wxLogError(_T("%s"),m_pClient->GetLastError().c_str());
564 }
565
566 }
567 //--------------------------------------------------------
568 else if(str == _T("exit"))
569 break;
570 //--------------------------------------------------------
571 else if(str == _T("dump"))
572 {
573 m_pClient->Dump(out);
574 wxPrintf(_T("%s"), out.GetString().c_str());
575 }
576 //--------------------------------------------------------
577 else if(str == _T("connect"))
578 {
579 m_pClient->Disconnect();
580 wxPrintf(_T("connecting...\n"));
581 if(!m_pClient->Connect())
582 wxLogError(_T("%s, terminating."), m_pClient->GetLastError().c_str());
583 else
584 wxPrintf(_T("connected\n"));
585 }
586 //--------------------------------------------------------
587 else if(str == _T("disconnect"))
588 {
589 if(!m_pClient->Disconnect())
590 wxLogError(_T("%s, terminating."), m_pClient->GetLastError().c_str());
591 else
592 wxPrintf(_T("disconnected\n"));
593 }
594 //--------------------------------------------------------
595 else if(str == _T("help"))
596 {
597 wxPrintf(_T("pl show player list\n"));
598 wxPrintf(_T("cl show channel list\n"));
599 wxPrintf(_T("pcl player with channel list\n"));
600 wxPrintf(_T("cc create channel\n"));
601 wxPrintf(_T("dc delete channel\n"));
602 wxPrintf(_T("mv move player\n"));
603 wxPrintf(_T("kick kick player\n"));
604 wxPrintf(_T("mc modify channel\n"));
605 wxPrintf(_T("connect connect to server\n"));
606 wxPrintf(_T("disconnect disconnect from server\n"));
607 wxPrintf(_T("dump full object dump\n"));
608 wxPrintf(_T("exit exit application\n"));
609 }
610 } while(1);
611
612 return true;
613}
614
615//makes the application class known to wxWidgets for dynamic construction
616IMPLEMENT_APP_CONSOLE(TSApp)
617