fgms 0.11.8
The
FlightGear MultiPlayer Server
project
fg_cli.cxx
Go to the documentation of this file.
1 /**
2  * @file fg_cli.hxx
3  * @author Oliver Schroeder
4  */
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U$
19 //
20 // Copyright (C) 2013 Oliver Schroeder
21 //
22 
23 /**
24  * @class FG_CLI
25  * @brief cisco like command line interface
26  *
27  */
28 
29 #include <fg_util.hxx>
30 #include <fg_cli.hxx>
31 #include <fg_common.hxx>
32 
34 (
35  FG_SERVER* fgms,
36  int fd
37 ): CLI(fd)
38 {
39  this->fgms = fgms;
40  this->setup ();
41 }
42 
43 void
45 ()
46 {
47  typedef Command<CLI>::cpp_callback_func callback_ptr;
48  typedef Command<CLI>::cpp_callback_func callback_ptr;
49  typedef CLI::cpp_auth_func auth_callback;
50  typedef CLI::cpp_enable_func enable_callback;
51  Command<CLI>* c;
52  // Command<CLI>* c2;
53 
54  //////////////////////////////////////////////////
55  // general setup
56  //////////////////////////////////////////////////
57  set_hostname (this->fgms->m_ServerName.c_str());
58  set_banner (
59  "\r\n"
60  "------------------------------------------------\r\n"
61  "FlightGear Multiplayer Server CLI\r\n"
62  "------------------------------------------------\r\n"
63  );
64  //////////////////////////////////////////////////
65  // setup authentication (if required)
66  //////////////////////////////////////////////////
67  if (fgms->m_AdminUser != "")
68  {
69  allow_user ( fgms->m_AdminUser.c_str(), fgms->m_AdminPass.c_str() );
70  }
71  if (fgms->m_AdminEnable != "")
72  {
73  allow_enable (fgms->m_AdminEnable.c_str());
74  }
75  //////////////////////////////////////////////////
76  // general commands
77  //////////////////////////////////////////////////
78  c = new Command<CLI> (
79  this,
80  "show",
83  "show system information"
84  );
85  register_command (c);
86 
87  register_command ( new Command<CLI> (
88  this,
89  "stats",
90  static_cast<callback_ptr> (&FG_CLI::cmd_show_stats),
91  LIBCLI::UNPRIVILEGED,
93  "Show statistical information"
94  ), c);
95 
96  register_command ( new Command<CLI> (
97  this,
98  "version",
99  static_cast<callback_ptr> (&FG_CLI::cmd_show_version),
100  LIBCLI::UNPRIVILEGED,
102  "Show running version information"
103  ), c);
104 
105  register_command ( new Command<CLI> (
106  this,
107  "uptime",
108  static_cast<callback_ptr> (&FG_CLI::cmd_show_uptime),
109  LIBCLI::UNPRIVILEGED,
111  "Show uptime information"
112  ), c);
113 
114  register_command (new Command<CLI> (
115  this,
116  "blacklist",
117  static_cast<callback_ptr> (&FG_CLI::cmd_blacklist_show),
118  LIBCLI::UNPRIVILEGED,
120  "Show entries in the blacklist"
121  ), c);
122 
123  register_command (new Command<CLI> (
124  this,
125  "crossfeeds",
126  static_cast<callback_ptr> (&FG_CLI::cmd_crossfeed_show),
127  LIBCLI::UNPRIVILEGED,
129  "Show entries in the crossfeeds"
130  ), c);
131 
132  register_command (new Command<CLI> (
133  this,
134  "relay",
135  static_cast<callback_ptr> (&FG_CLI::cmd_relay_show),
136  LIBCLI::UNPRIVILEGED,
138  "Show list of relays"
139  ), c);
140 
141  register_command (new Command<CLI> (
142  this,
143  "tracker",
144  static_cast<callback_ptr> (&FG_CLI::cmd_tracker_show),
145  LIBCLI::UNPRIVILEGED,
147  "Show status of tracker"
148  ), c);
149 
150  register_command (new Command<CLI> (
151  this,
152  "users",
153  static_cast<callback_ptr> (&FG_CLI::cmd_user_show),
154  LIBCLI::UNPRIVILEGED,
156  "Show list of users"
157  ), c);
158 
159  register_command (new Command<CLI> (
160  this,
161  "die",
162  static_cast<callback_ptr> (&FG_CLI::cmd_fgms_die),
164  LIBCLI::MODE_EXEC,
165  "force fgms to exit"
166  ));
167 
168  //////////////////////////////////////////////////
169  // modify blacklist
170  //////////////////////////////////////////////////
171  c = new Command<CLI> (
172  this,
173  "blacklist",
176  "show/modify blacklist"
177  );
178  register_command (c);
179  register_command (new Command<CLI> (
180  this,
181  "delete",
182  static_cast<callback_ptr> (&FG_CLI::cmd_blacklist_delete),
183  LIBCLI::PRIVILEGED,
184  LIBCLI::MODE_CONFIG,
185  "Show entries in the blacklist"
186  ), c);
187  register_command (new Command<CLI> (
188  this,
189  "add",
190  static_cast<callback_ptr> (&FG_CLI::cmd_blacklist_add),
191  LIBCLI::PRIVILEGED,
192  LIBCLI::MODE_CONFIG,
193  "Show entries in the blacklist"
194  ), c);
195 
196  //////////////////////////////////////////////////
197  // modify crossfeeds
198  //////////////////////////////////////////////////
199  c = new Command<CLI> (
200  this,
201  "crossfeed",
204  "modify crossfeeds"
205  );
206  register_command (c);
207  register_command (new Command<CLI> (
208  this,
209  "delete",
210  static_cast<callback_ptr> (&FG_CLI::cmd_crossfeed_delete),
211  LIBCLI::PRIVILEGED,
212  LIBCLI::MODE_CONFIG,
213  "Delete crossfeeds"
214  ), c);
215  register_command (new Command<CLI> (
216  this,
217  "add",
218  static_cast<callback_ptr> (&FG_CLI::cmd_crossfeed_add),
219  LIBCLI::PRIVILEGED,
220  LIBCLI::MODE_CONFIG,
221  "Add crossfeeds"
222  ), c);
223 
224  //////////////////////////////////////////////////
225  // modify relays
226  //////////////////////////////////////////////////
227  c = new Command<CLI> (
228  this,
229  "relay",
232  "modify relays"
233  );
234  register_command (c);
235  register_command (new Command<CLI> (
236  this,
237  "delete",
238  static_cast<callback_ptr> (&FG_CLI::cmd_relay_delete),
239  LIBCLI::PRIVILEGED,
240  LIBCLI::MODE_CONFIG,
241  "Delete relay"
242  ), c);
243  register_command (new Command<CLI> (
244  this,
245  "add",
246  static_cast<callback_ptr> (&FG_CLI::cmd_relay_add),
247  LIBCLI::PRIVILEGED,
248  LIBCLI::MODE_CONFIG,
249  "Add relay"
250  ), c);
251 
252 }
253 
254 bool
256 (
257  char* argv
258 )
259 {
260  if (! argv)
261  return false;
262  size_t l = strlen (argv);
263  if (argv[l-1] == '?')
264  return true;
265  return false;
266 }
267 
268 int
270 (
271  UNUSED(char *command),
272  UNUSED(char *argv[]),
273  UNUSED(int argc)
274 )
275 {
276  time_t difftime;
277  time_t now;
278  uint64_t accumulated_sent = 0;
279  uint64_t accumulated_rcvd = 0;
280  uint64_t accumulated_sent_pkts = 0;
281  uint64_t accumulated_rcvd_pkts = 0;
282 
283  if (argc > 0)
284  {
285  client << "<cr>" << CRLF;
286  return (0);
287  }
288  now = time(0);
289  difftime = now - fgms->m_Uptime;
290  cmd_show_version (command, argv, argc);
291  client << CRLF;
292  client << "I have " << fgms->m_BlackList.Size () << " entries in my blacklist"
293  << CRLF; if (check_pager()) return 0;
294  client << "I have " << fgms->m_CrossfeedList.Size () << " crossfeeds"
295  << CRLF; if (check_pager()) return 0;
296  client << "I have " << fgms->m_RelayList.Size () << " relays"
297  << CRLF; if (check_pager()) return 0;
298  client << "I have " << fgms->m_PlayerList.Size () << " users ("
299  << fgms->m_LocalClients << " local, "
300  << fgms->m_RemoteClients << " remote, "
301  << fgms->m_NumMaxClients << " max)"
302  << CRLF; if (check_pager()) return 0;
303  client << "Sent counters:" << CRLF; if (check_pager()) return 0;
304  client << " " << left << setfill(' ') << setw(22)
305  << "to crossfeeds:"
306  << fgms->m_CrossfeedList.PktsSent << " packets"
307  << " (" << fgms->m_CrossfeedList.PktsSent / difftime << "/s)"
308  << " / " << byte_counter (fgms->m_CrossfeedList.BytesSent)
309  << " (" << byte_counter ((double) fgms->m_CrossfeedList.BytesSent / difftime) << "/s)"
310  << CRLF; if (check_pager()) return 0;
311  client << " " << left << setfill(' ') << setw(22)
312  << "to relays:"
313  << fgms->m_RelayList.PktsSent << " packets"
314  << " (" << fgms->m_RelayList.PktsSent / difftime << "/s)"
315  << " / " << byte_counter (fgms->m_RelayList.BytesSent)
316  << " (" << byte_counter ((double) fgms->m_RelayList.BytesSent / difftime) << "/s)"
317  << CRLF; if (check_pager()) return 0;
318  client << " " << left << setfill(' ') << setw(22)
319  << "to users:"
320  << fgms->m_PlayerList.PktsSent << " packets"
321  << " (" << fgms->m_PlayerList.PktsSent / difftime << "/s)"
322  << " / " << byte_counter (fgms->m_PlayerList.BytesSent)
323  << " (" << byte_counter ((double) fgms->m_PlayerList.BytesSent / difftime) << "/s)"
324  << CRLF; if (check_pager()) return 0;
325  client << "Receive counters:" << CRLF; if (check_pager()) return 0;
326  client << " " << left << setfill(' ') << setw(22)
327  << "errors:"
328  << "invalid packets:" << fgms->m_PacketsInvalid
329  << " rejected:" << fgms->m_BlackRejected
330  << " unknown relay:" << fgms->m_UnknownRelay
331  << CRLF; if (check_pager()) return 0;
332  client << " " << left << setfill(' ') << setw(22)
333  << "valid data:"
334  << "pos data:" << fgms->m_PositionData
335  << " other:" << fgms->m_NotPosData
336  << CRLF; if (check_pager()) return 0;
337  client << " " << left << setfill(' ') << setw(22)
338  << "tracker:"
339  << "connects:" << fgms->m_TrackerConnect
340  << " disconnects:" << fgms->m_TrackerDisconnect
341  << " positions:" << fgms->m_TrackerPosition
342  << CRLF; if (check_pager()) return 0;
343  client << " " << left << setfill(' ') << setw(22)
344  << "admin connections:" << fgms->m_AdminReceived
345  << CRLF; if (check_pager()) return 0;
346  float telnet_per_second;
347  if (fgms->m_TelnetReceived)
348  telnet_per_second = (float) fgms->m_TelnetReceived / (time(0) - fgms->m_Uptime);
349  else
350  telnet_per_second = 0;
351  client << " " << left << setfill(' ') << setw(22)
352  << "telnet connections: "
353  << fgms->m_TelnetReceived
354  << " (" << setprecision(2) << telnet_per_second << " t/s)"
355  << CRLF; if (check_pager()) return 0;
356  client << " " << left << setfill(' ') << setw(22)
357  << "blacklist:"
358  << fgms->m_BlackList.PktsRcvd << " packets"
359  << " (" << fgms->m_BlackList.PktsRcvd / difftime << "/s)"
360  << " / " << byte_counter (fgms->m_BlackList.BytesRcvd)
361  << " (" << byte_counter ((double) fgms->m_BlackList.BytesRcvd / difftime) << "/s)"
362  << CRLF; if (check_pager()) return 0;
363  client << " " << left << setfill(' ') << setw(22)
364  << "relays:"
365  << fgms->m_RelayList.PktsRcvd << " packets"
366  << " (" << fgms->m_RelayList.PktsRcvd / difftime << "/s)"
367  << " / " << byte_counter (fgms->m_RelayList.BytesRcvd)
368  << " (" << byte_counter ((double) fgms->m_RelayList.BytesRcvd / difftime) << "/s)"
369  << CRLF; if (check_pager()) return 0;
370  client << " " << left << setfill(' ') << setw(22)
371  << "users:"
372  << fgms->m_PlayerList.PktsRcvd << " packets"
373  << " (" << fgms->m_PlayerList.PktsRcvd / difftime << "/s)"
374  << " / " << byte_counter (fgms->m_PlayerList.BytesRcvd)
375  << " (" << byte_counter ((double) fgms->m_PlayerList.BytesRcvd / difftime) << "/s)"
376  << CRLF; if (check_pager()) return 0;
377  accumulated_sent += fgms->m_CrossfeedList.BytesSent;
378  accumulated_sent_pkts += fgms->m_CrossfeedList.PktsSent;
379  accumulated_sent += fgms->m_RelayList.BytesSent;
380  accumulated_sent_pkts += fgms->m_RelayList.PktsSent;
381  accumulated_sent += fgms->m_PlayerList.BytesSent;
382  accumulated_sent_pkts += fgms->m_PlayerList.PktsSent;
383  accumulated_rcvd += fgms->m_BlackList.BytesRcvd;
384  accumulated_rcvd_pkts += fgms->m_BlackList.PktsRcvd;
385  accumulated_rcvd += fgms->m_RelayList.BytesRcvd;
386  accumulated_rcvd_pkts += fgms->m_RelayList.PktsRcvd;
387  accumulated_rcvd += fgms->m_PlayerList.BytesRcvd;
388  accumulated_rcvd_pkts += fgms->m_PlayerList.PktsRcvd;
389  client << "Totals:" << CRLF; if (check_pager()) return 0;
390  client << " " << left << setfill(' ') << setw(22)
391  << "sent:"
392  << accumulated_sent_pkts << " packets"
393  << " (" << accumulated_sent_pkts / difftime << "/s)"
394  << " / " << byte_counter (accumulated_sent)
395  << " (" << byte_counter ((double) accumulated_sent / difftime) << "/s)"
396  << CRLF; if (check_pager()) return 0;
397 
398  client << " " << left << setfill(' ') << setw(22)
399  << "received:"
400  << accumulated_rcvd_pkts << " packets"
401  << " (" << accumulated_rcvd_pkts / difftime << "/s)"
402  << " / " << byte_counter (accumulated_rcvd)
403  << " (" << byte_counter ((double) accumulated_rcvd / difftime) << "/s)"
404  << CRLF; if (check_pager()) return 0;
405  return (0);
406 }
407 
408 int
410 (
411  UNUSED(char *command),
412  UNUSED(char *argv[]),
413  UNUSED(int argc)
414 )
415 {
416  if (argc > 0)
417  {
418  if (strcmp (argv[0], "?") == 0)
419  {
420  client << "<cr>" << CRLF;
421  }
422  return (0);
423  }
424  fgms->m_WantExit = true;
425  return LIBCLI::QUIT;
426 }
427 
428 int
430 (
431  UNUSED(char *command),
432  UNUSED(char *argv[]),
433  UNUSED(int argc)
434 )
435 {
436  if (argc > 0)
437  {
438  if (strcmp (argv[0], "?") == 0)
439  {
440  client << "<cr>" << CRLF;
441  }
442  return (0);
443  }
444  client << "UP since " << timestamp_to_datestr(fgms->m_Uptime)
445  << "(" << timestamp_to_days(fgms->m_Uptime) << ")" << CRLF;
446  return (0);
447 }
448 
449 int
451 (
452  UNUSED(char *command),
453  UNUSED(char *argv[]),
454  UNUSED(int argc)
455 )
456 {
457  if (argc > 0)
458  {
459  if (strcmp (argv[0], "?") == 0)
460  {
461  client << "<cr>" << CRLF;
462  }
463  return (0);
464  }
465  string s;
466  if (fgms->m_IamHUB)
467  s = "HUB";
468  else
469  s = "LEAVE";
470  client << "This is " << fgms->m_ServerName << CRLF;
471  client << "FlightGear Multiplayer " << s << " Server version " << VERSION << CRLF;
472  client << "using protocol version v"
473  << fgms->m_ProtoMajorVersion << "." << fgms->m_ProtoMinorVersion << CRLF;
474  if (fgms->m_IsTracked)
475  client << "This server is tracked: " << fgms->m_Tracker->GetTrackerServer() << CRLF;
476  else
477  client << "This server is NOT tracked" << CRLF;
478  cmd_show_uptime (command, argv, argc);
479  return (0);
480 }
481 
482 //////////////////////////////////////////////////
483 /**
484  * @brief Show Blacklist
485  *
486  * possible arguments:
487  * show blacklist ?
488  * show blacklist <cr>
489  * show blacklist ID
490  * show blacklist IP-Address
491  * show blacklist [...] brief
492  */
493 int
495 (
496  char *command,
497  char *argv[],
498  int argc
499 )
500 {
501  size_t ID = 0;
502  int ID_invalid = -1;
503  netAddress Address ("0.0.0.0", 0);
504  bool Brief = false;
505  size_t EntriesFound = 0;
506  for (int i=0; i < argc; i++)
507  {
508  ID = StrToNum<size_t> ( argv[0], ID_invalid );
509  if (ID_invalid)
510  ID = 0;
511  switch (i)
512  {
513  case 0: // ID or IP or 'brief' or '?'
514  if ( need_help (argv[i]) )
515  {
516  client << " " << left << setfill(' ') << setw(22)
517  << "brief" << "show brief listing" << CRLF;
518  client << " " << left << setfill(' ') << setw(22)
519  << "ID" << "show entry with ID" << CRLF;
520  client << " " << left << setfill(' ') << setw(22)
521  << "IP" << "show entry with IP-Address" << CRLF;
522  client << " " << left << setfill(' ') << setw(22)
523  << "<cr>" << "show long listing" << CRLF;
524  client << " " << left << setfill(' ') << setw(22)
525  << "|" << "output modifier" << CRLF;
526  return (0);
527  }
528  else if (strncmp (argv[0], "brief", strlen (argv[i])) == 0)
529  {
530  Brief = true;
531  }
532  else if (ID == 0)
533  {
534  Address.set (argv[0], 0);
535  if (Address.getIP() == 0)
536  {
537  client << "% invalid IP address" << CRLF;
538  return (1);
539  }
540  }
541  break;
542  case 1: // 'brief' or '?'
543  if ( need_help (argv[i]) )
544  {
545  if (! Brief)
546  {
547  client << " " << left << setfill(' ') << setw(22)
548  << "brief" << "show brief listing" << CRLF;
549  }
550  client << " " << left << setfill(' ') << setw(22)
551  << "<cr>" << "show long listing" << CRLF;
552  client << " " << left << setfill(' ') << setw(22)
553  << "|" << "output modifier" << CRLF;
554  return (0);
555  }
556  else if (strncmp (argv[1], "brief", strlen (argv[0])) == 0)
557  {
558  Brief = true;
559  }
560  break;
561  default:
562  client << "% invalid argument" << CRLF;
563  break;
564  }
565  }
566  int Count = fgms->m_BlackList.Size ();
567  FG_ListElement Entry("");
568  client << CRLF;
569  time_t difftime;
570  time_t now;
571  now = time(0);
572  difftime = now - fgms->m_Uptime;
573  client << fgms->m_BlackList.Name << ":" << CRLF;
574  client << CRLF;
575  for (int i = 0; i < Count; i++)
576  {
577  Entry = fgms->m_BlackList[i];
578  if ( (ID == 0) && (Address.getIP() != 0) )
579  { // only list matching entries
580  if (Entry.Address != Address)
581  continue;
582  }
583  else if (ID)
584  {
585  if (Entry.ID != ID)
586  continue;
587  }
588  EntriesFound++;
589  client << "ID " << Entry.ID << ": "
590  << Entry.Address.getHost() << " : " << Entry.Name
591  << CRLF; if (check_pager()) return 0;
592  if (Brief == true)
593  {
594  continue;
595  }
596  string expire = "NEVER";
597  if (Entry.Timeout != 0)
598  {
599  expire = NumToStr (Entry.Timeout, 0) + " seconds";
600  }
601  client << " entered : " << timestamp_to_datestr (Entry.JoinTime)
602  << CRLF; if (check_pager()) return 0;
603  client << " last seen : " << timestamp_to_days (Entry.LastSeen)
604  << CRLF; if (check_pager()) return 0;
605  client << " rcvd packets : " << Entry.PktsRcvd
606  << CRLF; if (check_pager()) return 0;
607  client << " rcvd bytes : " << byte_counter (Entry.BytesRcvd)
608  << CRLF; if (check_pager()) return 0;
609  client << " expire in : " << expire
610  << CRLF; if (check_pager()) return 0;
611  }
612  if (EntriesFound)
613  client << CRLF; if (check_pager()) return 0;
614  client << EntriesFound << " entries found" << CRLF; if (check_pager()) return 0;
615  if (EntriesFound)
616  {
617  client << "Total rcvd: "
618  << fgms->m_BlackList.PktsRcvd << " packets"
619  << " (" << fgms->m_BlackList.PktsRcvd / difftime << "/s)"
620  << " / " << byte_counter (fgms->m_BlackList.BytesRcvd)
621  << " (" << byte_counter ((double) (fgms->m_BlackList.BytesRcvd/difftime)) << "/s)"
622  << CRLF; if (check_pager()) return 0;
623  }
624  return 0;
625 }
626 
627 //////////////////////////////////////////////////
628 /**
629  * @brief Delete Blacklist entry
630  *
631  * ONLY in config mode
632  *
633  * possible arguments:
634  * blacklist delete ?
635  * blacklist delete ID
636  * blacklist delete IP-Address
637  * blacklist delete [...] <cr>
638  */
639 int
641 (
642  char *command,
643  char *argv[],
644  int argc
645 )
646 {
647  size_t ID = 0;
648  int ID_invalid = -1;
649  netAddress Address;
650  ItList Entry;
651  for (int i=0; i < argc; i++)
652  {
653  ID = StrToNum<size_t> ( argv[0], ID_invalid );
654  if (ID_invalid)
655  ID = 0;
656  switch (i)
657  {
658  case 0: // ID or IP or 'brief' or '?'
659  if ( need_help (argv[i]) )
660  {
661  client << " " << left << setfill(' ') << setw(22)
662  << "ID" << "delete entry with ID" << CRLF;
663  client << " " << left << setfill(' ') << setw(22)
664  << "IP" << "delete entry with IP address" << CRLF;
665  return (0);
666  }
667  else if (ID == 0)
668  {
669  Address.set (argv[0], 0);
670  if (Address.getIP() == 0)
671  {
672  client << "% invalid IP address" << CRLF;
673  return (1);
674  }
675  }
676  break;
677  case 1: // only '?'
678  if ( need_help (argv[i]) )
679  {
680  client << " " << left << setfill(' ') << setw(22)
681  << "<cr>" << "delete entry" << CRLF;
682  return 1;
683  }
684  default:
685  client << "% invalid argument" << CRLF;
686  break;
687  }
688  }
689  if ( (ID == 0) && (Address.getIP() == 0) )
690  {
691  client << "% missing argument" << CRLF;
692  return 1;
693  }
694  if ( (ID == 0) && (Address.getIP() != 0) )
695  { // match IP
696  Entry = fgms->m_BlackList.Find (Address, "");
697  if (Entry != fgms->m_BlackList.End())
698  {
699  fgms->m_BlackList.Delete (Entry);
700  }
701  else
702  {
703  client << "no entry found!" << CRLF;
704  return 1;
705  }
706  return 0;
707  }
708  Entry = fgms->m_BlackList.FindByID (ID);
709  if (Entry != fgms->m_BlackList.End())
710  {
711  fgms->m_BlackList.Delete (Entry);
712  }
713  else
714  {
715  client << "no entry found!" << CRLF;
716  return 1;
717  }
718  client << "deleted!" << CRLF;
719  return 0;
720 }
721 
722 //////////////////////////////////////////////////
723 /**
724  * @brief Add Blacklist entry
725  *
726  * ONLY in config mode
727  *
728  * possible arguments:
729  * blacklist add ?
730  * blacklist add TTL IP-Address [reason]
731  * blacklist add [...] <cr>
732  */
733 int
735 (
736  char *command,
737  char *argv[],
738  int argc
739 )
740 {
741  time_t TTL = -1;
742  int I;
743  netAddress Address;
744  string Reason;
745  ItList Entry;
746  for (int i=0; i < argc; i++)
747  {
748  switch (i)
749  {
750  case 0: // must be TTL or '?'
751  if ( need_help (argv[i]) )
752  {
753  client << " " << left << setfill(' ') << setw(22)
754  << "TTL" << "Timeout of the new entry in seconds" << CRLF;
755  return (0);
756  }
757  TTL = StrToNum<size_t> ( argv[0], I );
758  if (I)
759  {
760  client << "% invalid TTL" << CRLF;
761  return (1);
762  }
763  break;
764  case 1: // IP or '?'
765  if ( need_help (argv[i]) )
766  {
767  client << " " << left << setfill(' ') << setw(22)
768  << "IP" << "IP address which should be blacklisted" << CRLF;
769  return (0);
770  }
771  Address.set (argv[i], 0);
772  if (Address.getIP() == 0)
773  {
774  client << "% invalid IP address" << CRLF;
775  return (1);
776  }
777  break;
778  default:
779  if ( need_help (argv[i]) )
780  {
781  if (Reason == "")
782  {
783  client << " " << left << setfill(' ') << setw(22)
784  << "STRING" << "a reason for blacklisting this IP" << CRLF;
785  }
786  else
787  {
788  client << " " << left << setfill(' ') << setw(22)
789  << "<cr>" << "add this IP" << CRLF;
790  }
791  return 0;
792  }
793  Reason += argv[i];
794  if (i+1 < argc)
795  Reason += " ";
796  break;
797  }
798  }
799  FG_ListElement E (Reason);
800  E.Address = Address;
801  size_t NewID;
802  ItList CurrentEntry = fgms->m_BlackList.Find ( E.Address, "" );
803  if ( CurrentEntry == fgms->m_BlackList.End() )
804  {
805  NewID = fgms->m_BlackList.Add (E, TTL);
806  }
807  else
808  {
809  client << "% entry already exists (ID " << CurrentEntry->ID << ")!" << CRLF;
810  return 1;
811  }
812  client << "added with ID " << NewID << CRLF;
813  return (0);
814 }
815 
816 //////////////////////////////////////////////////
817 /**
818  * @brief Delete Crossfeed entry
819  *
820  * ONLY in config mode
821  *
822  * possible arguments:
823  * crossfeed delete ?
824  * crossfeed delete ID
825  * crossfeed delete IP-Address
826  * crossfeed delete [...] <cr>
827  */
828 int
830 (
831  char *command,
832  char *argv[],
833  int argc
834 )
835 {
836  size_t ID = 0;
837  int ID_invalid = -1;
838  netAddress Address;
839  ItList Entry;
840  for (int i=0; i < argc; i++)
841  {
842  ID = StrToNum<size_t> ( argv[0], ID_invalid );
843  if (ID_invalid)
844  ID = 0;
845  switch (i)
846  {
847  case 0: // ID or IP or 'brief' or '?'
848  if ( need_help (argv[i]) )
849  {
850  client << " " << left << setfill(' ') << setw(22)
851  << "ID" << "delete entry with ID" << CRLF;
852  client << " " << left << setfill(' ') << setw(22)
853  << "IP" << "delete entry with IP address" << CRLF;
854  return (0);
855  }
856  else if (ID == 0)
857  {
858  Address.set (argv[0], 0);
859  if (Address.getIP() == 0)
860  {
861  client << "% invalid IP address" << CRLF;
862  return (1);
863  }
864  }
865  break;
866  case 1: // only '?'
867  if ( need_help (argv[i]) )
868  {
869  client << " " << left << setfill(' ') << setw(22)
870  << "<cr>" << "delete this crossfeed" << CRLF;
871  return 1;
872  }
873  default:
874  client << "% invalid argument" << CRLF;
875  break;
876  }
877  }
878  if ( (ID == 0) && (Address.getIP() == 0) )
879  {
880  client << "% missing argument" << CRLF;
881  return 1;
882  }
883  if ( (ID == 0) && (Address.getIP() != 0) )
884  { // match IP
885  Entry = fgms->m_CrossfeedList.Find (Address, "");
886  if (Entry != fgms->m_CrossfeedList.End())
887  {
888  fgms->m_CrossfeedList.Delete (Entry);
889  }
890  else
891  {
892  client << "no entry found" << CRLF;
893  return 1;
894  }
895  return 0;
896  }
897  Entry = fgms->m_CrossfeedList.FindByID (ID);
898  if (Entry != fgms->m_CrossfeedList.End())
899  {
900  fgms->m_CrossfeedList.Delete (Entry);
901  }
902  else
903  {
904  client << "no entry found" << CRLF;
905  return 1;
906  }
907  client << "deleted" << CRLF;
908  return 0;
909 }
910 
911 //////////////////////////////////////////////////
912 /**
913  * @brief Add Crossfeed entry
914  *
915  * ONLY in config mode
916  *
917  * possible arguments:
918  * crossfeed add ?
919  * crossfeed add IP-Address Port Name
920  * crossfeed add [...] <cr>
921  */
922 int
924 (
925  char *command,
926  char *argv[],
927  int argc
928 )
929 {
930  netAddress Address;
931  string Name;
932  int Port;
933  int I;
934  ItList Entry;
935  for (int i=0; i < argc; i++)
936  {
937  switch (i)
938  {
939  case 0: // IP or '?'
940  if ( need_help (argv[i]) )
941  {
942  client << " " << left << setfill(' ') << setw(22)
943  << "IP" << "IP address of the crossfeed" << CRLF;
944  return (0);
945  }
946  Address.set (argv[i], 0);
947  if (Address.getIP() == 0)
948  {
949  client << "% invalid IP address" << CRLF;
950  return (1);
951  }
952  break;
953  case 1: // Port or '?'
954  if ( need_help (argv[i]) )
955  {
956  client << " " << left << setfill(' ') << setw(22)
957  << "Port" << "Port of the relay" << CRLF;
958  return (0);
959  }
960  Port = StrToNum<int> ( argv[i], I );
961  if (I)
962  {
963  client << "% invalid port " << Port << CRLF;
964  return (1);
965  }
966  break;
967  default:
968  if ( need_help (argv[i]) )
969  {
970  if (Name == "")
971  {
972  client << " " << left << setfill(' ') << setw(22)
973  << "NAME" << "The name of this crossfeed" << CRLF;
974  }
975  else
976  {
977  client << " " << left << setfill(' ') << setw(22)
978  << "<cr>" << "add this crossfeed" << CRLF;
979  }
980  return 0;
981  }
982  Name += argv[i];
983  if (i+1 < argc)
984  Name += " ";
985  break;
986  }
987  }
988  FG_ListElement E (Name);
989  E.Address = Address;
990  E.Address.setPort (Port);
991  size_t NewID;
992  ItList CurrentEntry = fgms->m_CrossfeedList.Find ( E.Address, "" );
993  if ( CurrentEntry == fgms->m_CrossfeedList.End() )
994  {
995  NewID = fgms->m_CrossfeedList.Add (E, Port);
996  }
997  else
998  {
999  client << "entry already exists (ID " << CurrentEntry->ID << ")" << CRLF;
1000  return 1;
1001  }
1002  client << "added with ID " << NewID << CRLF;
1003  return (0);
1004 }
1005 
1006 //////////////////////////////////////////////////
1007 /**
1008  * @brief Show Crossfeed
1009  *
1010  * possible arguments:
1011  * show blacklist ?
1012  * show blacklist <cr>
1013  * show blacklist ID
1014  * show blacklist IP-Address
1015  * show blacklist [...] brief
1016  */
1017 int
1020  char *command,
1021  char *argv[],
1022  int argc
1023 )
1024 {
1025  size_t ID = 0;
1026  int ID_invalid = -1;
1027  netAddress Address ("0.0.0.0", 0);
1028  bool Brief = false;
1029  size_t EntriesFound = 0;
1030  for (int i=0; i < argc; i++)
1031  {
1032  ID = StrToNum<size_t> ( argv[0], ID_invalid );
1033  if (ID_invalid)
1034  ID = 0;
1035  switch (i)
1036  {
1037  case 0: // ID or IP or 'brief' or '?'
1038  if ( need_help (argv[i]) )
1039  {
1040  client << " " << left << setfill(' ') << setw(22)
1041  << "brief" << "show brief listing" << CRLF;
1042  client << " " << left << setfill(' ') << setw(22)
1043  << "ID" << "show entry with ID" << CRLF;
1044  client << " " << left << setfill(' ') << setw(22)
1045  << "IP" << "show entry with IP-Address" << CRLF;
1046  client << " " << left << setfill(' ') << setw(22)
1047  << "<cr>" << "show long listing" << CRLF;
1048  client << " " << left << setfill(' ') << setw(22)
1049  << "|" << "output modifier" << CRLF;
1050  return (0);
1051  }
1052  else if (strncmp (argv[0], "brief", strlen (argv[i])) == 0)
1053  {
1054  Brief = true;
1055  }
1056  else if (ID == 0)
1057  {
1058  Address.set (argv[0], 0);
1059  if (Address.getIP() == 0)
1060  {
1061  client << "% invalid IP address" << CRLF;
1062  return (1);
1063  }
1064  }
1065  break;
1066  case 1: // 'brief' or '?'
1067  if ( need_help (argv[i]) )
1068  {
1069  if (! Brief)
1070  {
1071  client << " " << left << setfill(' ') << setw(22)
1072  << "brief" << "show brief listing" << CRLF;
1073  }
1074  client << " " << left << setfill(' ') << setw(22)
1075  << "<cr>" << "show long listing" << CRLF;
1076  client << " " << left << setfill(' ') << setw(22)
1077  << "|" << "output modifier" << CRLF;
1078  return (0);
1079  }
1080  else if (strncmp (argv[1], "brief", strlen (argv[0])) == 0)
1081  {
1082  Brief = true;
1083  }
1084  break;
1085  default:
1086  client << "% invalid argument" << CRLF;
1087  break;
1088  }
1089  }
1090  int Count = fgms->m_CrossfeedList.Size ();
1091  FG_ListElement Entry("");
1092  client << fgms->m_CrossfeedList.Name << ":" << CRLF;
1093  client << CRLF;
1094  time_t difftime;
1095  time_t now;
1096  now = time(0);
1097  difftime = now - fgms->m_Uptime;
1098  for (int i = 0; i < Count; i++)
1099  {
1100  Entry = fgms->m_CrossfeedList[i];
1101  if ( (ID == 0) && (Address.getIP() != 0) )
1102  { // only list matching entries
1103  if (Entry.Address != Address)
1104  continue;
1105  }
1106  else if (ID)
1107  {
1108  if (Entry.ID != ID)
1109  continue;
1110  }
1111  EntriesFound++;
1112  client << "ID " << Entry.ID << ": "
1113  << Entry.Address.getHost() << ":" << Entry.Address.getPort()
1114  << " : " << Entry.Name
1115  << CRLF; if (check_pager()) return 0;
1116  if (Brief == true)
1117  {
1118  continue;
1119  }
1120  client << " entered : " << timestamp_to_datestr (Entry.JoinTime)
1121  << CRLF; if (check_pager()) return 0;
1122  client << " last sent : " << timestamp_to_days (Entry.LastSent)
1123  << CRLF; if (check_pager()) return 0;
1124  client << " sent packets : " << Entry.PktsSent
1125  << "(" << (double) (Entry.PktsSent / difftime) << " packets/s)"
1126  << CRLF; if (check_pager()) return 0;
1127  client << " sent bytes : " << byte_counter (Entry.BytesSent)
1128  << "(" << byte_counter ((double) Entry.BytesSent / difftime) << "/s)"
1129  << CRLF; if (check_pager()) return 0;
1130  }
1131  if (EntriesFound)
1132  client << CRLF; if (check_pager()) return 0;
1133  client << EntriesFound << " entries found" << CRLF; if (check_pager()) return 0;
1134  if (EntriesFound)
1135  {
1136  client << "Total sent: "
1137  << fgms->m_CrossfeedList.PktsSent << " packets"
1138  << "(" << fgms->m_CrossfeedList.PktsSent / difftime << "/s)"
1139  << " / " << byte_counter (fgms->m_CrossfeedList.BytesSent)
1140  << "(" << byte_counter ((double) (fgms->m_CrossfeedList.BytesSent/difftime)) << "/s)"
1141  << CRLF;
1142  }
1143  return 0;
1144 }
1145 
1146 //////////////////////////////////////////////////
1147 /**
1148  * @brief Show Relays
1149  *
1150  * possible arguments:
1151  * show relay ?
1152  * show relay <cr>
1153  * show relay ID
1154  * show relay IP-Address
1155  * show relay [...] brief
1156  */
1157 int
1160  char *command,
1161  char *argv[],
1162  int argc
1163 )
1164 {
1165  size_t ID = 0;
1166  int ID_invalid = -1;
1167  netAddress Address ("0.0.0.0", 0);
1168  bool Brief = false;
1169  size_t EntriesFound = 0;
1170  string Name;
1171  for (int i=0; i < argc; i++)
1172  {
1173  ID = StrToNum<size_t> ( argv[0], ID_invalid );
1174  if (ID_invalid)
1175  ID = 0;
1176  switch (i)
1177  {
1178  case 0: // ID or IP or 'brief' or '?'
1179  if ( need_help (argv[i]) )
1180  {
1181  client << " " << left << setfill(' ') << setw(22)
1182  << "brief" << "show brief listing" << CRLF;
1183  client << " " << left << setfill(' ') << setw(22)
1184  << "ID" << "show entry with ID" << CRLF;
1185  client << " " << left << setfill(' ') << setw(22)
1186  << "IP" << "show entry with IP-address" << CRLF;
1187  client << " " << left << setfill(' ') << setw(22)
1188  << "NAME" << "show user with NAME" << CRLF;
1189  client << " " << left << setfill(' ') << setw(22)
1190  << "<cr>" << "show log listing" << CRLF;
1191  client << " " << left << setfill(' ') << setw(22)
1192  << "|" << "output modifier" << CRLF;
1193  return (0);
1194  }
1195  else if (strncmp (argv[0], "brief", strlen (argv[i])) == 0)
1196  {
1197  Brief = true;
1198  }
1199  else if (ID == 0)
1200  {
1201  Address.set (argv[0], 0);
1202  if (Address.getIP() == 0)
1203  {
1204  Name = argv[0];
1205  }
1206  }
1207  break;
1208  case 1: // 'brief' or '?'
1209  if ( need_help (argv[i]) )
1210  {
1211  if (! Brief)
1212  {
1213  client << " " << left << setfill(' ') << setw(22)
1214  << "brief" << "show brief listing" << CRLF;
1215  }
1216  client << " " << left << setfill(' ') << setw(22)
1217  << "<cr>" << "show log listing" << CRLF;
1218  client << " " << left << setfill(' ') << setw(22)
1219  << "|" << "output modifier" << CRLF;
1220  return (0);
1221  }
1222  else if (strncmp (argv[1], "brief", strlen (argv[0])) == 0)
1223  {
1224  Brief = true;
1225  }
1226  break;
1227  default:
1228  client << "% invalid argument" << CRLF;
1229  break;
1230  }
1231  }
1232  int Count = fgms->m_RelayList.Size ();
1233  FG_ListElement Entry("");
1234  client << fgms->m_RelayList.Name << ":" << CRLF;
1235  client << CRLF;
1236  time_t difftime;
1237  time_t now;
1238  now = time(0);
1239  difftime = now - fgms->m_Uptime;
1240  for (int i = 0; i < Count; i++)
1241  {
1242  Entry = fgms->m_RelayList[i];
1243  if ( (ID == 0) && (Address.getIP() != 0) )
1244  { // only list matching entries
1245  if (Entry.Address != Address)
1246  continue;
1247  }
1248  else if (ID)
1249  {
1250  if (Entry.ID != ID)
1251  continue;
1252  }
1253  else if (Name != "")
1254  {
1255  if (Entry.Name.find(Name) == string::npos)
1256  continue;
1257  }
1258  EntriesFound++;
1259  client << "ID " << Entry.ID << ": "
1260  << Entry.Address.getHost() << ":" << Entry.Address.getPort()
1261  << " : " << Entry.Name
1262  << CRLF; if (check_pager()) return 0;
1263  if (Brief == true)
1264  {
1265  continue;
1266  }
1267  client << " entered : " << timestamp_to_datestr (Entry.JoinTime)
1268  << CRLF; if (check_pager()) return 0;
1269  client << " last seen : " << timestamp_to_datestr (Entry.LastSeen)
1270  << CRLF; if (check_pager()) return 0;
1271  client << " sent : "
1272  << Entry.PktsSent << " packets"
1273  << " (" << Entry.PktsSent / difftime << "/s)"
1274  << " / " << byte_counter (Entry.BytesSent)
1275  << " (" << byte_counter ((double) Entry.BytesSent / difftime) << "/s)"
1276  << CRLF; if (check_pager()) return 0;
1277  client << " rcvd : "
1278  << Entry.PktsRcvd << " packets"
1279  << " (" << Entry.PktsRcvd / difftime << "/s)"
1280  << " / " << byte_counter (Entry.BytesRcvd)
1281  << " (" << byte_counter ((double) Entry.BytesRcvd / difftime) << "/s)"
1282  << CRLF; if (check_pager()) return 0;
1283  }
1284  client << CRLF;
1285  client << EntriesFound << " entries found"
1286  << CRLF; if (check_pager()) return 0;
1287  if (Brief)
1288  {
1289  return 0;
1290  }
1291  client << "Totals:" << CRLF; if (check_pager()) return 0;
1292  client << " sent : "
1293  << fgms->m_RelayList.PktsSent << " packets"
1294  << " (" << fgms->m_RelayList.PktsSent / difftime << "/s)"
1295  << " / " << byte_counter (fgms->m_RelayList.BytesSent)
1296  << " (" << byte_counter ((double) fgms->m_RelayList.BytesSent / difftime) << "/s)"
1297  << CRLF; if (check_pager()) return 0;
1298  client << " received : "
1299  << fgms->m_RelayList.PktsRcvd << " packets"
1300  << " (" << fgms->m_RelayList.PktsRcvd / difftime << "/s)"
1301  << " / " << byte_counter (fgms->m_RelayList.BytesRcvd)
1302  << " (" << byte_counter ((double) fgms->m_RelayList.BytesRcvd / difftime) << "/s)"
1303  << CRLF; if (check_pager()) return 0;
1304  return 0;
1305 }
1306 
1307 //////////////////////////////////////////////////
1308 /**
1309  * @brief Show status of tracker server
1310  *
1311  * possible arguments:
1312  * show tracker ?
1313  * show tracker <cr>
1314  */
1315 int
1318  char *command,
1319  char *argv[],
1320  int argc
1321 )
1322 {
1323  for (int i=0; i < argc; i++)
1324  {
1325  switch (i)
1326  {
1327  case 0: // '?'
1328  if ( need_help (argv[i]) )
1329  {
1330  client << " " << left << setfill(' ') << setw(22)
1331  << "<cr>" << "show long listing" << CRLF;
1332  client << " " << left << setfill(' ') << setw(22)
1333  << "|" << "output modifier" << CRLF;
1334  return (0);
1335  }
1336  else
1337  client << "% invalid argument" << CRLF;
1338  break;
1339  default:
1340  client << "% invalid argument" << CRLF;
1341  break;
1342  }
1343  }
1344  if (! fgms->m_IsTracked)
1345  {
1346  client << "This server is NOT tracked" << CRLF;
1347  client << CRLF;
1348  return 0;
1349  }
1350  time_t difftime;
1351  time_t now;
1352  now = time(0);
1353  difftime = now - fgms->m_Uptime;
1354  client << "This server is tracked: "
1355  << fgms->m_Tracker->GetTrackerServer() << ":"
1356  << fgms->m_Tracker->GetTrackerPort()
1357  << CRLF;
1358  if (fgms->m_Tracker->m_connected)
1359  {
1360  client << "state: connected since "
1362  << " (" << timestamp_to_days (fgms->m_Tracker->LastConnected) << " ago)"
1363  << CRLF;
1364  }
1365  else
1366  {
1367  client << "state: NOT connected!" << CRLF;
1368  }
1369  string A = "NEVER";
1370  if (fgms->m_Tracker->LastSeen != 0)
1371  {
1372  A = timestamp_to_days (fgms->m_Tracker->LastSeen);
1373  A += " ago";
1374  }
1375  string B = "NEVER";
1376  if (fgms->m_Tracker->LastSent != 0)
1377  {
1378  B = timestamp_to_days (fgms->m_Tracker->LastSent);
1379  B += " ago";
1380  }
1381  client << "last seen " << A << ", last sent " << B << CRLF;
1382  client << "I had " << fgms->m_Tracker->LostConnections << " lost connections" << CRLF;
1383  client << CRLF;
1384  client << "Counters:" << CRLF;
1385  client << " sent : " << fgms->m_Tracker->PktsSent << " packets";
1386  client << " (" << fgms->m_Tracker->PktsSent / difftime << "/s)";
1387  client << " / " << byte_counter (fgms->m_Tracker->BytesSent);
1388  client << " (" << byte_counter ((double) fgms->m_Tracker->BytesSent / difftime) << "/s)";
1389  client << CRLF;
1390  client << " received: " << fgms->m_Tracker->PktsRcvd << " packets";
1391  client << " (" << fgms->m_Tracker->PktsRcvd / difftime << "/s)";
1392  client << " / " << byte_counter (fgms->m_Tracker->BytesRcvd);
1393  client << " (" << byte_counter ((double) fgms->m_Tracker->BytesRcvd / difftime) << "/s)";
1394  client << CRLF;
1395  client << " queue size: " << fgms->m_Tracker->msg_queue.size() << " messages" << CRLF;
1396  return 0;
1397 }
1398 
1399 //////////////////////////////////////////////////
1400 /**
1401  * @brief Delete Relay entry
1402  *
1403  * ONLY in config mode
1404  *
1405  * possible arguments:
1406  * relay delete ?
1407  * relay delete ID
1408  * relay delete IP-Address
1409  * relay delete [...] <cr>
1410  */
1411 int
1414  char *command,
1415  char *argv[],
1416  int argc
1417 )
1418 {
1419  size_t ID = 0;
1420  int ID_invalid = -1;
1421  netAddress Address;
1422  ItList Entry;
1423  for (int i=0; i < argc; i++)
1424  {
1425  ID = StrToNum<size_t> ( argv[0], ID_invalid );
1426  if (ID_invalid)
1427  ID = 0;
1428  switch (i)
1429  {
1430  case 0: // ID or IP or 'brief' or '?'
1431  if ( need_help (argv[i]) )
1432  {
1433  client << " " << left << setfill(' ') << setw(22)
1434  << "ID" << "delete entry with ID" << CRLF;
1435  client << " " << left << setfill(' ') << setw(22)
1436  << "IP" << "delete entry with IP address" << CRLF;
1437  return (0);
1438  }
1439  else if (ID == 0)
1440  {
1441  Address.set (argv[0], 0);
1442  if (Address.getIP() == 0)
1443  {
1444  client << "% invalid IP address" << CRLF;
1445  return (1);
1446  }
1447  }
1448  break;
1449  case 1: // only '?'
1450  if ( need_help (argv[i]) )
1451  {
1452  client << " " << left << setfill(' ') << setw(22)
1453  << "<cr>" << "delete entry" << CRLF;
1454  return 1;
1455  }
1456  default:
1457  client << "% invalid argument" << CRLF;
1458  break;
1459  }
1460  }
1461  if ( (ID == 0) && (Address.getIP() == 0) )
1462  {
1463  client << "% missing argument" << CRLF;
1464  return 1;
1465  }
1466  if ( (ID == 0) && (Address.getIP() != 0) )
1467  { // match IP
1468  Entry = fgms->m_RelayList.Find (Address, "");
1469  if (Entry != fgms->m_RelayList.End())
1470  {
1471  fgms->m_RelayList.Delete (Entry);
1472  }
1473  else
1474  {
1475  client << "no entry found" << CRLF;
1476  return 1;
1477  }
1478  return 0;
1479  }
1480  Entry = fgms->m_RelayList.FindByID (ID);
1481  if (Entry != fgms->m_RelayList.End())
1482  {
1483  fgms->m_RelayList.Delete (Entry);
1484  }
1485  else
1486  {
1487  client << "no entry found" << CRLF;
1488  return 1;
1489  }
1490  client << "deleted" << CRLF;
1491  return 0;
1492 }
1493 
1494 //////////////////////////////////////////////////
1495 /**
1496  * @brief Add Relay entry
1497  *
1498  * ONLY in config mode
1499  *
1500  * possible arguments:
1501  * relay add ?
1502  * relay add IP-Address Port [Name]
1503  * relay add [...] <cr>
1504  */
1505 int
1508  char *command,
1509  char *argv[],
1510  int argc
1511 )
1512 {
1513  netAddress Address;
1514  string Name;
1515  int Port;
1516  int I;
1517  ItList Entry;
1518  for (int i=0; i < argc; i++)
1519  {
1520  switch (i)
1521  {
1522  case 0: // IP or '?'
1523  if ( need_help (argv[i]) )
1524  {
1525  client << " " << left << setfill(' ') << setw(22)
1526  << "IP" << "IP address of the relay" << CRLF;
1527  return (0);
1528  }
1529  Address.set (argv[i], 0);
1530  if (Address.getIP() == 0)
1531  {
1532  client << "% invalid IP address" << CRLF;
1533  return (1);
1534  }
1535  break;
1536  case 1: // Port or '?'
1537  if ( need_help (argv[i]) )
1538  {
1539  client << " " << left << setfill(' ') << setw(22)
1540  << "Port" << "Port of the relay" << CRLF;
1541  return (0);
1542  }
1543  Port = StrToNum<int> ( argv[i], I );
1544  if (I)
1545  {
1546  client << "% invalid port " << Port << CRLF;
1547  return (1);
1548  }
1549  break;
1550  default: // '?' or <CR>
1551  if ( need_help (argv[i]) )
1552  {
1553  if (Name == "")
1554  client << " " << left << setfill(' ') << setw(22)
1555  << "NAME" << "the name of this relay" << CRLF;
1556  else
1557  client << " " << left << setfill(' ') << setw(22)
1558  << "<cr>" << "add this relay" << CRLF;
1559  return 0;
1560  }
1561  Name += argv[i];
1562  if (i+1 < argc)
1563  Name += " ";
1564  break;
1565  }
1566  }
1567  FG_ListElement E (Name);
1568  E.Address = Address;
1569  E.Address.setPort (Port);
1570  size_t NewID;
1571  ItList CurrentEntry = fgms->m_RelayList.Find ( E.Address, "" );
1572  if ( CurrentEntry == fgms->m_RelayList.End() )
1573  {
1574  NewID = fgms->m_RelayList.Add (E, 0);
1575  }
1576  else
1577  {
1578  client << "entry already exists (ID " << CurrentEntry->ID << ")" << CRLF;
1579  return 1;
1580  }
1581  client << "added with ID " << NewID << CRLF;
1582  return (0);
1583 }
1584 
1585 //////////////////////////////////////////////////
1586 /**
1587  * @brief Show Players
1588  *
1589  * possible arguments:
1590  * show user ?
1591  * show user <cr>
1592  * show user ID <cr>
1593  * show user IP-Address <cr>
1594  * show user Name <cr>
1595  * show user local <cr>
1596  * show user remote <cr>
1597  * show user [...] brief <cr>
1598  */
1599 int
1602  char *command,
1603  char *argv[],
1604  int argc
1605 )
1606 {
1607  size_t ID = 0;
1608  int ID_invalid = -1;
1609  netAddress Address ("0.0.0.0", 0);
1610  string Name;
1611  bool Brief = false;
1612  bool OnlyLocal = false;
1613  bool OnlyRemote = false;
1614  size_t EntriesFound = 0;
1615  time_t difftime;
1616  time_t now = time(0);
1617  for (int i=0; i < argc; i++)
1618  {
1619  ID = StrToNum<size_t> ( argv[0], ID_invalid );
1620  if (ID_invalid)
1621  ID = 0;
1622  switch (i)
1623  {
1624  case 0: // ID or IP or 'brief' or '?'
1625  if ( need_help (argv[i]) )
1626  {
1627  client << " " << left << setfill(' ') << setw(22)
1628  << "brief" << "show brief listing" << CRLF;
1629  client << " " << left << setfill(' ') << setw(22)
1630  << "ID" << "show user with ID" << CRLF;
1631  client << " " << left << setfill(' ') << setw(22)
1632  << "IP" << "show user with IP-Address" << CRLF;
1633  client << " " << left << setfill(' ') << setw(22)
1634  << "NAME" << "show user with NAME" << CRLF;
1635  client << " " << left << setfill(' ') << setw(22)
1636  << "local" << "show only local users" << CRLF;
1637  client << " " << left << setfill(' ') << setw(22)
1638  << "remote" << "show only local users" << CRLF;
1639  client << " " << left << setfill(' ') << setw(22)
1640  << "<cr>" << "show long listing" << CRLF;
1641  client << " " << left << setfill(' ') << setw(22)
1642  << "|" << "output modifier" << CRLF;
1643  return (0);
1644  }
1645  else if (strncmp (argv[0], "brief", strlen (argv[i])) == 0)
1646  {
1647  Brief = true;
1648  }
1649  else if (ID == 0)
1650  {
1651  Address.set (argv[0], 0);
1652  if (Address.getIP() == 0)
1653  {
1654  Name = argv[0];
1655  }
1656  }
1657  break;
1658  case 1: // 'brief' or '?'
1659  if ( need_help (argv[i]) )
1660  {
1661  if (! Brief)
1662  {
1663  client << " " << left << setfill(' ') << setw(22)
1664  << "brief" << "show brief listing" << CRLF;
1665  }
1666  client << " " << left << setfill(' ') << setw(22)
1667  << "<cr>" << "show long listing" << CRLF;
1668  client << " " << left << setfill(' ') << setw(22)
1669  << "|" << "output modifier" << CRLF;
1670  return (0);
1671  }
1672  else if (strncmp (argv[1], "brief", strlen (argv[0])) == 0)
1673  {
1674  Brief = true;
1675  }
1676  break;
1677  default:
1678  client << "% invalid argument" << CRLF;
1679  break;
1680  }
1681  }
1682  int Count = fgms->m_PlayerList.Size ();
1683  FG_Player Player;
1684  Point3D PlayerPosGeod;
1685  string Origin;
1686  string FullName;
1687  client << fgms->m_PlayerList.Name << ":" << CRLF;
1688  client << CRLF;
1689  if (Name == "local")
1690  {
1691  OnlyLocal = true;
1692  Name = "";
1693  }
1694  if (Name == "remote")
1695  {
1696  OnlyRemote = true;
1697  Name = "";
1698  }
1699  for (int i = 0; i < Count; i++)
1700  {
1701  now = time(0);
1702  difftime = now - fgms->m_Uptime;
1703  Player = fgms->m_PlayerList[i];
1704  if ( (ID == 0) && (Address.getIP() != 0) )
1705  { // only list matching entries
1706  if (Player.Address != Address)
1707  continue;
1708  }
1709  else if (ID)
1710  {
1711  if (Player.ID != ID)
1712  continue;
1713  }
1714  else if (Name != "")
1715  {
1716  if (Player.Name.find(Name) == string::npos)
1717  continue;
1718  }
1719  else if (OnlyLocal == true)
1720  {
1721  if (Player.IsLocal == false)
1722  continue;
1723  }
1724  else if (OnlyRemote == true)
1725  {
1726  if (Player.IsLocal == true)
1727  continue;
1728  }
1729  sgCartToGeod ( Player.LastPos, PlayerPosGeod );
1730  if (Player.IsLocal)
1731  {
1732  Origin = "LOCAL";
1733  }
1734  else
1735  {
1736  FG_SERVER::mT_RelayMapIt Relay = fgms->m_RelayMap.find ( Player.Address.getIP() );
1737  if ( Relay != fgms->m_RelayMap.end() )
1738  {
1739  Origin = Relay->second;
1740  }
1741  else
1742  {
1743  Origin = Player.Origin;
1744  }
1745  }
1746  FullName = Player.Name + string("@") + Origin;
1747  client << "ID " << Player.ID << ": "
1748  << FullName << " entered: "
1749  << timestamp_to_days (Player.JoinTime) << " ago"
1750  << CRLF; if (check_pager()) return 0;
1751  EntriesFound++;
1752  if (Brief == true)
1753  {
1754  continue;
1755  }
1756  if (Player.HasErrors == true)
1757  {
1758  client << " " << left << setfill(' ') << setw(15)
1759  << "ERROR" << Player.Error
1760  << CRLF; if (check_pager()) return 0;
1761  }
1762  int expires = Player.Timeout - (now - Player.LastSeen);
1763  client << " " << left << setfill(' ') << setw(15)
1764  << "joined" << timestamp_to_datestr(Player.JoinTime)
1765  << CRLF; if (check_pager()) return 0;
1766  client << " " << left << setfill(' ') << setw(15)
1767  << "last seen" << timestamp_to_datestr(Player.LastSeen)
1768  << CRLF; if (check_pager()) return 0;
1769  client << " " << left << setfill(' ') << setw(15)
1770  << "using model" << Player.ModelName
1771  << CRLF; if (check_pager()) return 0;
1772  client << " " << left << setfill(' ') << setw(15)
1773  << "real origin" << Player.Origin
1774  << CRLF; if (check_pager()) return 0;
1775  if (Player.IsLocal)
1776  {
1777  client << " " << left << setfill(' ') << setw(15)
1778  << "sent" << Player.PktsSent << " packets "
1779  << "(" << Player.PktsSent / difftime << "/s)"
1780  << " / " << byte_counter (Player.BytesSent)
1781  << " (" << byte_counter ((double) Player.BytesSent / difftime) << "/s)"
1782  << CRLF; if (check_pager()) return 0;
1783  client << " " << left << setfill(' ') << setw(15)
1784  << "rcvd" << Player.PktsRcvd << " packets "
1785  << "(" << Player.PktsRcvd / difftime << "/s)"
1786  << " / " << byte_counter (Player.BytesRcvd)
1787  << " (" << byte_counter ((double) Player.BytesRcvd / difftime) << "/s)"
1788  << CRLF; if (check_pager()) return 0;
1789  }
1790  client << " " << left << setfill(' ') << setw(15)
1791  << "expires in" << expires
1792  << CRLF; if (check_pager()) return 0;
1793  client << " " << left << setfill(' ') << setw(15)
1794  << "inactive" << now - Player.LastRelayedToInactive
1795  << CRLF; if (check_pager()) return 0;
1796  }
1797  difftime = now - fgms->m_Uptime;
1798  client << CRLF;
1799  client << EntriesFound << " entries found" << CRLF;
1800  if (! Brief)
1801  {
1802  client << "Totals:" << CRLF; if (check_pager()) return 0;
1803  client << " sent : " << fgms->m_PlayerList.PktsSent << " packets"
1804  << " (" << fgms->m_PlayerList.PktsSent / difftime << "/s)"
1805  << " / " << byte_counter (fgms->m_PlayerList.BytesSent)
1806  << " (" << byte_counter ((double) fgms->m_PlayerList.BytesSent / difftime) << "/s)"
1807  << CRLF; if (check_pager()) return 0;
1808  client << " received: " << fgms->m_PlayerList.PktsRcvd << " packets"
1809  << " (" << fgms->m_PlayerList.PktsRcvd / difftime << "/s)"
1810  << " / " << byte_counter (fgms->m_PlayerList.BytesRcvd)
1811  << " (" << byte_counter ((double) fgms->m_PlayerList.BytesRcvd / difftime) << "/s)"
1812  << CRLF; if (check_pager()) return 0;
1813  }
1814  return 0;
1815 }
1816 
1817 int
1820  char *command,
1821  char *argv[],
1822  int argc
1823 )
1824 {
1825  client << "Command '" << command << "' NOT IMPLEMENTED YET" << CRLF;
1826  if (argc > 0)
1827  {
1828  client << " args:" << CRLF;
1829  for (int i=0; i<argc; i++)
1830  client << " '" << argv[i] << "'" << CRLF;
1831  }
1832  return (0);
1833 }
1834 
unsigned int getPort() const
Return the port no as int.
Definition: netSocket.cxx:140
std::map< uint32_t, string >::iterator mT_RelayMapIt
Definition: fg_server.hxx:135
mT_IP2Relay m_RelayMap
Definition: fg_server.hxx:165
int16_t m_ProtoMajorVersion
Definition: fg_server.hxx:157
size_t m_NumMaxClients
Definition: fg_server.hxx:153
uint64_t PktsRcvd
Definition: fg_tracker.hxx:115
size_t LostConnections
Definition: fg_tracker.hxx:116
int cmd_relay_add(char *command, char *argv[], int argc)
Add Relay entry.
Definition: fg_cli.cxx:1507
void set(const char *host, int port)
Definition: netSocket.cxx:73
size_t ID
The ID of this entry.
Definition: fg_list.hxx:57
uint64_t BytesRcvd
Count of bytes recieved from client.
Definition: fg_list.hxx:190
FG_TRACKER * m_Tracker
Definition: fg_server.hxx:172
unsigned int getIP() const
Definition: netSocket.cxx:134
string Name
The callsign (or name)
Definition: fg_list.hxx:61
time_t m_Uptime
Definition: fg_server.hxx:196
string m_AdminUser
Definition: fg_server.hxx:147
vMSG msg_queue
Definition: fg_tracker.hxx:104
size_t m_TrackerDisconnect
Definition: fg_server.hxx:195
uint64_t PktsRcvd
Count of packets recieved from client.
Definition: fg_list.hxx:186
int cmd_tracker_show(char *command, char *argv[], int argc)
Show status of tracker server.
Definition: fg_cli.cxx:1317
uint64_t BytesSent
Count of bytes sent to client.
Definition: fg_list.hxx:77
size_t m_TelnetReceived
Definition: fg_server.hxx:188
uint64_t PktsSent
Definition: fg_tracker.hxx:114
ListIterator FindByID(size_t ID)
Definition: fg_list.hxx:417
time_t JoinTime
The time this entry was added to the list.
Definition: fg_list.hxx:65
bool m_connected
Definition: fg_tracker.hxx:97
FG_List m_BlackList
Definition: fg_server.hxx:167
void sgCartToGeod(const Point3D &CartPoint, Point3D &GeodPoint)
Convert a cartexian XYZ coordinate to a geodetic lat/lon/alt. This function is a copy of what's in Si...
time_t LastSent
Definition: fg_tracker.hxx:111
string m_ServerName
Definition: fg_server.hxx:160
time_t LastRelayedToInactive
Definition: fg_list.hxx:122
FG_CLI(FG_SERVER *fgms, int fd)
Definition: fg_cli.cxx:34
ListIterator Find(const netAddress &Address, const string &Name="")
Definition: fg_list.hxx:318
time_t LastSeen
Definition: fg_tracker.hxx:110
string Origin
Definition: fg_list.hxx:100
int cmd_relay_delete(char *command, char *argv[], int argc)
Delete Relay entry.
Definition: fg_cli.cxx:1413
uint64_t BytesSent
Count of bytes sent to client.
Definition: fg_list.hxx:192
uint64_t PktsSent
Count of packets sent to client.
Definition: fg_list.hxx:188
bool m_IsTracked
Definition: fg_server.hxx:159
int cmd_crossfeed_show(char *command, char *argv[], int argc)
Show Crossfeed.
Definition: fg_cli.cxx:1019
int cmd_user_show(char *command, char *argv[], int argc)
Show Players.
Definition: fg_cli.cxx:1601
#define UNUSED(d)
Definition: clitest.cxx:17
size_t m_RemoteClients
Definition: fg_server.hxx:155
int cmd_show_stats(UNUSED(char *command), UNUSED(char *argv[]), UNUSED(int argc))
Definition: fg_cli.cxx:270
ListIterator End()
Definition: fg_list.hxx:465
int cmd_relay_show(char *command, char *argv[], int argc)
Show Relays.
Definition: fg_cli.cxx:1159
Represent a Player.
Definition: fg_list.hxx:97
int GetTrackerPort()
Return the port no of the tracker.
Definition: fg_tracker.hxx:76
time_t Timeout
The Timeout of this entry.
Definition: fg_list.hxx:59
static char E[48]
Definition: crypt-win.c:146
size_t m_PositionData
Definition: fg_server.hxx:186
uint64_t PktsSent
Count of packets sent to client.
Definition: fg_list.hxx:73
string m_AdminEnable
Definition: fg_server.hxx:149
string NumToStr(T n_Number, int n_Precision=2, int n_Base=10)
Convert a number to string.
Definition: fg_util.hxx:193
bool HasErrors
true if this client has errors
Definition: fg_list.hxx:120
string Error
in case of errors the reason is stored here
Definition: fg_list.hxx:116
string timestamp_to_days(time_t Date)
calculate the difference of a timestamp to now and convert the difference to a string representation ...
Definition: fg_util.cxx:36
size_t Size()
Definition: fg_list.hxx:251
int cmd_crossfeed_delete(char *command, char *argv[], int argc)
Delete Crossfeed entry.
Definition: fg_cli.cxx:830
int cmd_fgms_die(UNUSED(char *command), UNUSED(char *argv[]), UNUSED(int argc))
Definition: fg_cli.cxx:410
int cmd_blacklist_show(char *command, char *argv[], int argc)
Show Blacklist.
Definition: fg_cli.cxx:495
size_t m_TrackerConnect
Definition: fg_server.hxx:195
int cmd_blacklist_delete(char *command, char *argv[], int argc)
Delete Blacklist entry.
Definition: fg_cli.cxx:641
FG_List m_CrossfeedList
Definition: fg_server.hxx:166
ListIterator Delete(const ListIterator &Element)
Definition: fg_list.hxx:292
FG_List m_RelayList
Definition: fg_server.hxx:168
Client & CRLF(Client &out)
Definition: cli_client.cxx:471
int cmd_show_uptime(UNUSED(char *command), UNUSED(char *argv[]), UNUSED(int argc))
Definition: fg_cli.cxx:430
string byte_counter(double bytes)
Definition: fg_util.cxx:100
void setPort(int port)
Definition: netSocket.cxx:113
uint64_t BytesRcvd
Definition: fg_tracker.hxx:113
bool m_IamHUB
Definition: fg_server.hxx:173
time_t LastConnected
Definition: fg_tracker.hxx:109
uint64_t BytesRcvd
Count of bytes recieved from client.
Definition: fg_list.hxx:75
Represent a generic list element.
Definition: fg_list.hxx:47
int cmd_NOT_IMPLEMENTED(char *command, char *argv[], int argc)
Definition: fg_cli.cxx:1819
size_t m_LocalClients
Definition: fg_server.hxx:154
int cmd_show_version(UNUSED(char *command), UNUSED(char *argv[]), UNUSED(int argc))
Definition: fg_cli.cxx:451
size_t m_TrackerPosition
Definition: fg_server.hxx:195
const std::string getHost() const
Create a string object representing an IP address. This is always a string of the form 'dd...
Definition: netSocket.cxx:123
Socket address, internet style.
Definition: netSocket.h:87
int16_t m_ProtoMinorVersion
Definition: fg_server.hxx:156
vector< FG_ListElement >::iterator ItList
Definition: fg_list.hxx:208
int cmd_crossfeed_add(char *command, char *argv[], int argc)
Add Crossfeed entry.
Definition: fg_cli.cxx:924
The Main fgms Class.
Definition: fg_server.hxx:55
size_t m_BlackRejected
Definition: fg_server.hxx:182
int cmd_blacklist_add(char *command, char *argv[], int argc)
Add Blacklist entry.
Definition: fg_cli.cxx:735
time_t LastSeen
timestamp of last seen packet from this element
Definition: fg_list.hxx:67
string ModelName
The model name.
Definition: fg_list.hxx:106
void setup()
Definition: fg_cli.cxx:45
bool need_help(char *argv)
Definition: fg_cli.cxx:256
size_t m_AdminReceived
Definition: fg_server.hxx:189
size_t m_UnknownRelay
Definition: fg_server.hxx:184
bool IsLocal
true is this client is directly connected to this fgms instance
Definition: fg_list.hxx:112
uint64_t PktsRcvd
Count of packets recieved from client.
Definition: fg_list.hxx:71
uint64_t BytesSent
Definition: fg_tracker.hxx:112
size_t m_NotPosData
Definition: fg_server.hxx:187
string GetTrackerServer()
Return the server of the tracker.
Definition: fg_tracker.hxx:70
netAddress Address
The network address of this element.
Definition: fg_list.hxx:63
string timestamp_to_datestr(time_t date)
convert a unix timestamp to a string representation of a date
Definition: fg_util.cxx:11
time_t LastSent
timestamp of last sent packet to this element
Definition: fg_list.hxx:69
size_t m_PacketsInvalid
Definition: fg_server.hxx:183
string m_AdminPass
Definition: fg_server.hxx:148
PlayerList m_PlayerList
Definition: fg_server.hxx:169
Point3D LastPos
The last recorded position.
Definition: fg_list.hxx:108
size_t Add(T &Element, time_t TTL)
Definition: fg_list.hxx:268
string Name
Definition: fg_list.hxx:194
bool m_WantExit
Definition: fg_server.hxx:175