1 /*******************************************************************************
2
3 KHOMP generic endpoint/channel library.
4 Copyright (C) 2007-2010 Khomp Ind. & Com.
5
6 The contents of this file are subject to the Mozilla Public License
7 Version 1.1 (the "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
10
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
13 the specific language governing rights and limitations under the License.
14
15 Alternatively, the contents of this file may be used under the terms of the
16 "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
17 case the provisions of "LGPL License" are applicable instead of those above.
18
19 If you wish to allow use of your version of this file only under the terms of
20 the LGPL License and not to allow others to use your version of this file
21 under the MPL, indicate your decision by deleting the provisions above and
22 replace them with the notice and other provisions required by the LGPL
23 License. If you do not delete the provisions above, a recipient may use your
24 version of this file under either the MPL or the LGPL License.
25
26 The LGPL header follows below:
27
28 This library is free software; you can redistribute it and/or
29 modify it under the terms of the GNU Lesser General Public
30 License as published by the Free Software Foundation; either
31 version 2.1 of the License, or (at your option) any later version.
32
33 This library is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 Lesser General Public License for more details.
37
38 You should have received a copy of the GNU Lesser General Public License
39 along with this library; if not, write to the Free Software Foundation,
40 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
41
42 *******************************************************************************/
43
44 #include "cli.h"
45 #include "k3l.h"
46 #include "lock.h"
47 #include "khomp_pvt.h"
48 #include "spec.h"
49
50 /* our stream and interface handlers */
51 switch_stream_handle_t *Cli::stream;
52 switch_loadable_module_interface_t **Cli::module_interface;
53
54 /* contains all commands */
55 Cli::Commands Cli::_commands;
56
57 /* khomp all commands usage */
58 std::string Cli::_khomp_usage;
59
60 /* register our commands, but you must create the command function */
registerCommands(APIFunc func,switch_loadable_module_interface_t ** mod_int)61 void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod_int)
62 {
63 if(!mod_int || !*mod_int)
64 {
65 LOG(ERROR,"Invalid module passed");
66 return;
67 }
68
69 /* the manual */
70 _khomp_usage = \
71 "---------------------------------------------------------------------------\n"\
72 "---------------------------------- HELP -----------------------------------\n"\
73 "---------------------------------------------------------------------------\n"\
74 " khomp channels disconnect {all | <board> all | <board> <channel>}\n" \
75 " khomp channels unblock {all | <board> all | <board> <channel>}\n" \
76 " khomp clear links [<board> [<link>]]\n" \
77 " khomp clear statistics [<board> [<channel>]]\n" \
78 " khomp dump config\n" \
79 " khomp get <option>\n" \
80 " khomp kommuter {on|off}\n" \
81 " khomp kommuter count\n" \
82 " khomp log console <options>\n" \
83 " khomp log disk <options>\n" \
84 " khomp log rotate\n" \
85 " khomp log status\n" \
86 " khomp log trace isdn <what>[,<what2>[,..]]\n" \
87 " khomp log trace k3l {on|off}\n" \
88 " khomp log trace r2 {on|off}\n" \
89 " khomp reset links [<board> [<link>]]\n" \
90 " khomp revision\n" \
91 " khomp select sim <board> <channel> <sim_card>\n" \
92 " khomp send command <board> <channel> <command> [argument]\n" \
93 " khomp send raw command <board> <dsp> <c0> <c1> [...]\n" \
94 " khomp set <option> <value>\n" \
95 " khomp show calls [<board> [<channel>]]\n" \
96 " khomp show channels [{<board> [<channel>]} | \n" \
97 " {{concise|verbose|xml} [<board> [<channel>]]}]\n" \
98 " khomp show links [[errors] [{<board>} | {{concise|verbose|xml}[<board>]}]]\n"\
99 " khomp show statistics [{{verbose|xml} [<board> [<channel>]]} | \n" \
100 " {detailed <board> <channel>}]\n" \
101 " khomp sms <device> <destination> <message..>\n" \
102 " khomp summary [concise|verbose|xml]\n" \
103 "---------------------------------------------------------------------------\n\n";
104
105 /* we need this module_inteface, is used by SWITCH_ADD_API, there's no escape */
106 module_interface = mod_int;
107
108 /* khomp cli commands */
109 SWITCH_ADD_API(Globals::api_interface, "khomp", "Khomp Menu", func, _khomp_usage.c_str());
110
111 /* insert commands in list */
112 for(Commands::iterator itr = _commands.begin();itr != _commands.end();itr++)
113 {
114 switch_console_set_complete(STR(FMT("add khomp %s") % (*itr)->complete_name));
115
116 /* if we have options, let's insert them */
117 if((*itr)->options.size() > 0)
118 {
119 std::vector<std::string>::iterator itr_option = (*itr)->options.begin();
120 while(itr_option != (*itr)->options.end())
121 {
122 switch_console_set_complete(STR(FMT("add khomp %s %s") % (*itr)->complete_name % *itr_option));
123 itr_option++;
124 }
125 }
126 }
127 }
128
129 /* is responsible for parse and execute all commands */
parseCommands(int argc,char * argv[])130 bool Cli::parseCommands(int argc, char *argv[])
131 {
132 /*
133 * DEBUG_CLI_CMD();
134 */
135
136 /* khomp summary */
137 if (ARG_CMP(0, "summary"))
138 return EXEC_CLI_CMD(Cli::KhompSummary);
139
140 /* khomp show */
141 else if(ARG_CMP(0, "show"))
142 {
143 /* khomp show calls */
144 if(ARG_CMP(1, "calls"))
145 return EXEC_CLI_CMD(Cli::KhompShowCalls);
146
147 /* khomp show channels */
148 if(ARG_CMP(1, "channels"))
149 return EXEC_CLI_CMD(Cli::KhompShowChannels);
150
151 /* khomp show links */
152 if(ARG_CMP(1, "links"))
153 return EXEC_CLI_CMD(Cli::KhompShowLinks);
154
155 /* khomp show statistics */
156 if(ARG_CMP(1, "statistics"))
157 return EXEC_CLI_CMD(Cli::KhompShowStatistics);
158 }
159
160 /* khomp clear */
161 else if(ARG_CMP(0, "clear"))
162 {
163 /* khomp clear links */
164 if(ARG_CMP(1, "links"))
165 return EXEC_CLI_CMD(Cli::KhompClearLinks);
166
167 /* khomp clear statistics */
168 if(ARG_CMP(1, "statistics"))
169 return EXEC_CLI_CMD(Cli::KhompClearStatistics);
170 }
171
172 /* khomp dump */
173 else if(ARG_CMP(0, "dump"))
174 {
175 /* khomp dump config */
176 if(ARG_CMP(1, "config"))
177 return EXEC_CLI_CMD(Cli::KhompDumpConfig);
178 }
179
180 /* khomp reset */
181 else if(ARG_CMP(0, "reset"))
182 {
183 /* khomp reset links */
184 if(ARG_CMP(1, "links"))
185 return EXEC_CLI_CMD(Cli::KhompResetLinks);
186
187 }
188
189 /* khomp sms */
190 else if(ARG_CMP(0, "sms"))
191 {
192 return EXEC_CLI_CMD(Cli::KhompSMS);
193 }
194
195 /* khomp log */
196 else if(ARG_CMP(0, "log"))
197 {
198 /* khomp log console */
199 if(ARG_CMP(1, "console"))
200 return EXEC_CLI_CMD(Cli::KhompLogConsole);
201
202 /* khomp log disk */
203 if(ARG_CMP(1, "disk"))
204 return EXEC_CLI_CMD(Cli::KhompLogDisk);
205
206 /* khomp log status */
207 if(ARG_CMP(1, "status"))
208 return EXEC_CLI_CMD(Cli::KhompLogStatus);
209
210 /* khomp log rotate */
211 if(ARG_CMP(1, "rotate"))
212 return EXEC_CLI_CMD(Cli::KhompLogRotate);
213
214 /* khomp log trace */
215 if(ARG_CMP(1, "trace"))
216 {
217 /* khomp log trace k3l */
218 if(ARG_CMP(2, "k3l"))
219 return EXEC_CLI_CMD(Cli::KhompLogTraceK3L);
220
221 /* khomp log trace isdn */
222 if(ARG_CMP(2, "isdn"))
223 return EXEC_CLI_CMD(Cli::KhompLogTraceISDN);
224
225 /* khomp log trace r2 */
226 if(ARG_CMP(2, "r2"))
227 return EXEC_CLI_CMD(Cli::KhompLogTraceR2);
228 }
229 }
230
231 /* khomp channels */
232 else if(ARG_CMP(0, "channels"))
233 {
234 /* khomp channels disconnect */
235 if(ARG_CMP(1, "disconnect"))
236 return EXEC_CLI_CMD(Cli::KhompChannelsDisconnect);
237
238 /* khomp channels unblock */
239 if(ARG_CMP(1, "unblock"))
240 return EXEC_CLI_CMD(Cli::KhompChannelsUnblock);
241 }
242
243 /* khomp get */
244 else if(ARG_CMP(0, "get"))
245 return EXEC_CLI_CMD(Cli::KhompGet);
246
247 /* khomp set */
248 else if(ARG_CMP(0, "set"))
249 return EXEC_CLI_CMD(Cli::KhompSet);
250
251 /* khomp reivision */
252 else if(ARG_CMP(0, "revision"))
253 return EXEC_CLI_CMD(Cli::KhompRevision);
254
255 /* khomp send */
256 else if(ARG_CMP(0, "send"))
257 {
258 /* khomp send command */
259 if(ARG_CMP(1, "command"))
260 return EXEC_CLI_CMD(Cli::KhompSendCommand);
261
262 /* khomp send raw */
263 if(ARG_CMP(1, "raw"))
264 return EXEC_CLI_CMD(Cli::KhompSendRawCommand);
265 }
266
267 /* khomp select */
268 else if(ARG_CMP(0, "select"))
269 {
270 /* khomp select sim */
271 if(ARG_CMP(1, "sim"))
272 return EXEC_CLI_CMD(Cli::KhompSelectSim);
273
274 }
275
276 /* khomp kommuter */
277 else if(ARG_CMP(0, "kommuter"))
278 {
279 if(ARG_CMP(1, "on") || ARG_CMP(1, "off"))
280 return EXEC_CLI_CMD(Cli::KhompKommuterOnOff);
281
282 if(ARG_CMP(1, "count"))
283 return EXEC_CLI_CMD(Cli::KhompKommuterCount);
284 }
285
286 /* if everything fails, i'm here to support */
287 printKhompUsage();
288
289 return false;
290 }
291
292 /******************************************************************************/
293 /******************** Defining the static initialization **********************/
294
295 Cli::_KhompSummary Cli::KhompSummary;
296 Cli::_KhompShowCalls Cli::KhompShowCalls;
297 Cli::_KhompShowChannels Cli::KhompShowChannels;
298 Cli::_KhompShowLinks Cli::KhompShowLinks;
299 Cli::_KhompShowStatistics Cli::KhompShowStatistics;
300 Cli::_KhompClearLinks Cli::KhompClearLinks;
301 Cli::_KhompDumpConfig Cli::KhompDumpConfig;
302 Cli::_KhompClearStatistics Cli::KhompClearStatistics;
303 Cli::_KhompResetLinks Cli::KhompResetLinks;
304 Cli::_KhompChannelsDisconnect Cli::KhompChannelsDisconnect;
305 Cli::_KhompChannelsUnblock Cli::KhompChannelsUnblock;
306 Cli::_KhompSMS Cli::KhompSMS;
307 Cli::_KhompLogConsole Cli::KhompLogConsole;
308 Cli::_KhompLogDisk Cli::KhompLogDisk;
309 Cli::_KhompLogStatus Cli::KhompLogStatus;
310 Cli::_KhompLogRotate Cli::KhompLogRotate;
311 Cli::_KhompLogTraceK3L Cli::KhompLogTraceK3L;
312 Cli::_KhompLogTraceISDN Cli::KhompLogTraceISDN;
313 Cli::_KhompLogTraceR2 Cli::KhompLogTraceR2;
314 Cli::_KhompGet Cli::KhompGet;
315 Cli::_KhompSet Cli::KhompSet;
316 Cli::_KhompRevision Cli::KhompRevision;
317 Cli::_KhompSendCommand Cli::KhompSendCommand;
318 Cli::_KhompSendRawCommand Cli::KhompSendRawCommand;
319 Cli::_KhompSelectSim Cli::KhompSelectSim;
320 Cli::_KhompKommuterOnOff Cli::KhompKommuterOnOff;
321 Cli::_KhompKommuterCount Cli::KhompKommuterCount;
322
323 /******************************************************************************/
324 /*************************** Defining the commands ****************************/
325 /*!
326 \brief Print a system summary for all the boards. [khomp summary]
327 */
execute(int argc,char * argv[])328 bool Cli::_KhompSummary::execute(int argc, char *argv[])
329 {
330 if(argc < 1 || argc > 2)
331 {
332 printUsage(stream);
333 return false;
334 }
335
336 Cli::OutputType output_type = Cli::VERBOSE;
337 if(ARG_CMP(1, "concise")) output_type = Cli::CONCISE;
338 if(ARG_CMP(1, "xml"))
339 {
340 output_type = Cli::XML;
341 createRoot("summary");
342 }
343
344 class_type classe = ( !_on_cli_term ? C_MESSAGE : C_CLI );
345 K3L_API_CONFIG apiCfg;
346
347 if (output_type == Cli::VERBOSE)
348 {
349 K::Logger::Logg2(classe, stream, " ------------------------------------------------------------------");
350 K::Logger::Logg2(classe, stream, "|---------------------- Khomp System Summary ----------------------|");
351 K::Logger::Logg2(classe, stream, "|------------------------------------------------------------------|");
352 }
353
354 const bool running = (k3lGetDeviceConfig(-1, ksoAPI, &apiCfg, sizeof(apiCfg)) == ksSuccess);
355
356 if(running)
357 {
358 switch(output_type)
359 {
360 case Cli::VERBOSE:
361 {
362 K::Logger::Logg2(classe, stream, FMT("| K3L API %d.%d.%d [m.VPD %d] - %-38s |")
363 % apiCfg.MajorVersion % apiCfg.MinorVersion % apiCfg.BuildVersion
364 % apiCfg.VpdVersionNeeded % apiCfg.StrVersion);
365 } break;
366
367 case Cli::CONCISE:
368 {
369 K::Logger::Logg2(classe, stream, FMT("%d.%d.%d;%d;%s")
370 % apiCfg.MajorVersion % apiCfg.MinorVersion % apiCfg.BuildVersion
371 % apiCfg.VpdVersionNeeded % apiCfg.StrVersion);
372 } break;
373
374 case Cli::XML:
375 {
376 /* summary/k3lapi */
377 switch_xml_t xk3lapi = switch_xml_add_child_d(root, "k3lapi",0);
378
379 /* summary/k3lapi/version */
380 switch_xml_t xk3l_version = switch_xml_add_child_d(xk3lapi,"version", 0);
381 switch_xml_set_attr_d(xk3l_version,"major",STR(FMT("%d") % apiCfg.MajorVersion));
382 switch_xml_set_attr_d(xk3l_version,"minor",STR(FMT("%d") % apiCfg.MinorVersion));
383 switch_xml_set_attr_d(xk3l_version,"build",STR(FMT("%d") % apiCfg.BuildVersion));
384 switch_xml_set_attr_d(xk3l_version,"vpd",STR(FMT("%d") % apiCfg.VpdVersionNeeded));
385
386 /* summary/k3lapi/version/revision */
387 switch_xml_t xk3l_rev = switch_xml_add_child_d(xk3l_version,"revision",0);
388 switch_xml_set_txt_d(xk3l_rev,STR(FMT("%s") % apiCfg.StrVersion));
389 } break;
390
391 default:
392 break;
393 }
394 }
395 else
396 {
397 switch(output_type)
398 {
399 case Cli::VERBOSE:
400 {
401 K::Logger::Logg2(classe, stream, "| Connection to KServer broken, please check system logs! |");
402 } break;
403
404 case Cli::CONCISE:
405 {
406 K::Logger::Logg2(classe, stream, "CONNECTION BROKEN");
407 } break;
408
409 case Cli::XML:
410 {
411 /* summary/k3lapi */
412 switch_xml_t xk3lapi = switch_xml_add_child_d(root, "k3lapi",0);
413 switch_xml_set_txt_d(xk3lapi, "CONNECTION BROKEN");
414 } break;
415 }
416 }
417
418 #ifndef MOD_KHOMP_VERSION
419 #define MOD_KHOMP_VERSION "unknown"
420 #endif
421
422 #ifndef SWITCH_VERSION_FULL
423 #define SWITCH_VERSION_FULL "unknown"
424 #endif
425
426 std::string khomp_endpoint_rev(MOD_KHOMP_VERSION);
427 std::string freeswitch_rev(SWITCH_VERSION_FULL);
428
429 switch(output_type)
430 {
431 case Cli::VERBOSE:
432 {
433 K::Logger::Logg2(classe, stream, FMT("| Khomp Endpoint - %-47s |") % khomp_endpoint_rev);
434 K::Logger::Logg2(classe, stream, FMT("| FreeSWITCH - %-51s |") % freeswitch_rev);
435 } break;
436
437 case Cli::CONCISE:
438 {
439 K::Logger::Logg2(classe, stream, FMT("%s") % khomp_endpoint_rev);
440 K::Logger::Logg2(classe, stream, FMT("%s") % freeswitch_rev);
441 } break;
442
443 case Cli::XML:
444 {
445 /* summary/mod_khomp */
446 switch_xml_t xmod_khomp = switch_xml_add_child_d(root,"mod_khomp",0);
447
448 /* summary/mod_khomp/revision */
449 switch_xml_t xrevision = switch_xml_add_child_d(xmod_khomp,"revision",0);
450 switch_xml_set_txt_d(xrevision, khomp_endpoint_rev.c_str());
451
452 /* summary/freeswitch */
453 switch_xml_t xfs = switch_xml_add_child_d(root,"freeswitch",0);
454
455 /* summary/freeswitch/revision */
456 switch_xml_t xfs_rev = switch_xml_add_child_d(xfs,"revision",0);
457 switch_xml_set_txt_d(xfs_rev, freeswitch_rev.c_str());
458 } break;
459
460 default:
461 break;
462 }
463
464 if(!running)
465 {
466 if (output_type == Cli::VERBOSE)
467 K::Logger::Logg2(classe,stream, " ------------------------------------------------------------------");
468
469 if (output_type == Cli::XML)
470 {
471 printXMLOutput(stream);
472 clearRoot();
473 }
474
475 return false;
476 }
477
478 if (output_type == Cli::XML)
479 {
480 /* summary/board */
481 xdevs = switch_xml_add_child_d(root,"devices",0);
482 }
483
484 for (unsigned int i = 0; i < Globals::k3lapi.device_count(); i++)
485 {
486 const K3L_DEVICE_CONFIG & devCfg = Globals::k3lapi.device_config(i);
487
488 std::string tipo = Verbose::deviceName((KDeviceType)Globals::k3lapi.device_type(i), devCfg.DeviceModel);
489
490 if (output_type == Cli::VERBOSE)
491 K::Logger::Logg2(classe, stream, " ------------------------------------------------------------------");
492
493 switch (Globals::k3lapi.device_type(i))
494 {
495 /* E1 boards */
496 case kdtE1:
497 case kdtConf:
498 case kdtPR:
499 case kdtE1GW:
500 case kdtE1IP:
501 case kdtE1Spx:
502 case kdtGWIP:
503 case kdtFXS:
504 case kdtFXSSpx:
505 case kdtE1FXSSpx:
506 {
507 K3L_E1600A_FW_CONFIG dspAcfg;
508 K3L_E1600B_FW_CONFIG dspBcfg;
509
510 if ((k3lGetDeviceConfig(i, ksoFirmware + kfiE1600A, &dspAcfg, sizeof(dspAcfg)) == ksSuccess) &&
511 (k3lGetDeviceConfig(i, ksoFirmware + kfiE1600B, &dspBcfg, sizeof(dspBcfg)) == ksSuccess))
512 {
513 switch(output_type)
514 {
515 case Cli::VERBOSE:
516 {
517 K::Logger::Logg2(classe, stream, FMT("| [[ %02u ]] %s, serial '%s', %02d channels, %d links.%s|")
518 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount % devCfg.LinkCount
519 % std::string(std::max<int>(0, 22 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
520 K::Logger::Logg2(classe, stream, FMT("| * DSP A: %s, DSP B: %s - PCI bus: %02d, PCI slot: %02d %s|")
521 % dspAcfg.DspVersion % dspBcfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
522 % std::string(18 - strlen(dspAcfg.DspVersion) - strlen(dspBcfg.DspVersion), ' '));
523 K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspAcfg.FwVersion);
524 K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspBcfg.FwVersion);
525
526 K::Logger::Logg2(classe, stream, FMT("| * Echo Canceller: %-20s - Location: %-12s |")
527 % Verbose::echoCancellerConfig(devCfg.EchoConfig)
528 % Verbose::echoLocation(devCfg.EchoLocation));
529 } break;
530
531 case Cli::CONCISE:
532 {
533 K::Logger::Logg2(classe, stream, FMT("%02u;%s;%d;%d;%d;%s;%s;%02d;%02d;%s;%s;%s;%s")
534 % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount % devCfg.LinkCount
535 % dspAcfg.DspVersion % dspBcfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
536 % dspAcfg.FwVersion % dspBcfg.FwVersion
537 % Verbose::echoCancellerConfig(devCfg.EchoConfig)
538 % Verbose::echoLocation(devCfg.EchoLocation));
539 } break;
540
541 case Cli::XML:
542 {
543 /* boards/board */
544 switch_xml_t xdev = switch_xml_add_child_d(xdevs,"device",0);
545 switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
546
547 /* boards/board/general */
548 switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
549
550 /* boards/board/general/type */
551 switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
552 switch_xml_set_txt_d(xtype,tipo.c_str());
553
554 /* boards/board/general/serial */
555 switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
556 switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
557
558 /* boards/board/general/channels */
559 switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
560 switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
561
562 /* boards/board/general/links */
563 switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
564 switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
565
566 /* boards/board/hardware */
567 switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
568
569 /* boards/board/hardware/dsps */
570 switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
571
572 /* boards/board/hardware/dsps/dsp (0) */
573 switch_xml_t xdsp0 = switch_xml_add_child_d(xdsps,"dsp",0);
574 switch_xml_set_attr_d(xdsp0,"id","0");
575
576 /* boards/board/hardware/dsps/dsp/version */
577 switch_xml_t xversion0 = switch_xml_add_child_d(xdsp0,"version",0);
578 switch_xml_set_txt_d(xversion0, dspAcfg.DspVersion);
579
580 /* boards/board/hardware/dsps/dsp/firmware */
581 switch_xml_t xfirmware0 = switch_xml_add_child_d(xdsp0,"firmware",0);
582 switch_xml_set_txt_d(xfirmware0,dspAcfg.FwVersion);
583
584 /* boards/board/hardware/dsps/dsp (1) */
585 switch_xml_t xdsp1 = switch_xml_add_child_d(xdsps,"dsp",0);
586 switch_xml_set_attr_d(xdsp1,"id","1");
587
588 /* boards/board/hardware/dsps/dsp/version */
589 switch_xml_t xversion1 = switch_xml_add_child_d(xdsp1,"version",0);
590 switch_xml_set_txt_d(xversion1, dspBcfg.DspVersion);
591
592 /* boards/board/hardware/dsps/dsp/firmware */
593 switch_xml_t xfirmware1 = switch_xml_add_child_d(xdsp1,"firmware",0);
594 switch_xml_set_txt_d(xfirmware1,dspBcfg.FwVersion);
595 } break;
596
597 default:
598 break;
599 }
600 }
601
602 break;
603 }
604
605 /* analog boards */
606 case kdtFXO:
607 case kdtFXOVoIP:
608 /*
609 TODO: This not found
610 case kdtFX:
611 case kdtFXVoIP:
612 */
613 {
614 K3L_FXO80_FW_CONFIG dspCfg;
615
616 if (k3lGetDeviceConfig(i, ksoFirmware + kfiFXO80, &dspCfg, sizeof(dspCfg)) == ksSuccess)
617 {
618 switch(output_type)
619 {
620 case Cli::VERBOSE:
621 {
622 K::Logger::Logg2(classe, stream, FMT("| [[ %02u ]] %s, serial '%s', %02d channels. %s|")
623 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
624 % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
625 K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - PCI bus: %02d, PCI slot: %02d%s|")
626 % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
627 % std::string(30 - strlen(dspCfg.DspVersion), ' '));
628 K::Logger::Logg2(classe, stream, FMT("| * %-63s|") % dspCfg.FwVersion);
629 } break;
630
631 case Cli::CONCISE:
632 {
633 K::Logger::Logg2(classe, stream, FMT("%02u;%s;%d;%d;%s;%02d;%02d;%s")
634 % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
635 % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
636 % dspCfg.FwVersion);
637 } break;
638
639 case Cli::XML:
640 {
641 /* boards/board */
642 switch_xml_t xdev = switch_xml_add_child_d(xdevs,"device",0);
643 switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
644
645 /* boards/board/general */
646 switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
647
648 /* boards/board/general/type */
649 switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
650 switch_xml_set_txt_d(xtype,tipo.c_str());
651
652 /* boards/board/general/serial */
653 switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
654 switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
655
656 /* boards/board/general/channels */
657 switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
658 switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
659
660 /* boards/board/general/links */
661 switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
662 switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
663
664 /* boards/hardware */
665 switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
666
667 /* boards/board/hardware/dsps */
668 switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
669
670 /* boards/board/hardware/dsps/dsp */
671 switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
672 switch_xml_set_attr_d(xdsp,"id","0");
673
674 /* boards/board/hardware/dsps/dsps/version */
675 switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
676 switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
677
678 /* boards/board/hardware/dsps/dsps/firmare */
679 switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
680 switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
681
682 /* boards/board/hardware/pci */
683 switch_xml_t xpci = switch_xml_add_child_d(xhardware,"pci",0);
684 switch_xml_set_attr_d(xpci,"bus" ,STR(FMT("%02d") % devCfg.PciBus ));
685 switch_xml_set_attr_d(xpci,"slot",STR(FMT("%02d") % devCfg.PciSlot));
686 } break;
687
688 default:
689 break;
690 }
691 }
692
693 if (Globals::k3lapi.device_type(i) == kdtFXOVoIP)
694 {
695 if (output_type == Cli::VERBOSE)
696 {
697 K::Logger::Logg2(classe, stream, FMT("| * Echo Canceller: %-20s - Location: %-12s |")
698 % Verbose::echoCancellerConfig(devCfg.EchoConfig)
699 % Verbose::echoLocation(devCfg.EchoLocation));
700 }
701 }
702
703 break;
704 }
705 case kdtGSM:
706 case kdtGSMSpx:
707 {
708 K3L_GSM40_FW_CONFIG dspCfg;
709
710 if (k3lGetDeviceConfig(i, ksoFirmware + kfiGSM40, &dspCfg, sizeof(dspCfg)) == ksSuccess)
711 {
712 switch(output_type)
713 {
714 case Cli::VERBOSE:
715 {
716 K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] %s, serial '%s', %02d channels. %s|")
717 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
718 % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
719
720 K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - PCI bus: %02d, PCI slot: %02d%s|")
721 % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
722 % std::string(std::max<int>(30 - strlen(dspCfg.DspVersion), 0), ' '));
723
724 K::Logger::Logg2(classe, stream, FMT("| * %-62s |") % dspCfg.FwVersion);
725 } break;
726
727 case Cli::CONCISE:
728 {
729 K::Logger::Logg2(classe, stream, FMT("%02d;%s;%d;%d;%s;%02d;%02d;%s")
730 % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
731 % dspCfg.DspVersion % devCfg.PciBus % devCfg.PciSlot
732 % dspCfg.FwVersion);
733 } break;
734
735 case Cli::XML:
736 {
737 /* boards/board */
738 switch_xml_t xdev = switch_xml_add_child_d(xdev,"device",0);
739 switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
740
741 /* boards/board/general */
742 switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
743
744 /* boards/board/general/type */
745 switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
746 switch_xml_set_txt_d(xtype,tipo.c_str());
747
748 /* boards/board/general/serial */
749 switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
750 switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
751
752 /* boards/board/general/channels */
753 switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
754 switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
755
756 /* boards/board/general/links */
757 switch_xml_t xlinks = switch_xml_add_child_d(xgeneral,"links",0);
758 switch_xml_set_txt_d(xlinks, STR(FMT("%d") % devCfg.LinkCount));
759
760 /* boards/board/hardware */
761 switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
762
763 /* boards/board/hardware/dsps */
764 switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
765
766 /* boards/board/hardware/dsps/dsp */
767 switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
768 switch_xml_set_attr_d(xdsp,"id","0");
769
770 /* boards/board/hardware/dsps/dsp/version */
771 switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
772 switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
773
774 /* boards/board/hardware/dsps/dsp/firmware*/
775 switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
776 switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
777
778 /* boards/board/hardware/dsps/dsp/pci */
779 switch_xml_t xpci = switch_xml_add_child_d(xhardware,"pci",0);
780 switch_xml_set_attr_d(xpci,"bus" ,STR(FMT("%02d") % devCfg.PciBus ));
781 switch_xml_set_attr_d(xpci,"slot",STR(FMT("%02d") % devCfg.PciSlot));
782 } break;
783
784 default:
785 break;
786 }
787 }
788
789 break;
790 }
791 case kdtGSMUSB:
792 case kdtGSMUSBSpx:
793 {
794 K3L_GSMUSB_FW_CONFIG dspCfg;
795
796 if (k3lGetDeviceConfig(i, ksoFirmware + kfiGSMUSB, &dspCfg, sizeof(dspCfg)) == ksSuccess)
797 {
798 switch(output_type)
799 {
800 case Cli::VERBOSE:
801 {
802 K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] %s, serial '%s', %02d channels. %s|")
803 % i % tipo % devCfg.SerialNumber % devCfg.ChannelCount
804 % std::string(std::max<int>(0, 30 - tipo.size() - strlen(devCfg.SerialNumber)), ' '));
805
806 int size = strlen(dspCfg.DspVersion) + strlen(dspCfg.FwVersion);
807
808 K::Logger::Logg2(classe, stream, FMT("| * DSP: %s - %s%s|")
809 % dspCfg.DspVersion % dspCfg.FwVersion
810 % std::string(std::max<int>(55 - size, 0), ' '));
811
812 } break;
813
814 case Cli::CONCISE:
815 {
816 K::Logger::Logg2(classe, stream, FMT("%02d;%s;%d;%d;%s;%s")
817 % i % tipo % atoi(devCfg.SerialNumber) % devCfg.ChannelCount
818 % dspCfg.DspVersion % dspCfg.FwVersion);
819 } break;
820
821 case Cli::XML:
822 {
823 /* boards/board */
824 switch_xml_t xdev = switch_xml_add_child_d(xdev,"device",0);
825 switch_xml_set_attr_d(xdev,"id",STR(FMT("%02u") % i));
826
827 /* boards/board/general */
828 switch_xml_t xgeneral = switch_xml_add_child_d(xdev,"general",0);
829
830 /* boards/board/general/type */
831 switch_xml_t xtype = switch_xml_add_child_d(xgeneral,"type",0);
832 switch_xml_set_txt_d(xtype,tipo.c_str());
833
834 /* boards/board/general/serial */
835 switch_xml_t xserial = switch_xml_add_child_d(xgeneral,"serial",0);
836 switch_xml_set_txt_d(xserial, devCfg.SerialNumber);
837
838 /* boards/board/general/channels */
839 switch_xml_t xchannels = switch_xml_add_child_d(xgeneral,"channels",0);
840 switch_xml_set_txt_d(xchannels, STR(FMT("%02d") % devCfg.ChannelCount));
841
842 /* boards/board/hardware */
843 switch_xml_t xhardware = switch_xml_add_child_d(xdev,"hardware",0);
844
845 /* boards/board/hardware/dsps */
846 switch_xml_t xdsps = switch_xml_add_child_d(xhardware,"dsps",0);
847
848 /* boards/board/hardware/dsp */
849 switch_xml_t xdsp = switch_xml_add_child_d(xdsps,"dsp",0);
850 switch_xml_set_attr_d(xdsp,"id","0");
851
852 /* boards/board/hardware/dsps/dsp/version */
853 switch_xml_t xversion_a = switch_xml_add_child_d(xdsp,"version",0);
854 switch_xml_set_txt_d(xversion_a, dspCfg.DspVersion);
855
856 /* boards/board/hardware/dsps/dsp/firmware */
857 switch_xml_t xfirmware = switch_xml_add_child_d(xdsp,"firmware",0);
858 switch_xml_set_txt_d(xfirmware,dspCfg.FwVersion);
859 } break;
860
861 default:
862 break;
863 }
864 }
865
866 break;
867 }
868
869 default:
870 K::Logger::Logg2(classe, stream, FMT("| [[ %02d ]] Unknown type '%02d'! Please contact Khomp support for help! |")
871 % i % Globals::k3lapi.device_type(i));
872 break;
873 }
874 }
875
876 if (output_type == Cli::VERBOSE)
877 K::Logger::Logg2(classe,stream, " ------------------------------------------------------------------");
878
879 if (output_type == Cli::XML)
880 {
881 printXMLOutput(stream);
882 clearRoot();
883 }
884
885 return true;
886 }
887
888 /* support function for _KhompShowCalls */
showCalls(unsigned int d,unsigned int o,std::string & buffer)889 void Cli::_KhompShowCalls::showCalls(unsigned int d, unsigned int o, std::string &buffer)
890 {
891 buffer += STR(FMT("| %d,%02d | unused | %11s | %-36s |\n")
892 % d
893 % o
894 % Globals::k3lutil.callStatus(d,o)
895 % Globals::k3lutil.channelStatus(d,o));
896 }
897
execute(int argc,char * argv[])898 bool Cli::_KhompShowCalls::execute(int argc, char *argv[])
899 {
900 if(argc > 4)
901 {
902 printUsage(stream);
903 return false;
904 }
905
906 int device = argv[2] ? atoi(argv[2]) : -1;
907 int object = argv[3] ? atoi(argv[3]) : -1;
908
909 int d = -1;
910 int o = -1;
911
912 if (device != -1)
913 {
914 d = device;
915
916 if (!Globals::k3lapi.valid_device(d))
917 {
918 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device %d!") % d);
919 return false;
920 }
921 }
922
923 if (object != -1)
924 {
925 o = object;
926
927 if (!Globals::k3lapi.valid_channel(d,o))
928 {
929 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such chanel %d for device %d!") % o % d);
930 return false;
931 }
932 }
933
934 /* keep the channels reponse */
935 std::string buffer("");
936
937 try
938 {
939 /**/ if (d != -1 && o != -1)
940 {
941 showCalls(d,o,buffer);
942 }
943 else if (d != -1 && o == -1)
944 {
945 for (unsigned int i = 0; i < Globals::k3lapi.channel_count(d); i++)
946 {
947 buffer += " ------------------------------------------------------------------------\n";
948 showCalls(d,i,buffer);
949 }
950 }
951 else if (d == -1 && o == -1)
952 {
953 for (unsigned int i = 0; i < Globals::k3lapi.device_count(); i++)
954 {
955 buffer += " ------------------------------------------------------------------------\n";
956 for (unsigned int j = 0; j < Globals::k3lapi.channel_count(i); j++)
957 {
958 showCalls(i,j,buffer);
959 }
960 }
961 }
962 }
963 catch(K3LAPITraits::invalid_channel & err)
964 {
965 K::Logger::Logg2(C_CLI, stream, "ERROR: No such chanel");
966 return false;
967 }
968
969 //TODO: The information shown here, must be reviewed cuz is the same of show channels
970 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
971 K::Logger::Logg2(C_CLI, stream, "|------------------------------- Khomp Calls ----------------------------|");
972 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------ ");
973 K::Logger::Logg2(C_CLI, stream, "| hw | freeSWITCH | khomp call | khomp channel |");
974 K::Logger::Logg2(C_CLI, stream, "| id | status | status | status |");
975 K::Logger::Logg2(C_CLI, stream, "%s", (char*) buffer.c_str());
976 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
977
978 return true;
979 }
980
forceDisconnect(unsigned int device,unsigned int channel)981 bool Cli::_KhompChannelsDisconnect::forceDisconnect(unsigned int device, unsigned int channel)
982 {
983 bool ret = false;
984 Board::KhompPvt *pvt = NULL;
985
986 try
987 {
988 pvt = Board::get(device,channel);
989 ScopedPvtLock lock(pvt);
990
991 ret = pvt->command(KHOMP_LOG,CM_DISCONNECT);
992 DBG(FUNC,PVT_FMT(pvt->target(),"Command CM_DISCONNECT sent!"));
993 }
994 catch (K3LAPITraits::invalid_channel & err)
995 {
996 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
997 }
998 catch (ScopedLockFailed & err)
999 {
1000 K::Logger::Logg2(C_CLI,stream,FMT("error: channel %d at device %d could not be locked: %s!")
1001 % channel
1002 % device
1003 % err._msg.c_str());
1004 }
1005
1006 return ret;
1007 }
1008
execute(int argc,char * argv[])1009 bool Cli::_KhompChannelsDisconnect::execute(int argc, char *argv[])
1010 {
1011 if (argc < 3 || argc > 4)
1012 {
1013 printUsage(stream);
1014 return false;
1015 }
1016
1017 switch (argc)
1018 {
1019 case 3:
1020 {
1021 if (!ARG_CMP(2, "all"))
1022 {
1023 K::Logger::Logg2(C_CLI, stream, "usage: khomp channels disconnect < all | <boardid> < all | <channelid> > >");
1024 return false;
1025 }
1026
1027 K::Logger::Logg2(C_CLI, stream, "NOTICE: Disconnecting all channels on all boards!");
1028
1029 for (unsigned int dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1030 {
1031 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1032 forceDisconnect(dev,chan);
1033 }
1034 break;
1035 }
1036 case 4:
1037 {
1038 unsigned int dev = atoi(argv[2]);
1039
1040 if (ARG_CMP(3, "all"))
1041 {
1042 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Disconnecting all channels on board %d!") % dev);
1043
1044 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1045 forceDisconnect(dev,chan);
1046 }
1047
1048 unsigned int channel = atoi(argv[3]);
1049
1050 if (dev >= Globals::k3lapi.device_count())
1051 {
1052 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
1053 return false;
1054 }
1055
1056
1057 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Disconnecting channel %d on board %d!") % channel % dev);
1058
1059 forceDisconnect(dev,channel);
1060 break;
1061 }
1062
1063 default:
1064 break;
1065 }
1066
1067 return true;
1068 }
1069
execute(int argc,char * argv[])1070 bool Cli::_KhompChannelsUnblock::execute(int argc, char *argv[])
1071 {
1072 if (argc != 4 && argc != 3)
1073 {
1074 printUsage(stream);
1075 return false;
1076 }
1077
1078 switch (argc)
1079 {
1080 case 3:
1081 {
1082 K::Logger::Logg2(C_CLI, stream, "NOTICE: Unblocking all channels on all devices!");
1083 for (unsigned int dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1084 {
1085 for (unsigned int chan = 0; chan < Globals::k3lapi.channel_count(dev); chan++)
1086 {
1087 try
1088 {
1089 Globals::k3lapi.command(dev,chan,CM_UNLOCK_INCOMING);
1090 Globals::k3lapi.command(dev,chan,CM_UNLOCK_OUTGOING);
1091 }
1092 catch(K3LAPI::failed_command &e)
1093 {
1094 if (K::Logger::Logg.classe(C_WARNING).enabled())
1095 {
1096 LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1097 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1098 }
1099
1100 return false;
1101 }
1102 }
1103 }
1104 break;
1105 }
1106 case 4:
1107 {
1108 int dev = atoi (argv[2]);
1109
1110 if ( !SAFE_strcasecmp(argv[3], "all") )
1111 {
1112 if (!Globals::k3lapi.valid_device( dev ))
1113 {
1114 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find device: %d!") % dev );
1115 return false;
1116 }
1117
1118 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Unblocking all channels on device %d!") % dev);
1119
1120 for (unsigned int i = 0; i < Globals::k3lapi.channel_count(dev); i++)
1121 {
1122 try
1123 {
1124 Globals::k3lapi.command(dev,i,CM_UNLOCK_INCOMING);
1125 Globals::k3lapi.command(dev,i,CM_UNLOCK_OUTGOING);
1126 }
1127 catch(K3LAPI::failed_command &e)
1128 {
1129 if (K::Logger::Logg.classe(C_WARNING).enabled())
1130 {
1131 LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1132 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1133 }
1134
1135 return false;
1136 }
1137 }
1138 }
1139 else
1140 {
1141 int obj = atoi (argv[3]);
1142
1143 if (!Globals::k3lapi.valid_channel(dev, obj))
1144 {
1145 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such channel %d at device %d!") % obj % dev);
1146 return false;
1147 }
1148
1149 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Unblocking channel %d on device %d!") % obj % dev);
1150
1151 try
1152 {
1153 Globals::k3lapi.command(dev,obj,CM_UNLOCK_INCOMING);
1154 Globals::k3lapi.command(dev,obj,CM_UNLOCK_OUTGOING);
1155 }
1156 catch(K3LAPI::failed_command &e)
1157 {
1158 if (K::Logger::Logg.classe(C_WARNING).enabled())
1159 {
1160 LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
1161 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
1162 }
1163
1164 return false;
1165 }
1166 }
1167 break;
1168 }
1169 default:
1170 break;
1171 }
1172
1173 return true;
1174 }
1175
cliStatistics(unsigned int device,OutputType output_type)1176 void Cli::_KhompShowStatistics::cliStatistics(unsigned int device, OutputType output_type)
1177 {
1178 if(output_type == Cli::XML)
1179 {
1180 /* device */
1181 xdevs = switch_xml_add_child_d(root,"device",0);
1182 switch_xml_set_attr_d(xdevs,"id",STR(FMT("%d") % device));
1183 }
1184
1185 for (unsigned int channel = 0; channel < Globals::k3lapi.channel_count(device); channel++)
1186 {
1187 try
1188 {
1189 Board::KhompPvt *pvt = Board::get(device, channel);
1190 switch(output_type)
1191 {
1192 case Cli::VERBOSE:
1193 K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::ROW).c_str());
1194 break;
1195 case Cli::CONCISE:
1196 /* do we need concise ? */
1197 break;
1198 case Cli::XML:
1199 switch_xml_insert(pvt->getStatisticsXML(Statistics::ROW),xdevs,0);
1200 break;
1201 }
1202 }
1203 catch (K3LAPITraits::invalid_channel & err)
1204 {
1205 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1206 }
1207 }
1208 }
1209
cliDetailedStatistics(unsigned int device,unsigned int channel,OutputType output_type)1210 void Cli::_KhompShowStatistics::cliDetailedStatistics(unsigned int device, unsigned int channel, OutputType output_type)
1211 {
1212 try
1213 {
1214 Board::KhompPvt *pvt = Board::get(device, channel);
1215 switch(output_type)
1216 {
1217 case Cli::DETAILED:
1218 {
1219 K::Logger::Logg2(C_CLI,stream,"----------------------------------------------");
1220 K::Logger::Logg2(C_CLI,stream,FMT("Detailed statistics of: Device %02d - Channel %02d") % pvt->target().device % pvt->target().object);
1221 K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::DETAILED).c_str());
1222 K::Logger::Logg2(C_CLI,stream,"----------------------------------------------");
1223 } break;
1224
1225 case Cli::CONCISE:
1226 {
1227 /* We don't have xml, need concise yet ? */
1228 } break;
1229
1230 case Cli::XML:
1231 {
1232 /* We don't have concise, need XML yet ? */
1233 } break;
1234 }
1235 }
1236 catch (K3LAPITraits::invalid_channel & err)
1237 {
1238 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1239 }
1240 }
1241
execute(int argc,char * argv[])1242 bool Cli::_KhompShowStatistics::execute(int argc, char *argv[])
1243 {
1244 if (argc < 2 || argc > 5)
1245 {
1246 printUsage(stream);
1247 return false;
1248 }
1249
1250 unsigned int dev = UINT_MAX;
1251 unsigned int obj = UINT_MAX;
1252 int detailed = 0, verbose = 0, as_xml = 0;
1253 OutputType output_type = Cli::VERBOSE;
1254
1255 detailed = ((argc > 2) && (!strcasecmp(argv[2], "detailed")) ? 1 : 0 );
1256 verbose = ((argc > 2) && (!strcasecmp(argv[2], "verbose")) ? 1 : 0 );
1257 as_xml = ((argc > 2) && (!strcasecmp(argv[2], "xml")) ? 1 : 0 );
1258
1259 try
1260 {
1261 if(argc > (2+detailed+verbose+as_xml))
1262 {
1263 dev = Strings::tolong(argv[2+detailed+verbose+as_xml]);
1264 if (!Globals::k3lapi.valid_device(dev))
1265 {
1266 K::Logger::Logg2(C_CLI, stream, "ERROR: No such device!");
1267 return false;
1268 }
1269 }
1270
1271 if (argc > (3+detailed+verbose+as_xml))
1272 {
1273 std::string object(argv[3+detailed+verbose+as_xml]);
1274 obj = Strings::tolong(object);
1275
1276 if (!Globals::k3lapi.valid_channel(dev, obj))
1277 {
1278 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % obj % dev );
1279 return false;
1280 }
1281 }
1282 }
1283 catch (Strings::invalid_value e)
1284 {
1285 K::Logger::Logg2(C_CLI, stream, "ERROR: Invalid numeric value!");
1286 return false;
1287 }
1288
1289 if(detailed) output_type = Cli::DETAILED;
1290 if(as_xml)
1291 {
1292 createRoot("statistics");
1293 output_type = Cli::XML;
1294 }
1295
1296 std::string header;
1297 header.append( " ------------------------------------------------------------------------------------\n");
1298 header.append( "|----------------------------- Khomp Endpoint Statistics ----------------------------|\n");
1299 header.append( "|------------------------------------------------------------------------------------|\n");
1300 header.append( "| hw | total calls | channel | FreeSWITCH | channel | status |\n");
1301 header.append( "| id | incoming | outgoing | failed | fails | status | state | time |\n");
1302 header.append( " ------------------------------------------------------------------------------------");
1303 std::string footer;
1304 footer.append( " ------------------------------------------------------------------------------------");
1305
1306 try
1307 {
1308 if (obj != UINT_MAX)
1309 {
1310 switch(output_type)
1311 {
1312 case Cli::VERBOSE:
1313 {
1314 K::Logger::Logg2(C_CLI,stream,header.c_str());
1315 Board::KhompPvt *pvt = Board::get(dev, obj);
1316 K::Logger::Logg2(C_CLI,stream,pvt->getStatistics(Statistics::ROW).c_str());
1317 K::Logger::Logg2(C_CLI,stream,footer.c_str());
1318 } break;
1319
1320 case Cli::DETAILED:
1321 {
1322 cliDetailedStatistics (dev, obj, output_type);
1323 } break;
1324
1325 case Cli::XML:
1326 {
1327 /* no problem, nothing created */
1328 switch_xml_t xboard = NULL;
1329
1330 /* device */
1331 xdevs = switch_xml_add_child_d(root,"device",0);
1332 switch_xml_set_attr_d(xdevs,"id",STR(FMT("%d") % dev));
1333
1334 try
1335 {
1336 Board::KhompPvt *pvt = Board::get(dev, obj);
1337 switch_xml_insert(pvt->getStatisticsXML(Statistics::ROW),xdevs,0);
1338 }
1339 catch (K3LAPITraits::invalid_channel & err)
1340 {
1341 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1342 }
1343
1344 printXMLOutput(stream);
1345 clearRoot();
1346 } break;
1347 }
1348 }
1349 else
1350 {
1351 switch(output_type)
1352 {
1353 case Cli::VERBOSE:
1354 {
1355 K::Logger::Logg2(C_CLI,stream,header.c_str());
1356
1357 if (dev == UINT_MAX)
1358 {
1359 for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1360 cliStatistics (dev, output_type);
1361 }
1362 else
1363 {
1364 cliStatistics (dev, output_type);
1365 }
1366
1367 K::Logger::Logg2(C_CLI,stream,footer.c_str());
1368 } break;
1369
1370 case Cli::XML:
1371 {
1372 if (dev == UINT_MAX)
1373 {
1374 for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1375 cliStatistics (dev, output_type);
1376 }
1377 else
1378 {
1379 cliStatistics (dev, output_type);
1380 }
1381
1382 printXMLOutput(stream);
1383 clearRoot();
1384
1385 } break;
1386
1387 case Cli::DETAILED:
1388 {
1389 printUsage(stream);
1390 return false;
1391 } break;
1392 }
1393 }
1394 }
1395 catch(K3LAPITraits::invalid_channel &e)
1396 {
1397 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % obj % dev );
1398 }
1399
1400 return true;
1401 }
1402
showChannel(unsigned int device,unsigned int channel,OutputType output_type)1403 void Cli::_KhompShowChannels::showChannel(unsigned int device, unsigned int channel, OutputType output_type)
1404 {
1405 try
1406 {
1407 Board::KhompPvt *pvt = Board::get(device, channel);
1408
1409 DBG(FUNC, PVT_FMT(pvt->target(), "found channel.."));
1410
1411 /* skip inactive channels */
1412 if (pvt->getSignaling() == ksigInactive)
1413 return;
1414
1415 DBG(FUNC, PVT_FMT(pvt->target(), "is valid.."));
1416
1417 /* make sure the states wont start 'dancing' at random.. */
1418 ScopedPvtLock lock(pvt);
1419
1420 std::string tmp_call = Globals::k3lutil.callStatus(
1421 pvt->target().device,
1422 pvt->target().object,
1423 (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1424
1425 std::string tmp_chan = Globals::k3lutil.channelStatus(
1426 pvt->target().device,
1427 pvt->target().object,
1428 (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1429
1430
1431 switch(output_type)
1432 {
1433 case Cli::VERBOSE:
1434 {
1435 if (pvt->getSignaling() == ksigGSM)
1436 {
1437 K3L_GSM_CHANNEL_STATUS gsmStatus;
1438
1439 if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1440 return;
1441
1442 const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1443
1444 const unsigned int full_size = 10;
1445 const unsigned int sign_size = std::min((sign_numb * full_size) / 100, full_size);
1446
1447 std::string tmp_antenna_level;
1448
1449 for (unsigned int i = 0; i < sign_size; i++)
1450 tmp_antenna_level += '*';
1451
1452 for (unsigned int i = sign_size; i < full_size; i++)
1453 tmp_antenna_level += ' ';
1454
1455 tmp_chan += " (";
1456 tmp_chan += (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "...");
1457 tmp_chan += ")";
1458
1459 K::Logger::Logg2(C_CLI, stream, FMT("| %d,%02d | %8s | %8s | %-23s | %02d%% |%s|")
1460 % device % channel % pvt->getStateString() % tmp_call % tmp_chan
1461 % sign_numb % tmp_antenna_level);
1462 }
1463 else
1464 {
1465 K::Logger::Logg2(C_CLI, stream, FMT("| %d,%02d | %8s | %8s | %-40s |")
1466 % device % channel % pvt->getStateString() % tmp_call % tmp_chan);
1467 }
1468
1469 } break;
1470
1471 case Cli::CONCISE:
1472 {
1473 std::string state = pvt->getStateString();
1474
1475 if (pvt->getSignaling() == ksigGSM)
1476 {
1477 K3L_GSM_CHANNEL_STATUS gsmStatus;
1478
1479 if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1480 return;
1481
1482 const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1483
1484 std::string gsm_registry = (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "<none>");
1485
1486 K::Logger::Logg2(C_CLI, stream, FMT("B%02dC%02d:%s:%s:%s:%d%%:%s")
1487 % device % channel % state % tmp_call % tmp_chan
1488 % sign_numb % gsm_registry);
1489 }
1490 else
1491 {
1492 K::Logger::Logg2(C_CLI, stream, FMT("B%02dC%02d:%s:%s:%s")
1493 % device % channel % state % tmp_call % tmp_chan);
1494 }
1495
1496 } break;
1497
1498 case Cli::XML:
1499 {
1500 /* device/channel */
1501 switch_xml_t xchannel = switch_xml_add_child_d(xdev,"channel",0);
1502 switch_xml_set_attr_d(xchannel,"id",STR(FMT("%d") % channel));
1503
1504 /* device/channel/fs_state */
1505 switch_xml_t xstate = switch_xml_add_child_d(xchannel,"fs_state",0);
1506 switch_xml_set_txt_d(xstate, pvt->getStateString().c_str());
1507
1508 /* device/channel/call */
1509 switch_xml_t xcall = switch_xml_add_child_d(xchannel,"call",0);
1510 switch_xml_set_txt_d(xcall, tmp_call.c_str());
1511
1512 /* device/channel/status */
1513 switch_xml_t xstatus = switch_xml_add_child_d(xchannel,"status",0);
1514 switch_xml_set_txt_d(xstatus, tmp_chan.c_str());
1515
1516 if (pvt->getSignaling() == ksigGSM)
1517 {
1518 K3L_GSM_CHANNEL_STATUS gsmStatus;
1519
1520 if (k3lGetDeviceStatus(device, channel + ksoGsmChannel, &gsmStatus, sizeof(gsmStatus)) != ksSuccess)
1521 return;
1522
1523 const unsigned int sign_numb = (gsmStatus.SignalStrength != 255 ? gsmStatus.SignalStrength : 0);
1524 std::string gsm_registry = (strlen(gsmStatus.OperName) != 0 ? gsmStatus.OperName : "<none>");
1525
1526 /* device/channel/signal */
1527 switch_xml_t xsign_numb = switch_xml_add_child_d(xchannel, "signal", 0);
1528 switch_xml_set_txt_d(xsign_numb, STR(FMT("%d") % sign_numb));
1529
1530 /* device/channel/registry */
1531 switch_xml_t xgsm_registry = switch_xml_add_child_d(xchannel, "registry", 9);
1532 switch_xml_set_txt_d(xgsm_registry, gsm_registry.c_str());
1533 }
1534
1535 } break;
1536
1537 default:
1538 /* do nothing */
1539 break;
1540 }
1541
1542 }
1543 catch (K3LAPITraits::invalid_channel & err)
1544 {
1545 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
1546 }
1547 catch (...)
1548 {
1549 K::Logger::Logg2(C_CLI, stream, "ERROR: Unexpected error..., skipping");
1550 }
1551 }
1552
showChannels(unsigned int device,OutputType output_type)1553 void Cli::_KhompShowChannels::showChannels(unsigned int device, OutputType output_type)
1554 {
1555 if(output_type == Cli::XML)
1556 {
1557 /* channels/device */
1558 xdev = switch_xml_add_child_d(root,"device",0);
1559 switch_xml_set_attr_d(xdev, "id", STR(FMT("%d") % device));
1560 }
1561
1562 for (unsigned int channel = 0; channel < Globals::k3lapi.channel_count(device); channel++)
1563 {
1564 showChannel(device, channel, output_type);
1565 }
1566 }
1567
execute(int argc,char * argv[])1568 bool Cli::_KhompShowChannels::execute(int argc, char *argv[])
1569 {
1570 unsigned int dev = UINT_MAX;
1571 int concise = 0, verbose = 0, as_xml = 0;
1572 OutputType output_type = Cli::VERBOSE;
1573
1574 bool onlyShowOneChannel = false;
1575 unsigned int channelToShow = 0;
1576
1577 if (argc > 5)
1578 {
1579 Cli::KhompShowChannels.printUsage(stream);
1580 return false;
1581 }
1582
1583 concise = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "concise")) ? 1 : 0 );
1584 verbose = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "verbose")) ? 1 : 0 );
1585 as_xml = ( ((argc == 3) || (argc == 4) || (argc == 5) ) && (ARG_CMP(2, "xml")) ? 1 : 0 );
1586
1587 if (argc >= (3 + concise + verbose + as_xml))
1588 {
1589 dev = atoi (argv[2 + concise + verbose + as_xml]);
1590
1591 if (!Globals::k3lapi.valid_device(dev))
1592 {
1593 K::Logger::Logg2(C_CLI, stream, "ERROR: no such device!");
1594 return false;
1595 }
1596
1597 if (argc == ( 4 + concise + verbose + as_xml))
1598 {
1599 onlyShowOneChannel = true;
1600 channelToShow = atoi (argv[3 + concise + verbose + as_xml]);
1601 }
1602 }
1603
1604 if (concise == 0 && as_xml == 0)
1605 {
1606 K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1607 K::Logger::Logg2(C_CLI, stream, "|-------------------- Khomp Channels and Connections -------------------|");
1608 K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1609 K::Logger::Logg2(C_CLI, stream, "| hw |freeSWITCH| call | channel |");
1610 K::Logger::Logg2(C_CLI, stream, "| id | status | status | status |");
1611 K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1612 }
1613
1614 if (concise != 0) output_type = Cli::CONCISE;
1615 if (as_xml != 0)
1616 {
1617 output_type = Cli::XML;
1618
1619 /* channels */
1620 createRoot("channels");
1621 }
1622
1623 if ( onlyShowOneChannel )
1624 {
1625 if ( channelToShow < Globals::k3lapi.channel_count(dev) )
1626 {
1627 if(output_type == Cli::XML)
1628 {
1629 /* channels/device */
1630 xdev = switch_xml_add_child_d(root,"device",0);
1631 switch_xml_set_attr_d(xdev, "id", STR(FMT("%d") % dev));
1632 }
1633
1634 showChannel (dev, channelToShow, output_type);
1635 }
1636 else
1637 {
1638 K::Logger::Logg2(C_CLI, stream, "ERROR: no such channel!");
1639 }
1640 }
1641 else if (dev == UINT_MAX)
1642 {
1643 for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
1644 {
1645 showChannels(dev, output_type);
1646 }
1647 }
1648 else
1649 {
1650 showChannels ( dev, output_type);
1651 }
1652
1653 if (concise == 0 && as_xml == 0)
1654 K::Logger::Logg2(C_CLI, stream, " -----------------------------------------------------------------------");
1655
1656 if(output_type == Cli::XML)
1657 {
1658 printXMLOutput(stream);
1659 clearRoot();
1660 }
1661
1662 return true;
1663 }
1664
getLinkStatus(int dev,int obj,Verbose::Presentation fmt)1665 std::string Cli::_KhompShowLinks::getLinkStatus(int dev, int obj, Verbose::Presentation fmt)
1666 {
1667 switch(Globals::k3lapi.device_type(dev))
1668 {
1669 case kdtE1FXSSpx:
1670 if (obj == 1)
1671 return Globals::k3lutil.linkStatus(dev, obj, fmt, ksigAnalogTerminal, true);
1672 default:
1673 break;
1674 }
1675
1676 std::string res;
1677
1678 try
1679 {
1680 const K3L_LINK_CONFIG & conf = Globals::k3lapi.link_config(dev, obj);
1681
1682 res = Globals::k3lutil.linkStatus(dev, obj, fmt);
1683
1684 if (conf.ReceivingClock & 0x01)
1685 res += (fmt == Verbose::EXACT ? ",sync" : " (sync)");
1686 }
1687 catch (K3LAPITraits::invalid_target & e)
1688 {
1689 res = "<error>";
1690 }
1691
1692 return res;
1693 }
1694
showLinks(unsigned int device,OutputType output_type)1695 void Cli::_KhompShowLinks::showLinks(unsigned int device, OutputType output_type)
1696 {
1697 if (output_type != Cli::CONCISE && output_type != Cli::XML)
1698 K::Logger::Logg2(C_CLI, stream, "|------------------------------------------------------------------------|");
1699
1700 switch (Globals::k3lutil.physicalLinkCount(device, true))
1701 {
1702 case 1:
1703 {
1704 std::string str_link0 = getLinkStatus(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1705
1706 switch(output_type)
1707 {
1708 case Cli::VERBOSE:
1709 {
1710 K::Logger::Logg2(C_CLI, stream, FMT("| Link '0' on board '%d': %-47s |") % device % str_link0);
1711 } break;
1712
1713 case Cli::CONCISE:
1714 {
1715 K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL00:%s") % device % str_link0);
1716 } break;
1717
1718 case Cli::XML:
1719 {
1720 /* device */
1721 xdev = switch_xml_add_child_d(root,"device",0);
1722 switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1723
1724 /* device/links */
1725 switch_xml_t xlinks = switch_xml_add_child_d(xdev,"links",0);
1726
1727 /* device/links/link */
1728 switch_xml_t xlink = switch_xml_add_child_d(xlinks,"link",0);
1729 switch_xml_set_attr_d(xlink, "id", "0");
1730 switch_xml_set_txt_d(xlink, str_link0.c_str());
1731 } break;
1732 }
1733
1734 break;
1735 }
1736
1737 case 2:
1738 {
1739 std::string str_link0 = getLinkStatus(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1740 std::string str_link1 = getLinkStatus(device, 1, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1741
1742 switch(output_type)
1743 {
1744 case Cli::VERBOSE:
1745 {
1746 K::Logger::Logg2(C_CLI, stream, FMT("|------ Link '0' on board '%d' ------||------ Link '1' on board '%d' ------|")
1747 % device % device);
1748
1749 K::Logger::Logg2(C_CLI, stream, FMT("| %-33s || %-33s |") % str_link0 % str_link1);
1750 } break;
1751
1752 case Cli::CONCISE:
1753 {
1754 K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL00:%s") % device % str_link0);
1755 K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dL01:%s") % device % str_link1);
1756 } break;
1757
1758 case Cli::XML:
1759 {
1760 /* device */
1761 xdev = switch_xml_add_child_d(root,"device",0);
1762 switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1763
1764 /* device/links */
1765 switch_xml_t xlinks = switch_xml_add_child_d(xdev,"links",0);
1766
1767 /* device/links/link (0) */
1768 switch_xml_t xlink = switch_xml_add_child_d(xlinks,"link",0);
1769 switch_xml_set_attr_d(xlink, "id", "0");
1770 switch_xml_set_txt_d(xlink, str_link0.c_str());
1771
1772 /* device/links/link (1) */
1773 switch_xml_t xlink1 = switch_xml_add_child_d(xlinks,"link",0);
1774 switch_xml_set_attr_d(xlink1, "id", "1");
1775 switch_xml_set_txt_d(xlink1, str_link0.c_str());
1776 } break;
1777 }
1778
1779 break;
1780 }
1781 default:
1782 {
1783 switch(output_type)
1784 {
1785 case Cli::VERBOSE:
1786 {
1787 K::Logger::Logg2(C_CLI, stream, FMT("| Board '%d': %-59s |") % device % "No links available.");
1788 } break;
1789
1790 case Cli::CONCISE:
1791 {
1792 K::Logger::Logg2(C_MESSAGE, stream, FMT("B%02dLXX:NoLinksAvailable") % device);
1793 } break;
1794
1795 case Cli::XML:
1796 {
1797 /* device */
1798 xdev = switch_xml_add_child_d(root,"device",0);
1799 switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1800 switch_xml_set_txt_d(xdev,"NoLinksAvailable");
1801 } break;
1802 }
1803
1804 break;
1805 }
1806 }
1807 }
1808
showErrors(unsigned int device,OutputType output_type)1809 void Cli::_KhompShowLinks::showErrors(unsigned int device, OutputType output_type)
1810 {
1811 if (output_type != Cli::CONCISE && output_type != Cli::XML)
1812 K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1813
1814 switch (Globals::k3lutil.physicalLinkCount(device, true))
1815 {
1816 case 2:
1817 {
1818 K3LUtil::ErrorCountType link0 = Globals::k3lutil.linkErrorCount(
1819 device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1820 K3LUtil::ErrorCountType link1 = Globals::k3lutil.linkErrorCount(
1821 device, 1, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1822
1823 switch(output_type)
1824 {
1825 case Cli::VERBOSE:
1826 {
1827 K::Logger::Logg2(C_CLI, stream, FMT("|----- Link '0' on board '%d' ------| |----- Link '1' on board '%d' ------|") % device % device);
1828 K::Logger::Logg2(C_CLI, stream, "|----------------------------------| |----------------------------------|");
1829 K::Logger::Logg2(C_CLI, stream, "| Error type | Number | | Error type | Number |");
1830 K::Logger::Logg2(C_CLI, stream, "|----------------------------------| |----------------------------------|");
1831
1832 K3LUtil::ErrorCountType::iterator i = link0.begin();
1833 K3LUtil::ErrorCountType::iterator j = link1.begin();
1834
1835 for (; i != link0.end() && j != link1.end(); i++, j++)
1836 {
1837 K::Logger::Logg2(C_CLI, stream, FMT("| %22s | %-7d | | %22s | %-7d |")
1838 % i->first % i->second % j->first % j->second);
1839 }
1840 } break;
1841
1842 case Cli::CONCISE:
1843 {
1844 for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1845 K::Logger::Logg2(C_CLI, stream, FMT("%d:0:%s:%d") % device % i->first % i->second);
1846
1847 for (K3LUtil::ErrorCountType::iterator i = link1.begin(); i != link1.end(); i++)
1848 K::Logger::Logg2(C_CLI, stream, FMT("%d:1:%s:%d") % device % i->first % i->second);
1849 } break;
1850
1851 case Cli::XML:
1852 {
1853 /* device */
1854 xdev = switch_xml_add_child_d(root,"device",0);
1855 switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1856
1857 /* device/errors */
1858 switch_xml_t xerrors = switch_xml_add_child_d(xdev,"errors",0);
1859
1860 /* device/errors/link (0) */
1861 switch_xml_t xlinks0 = switch_xml_add_child_d(xerrors,"link",0);
1862 switch_xml_set_attr_d(xlinks0,"id","0");
1863
1864 for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1865 {
1866 /* device/errors/link/type */
1867 switch_xml_t xtype0 = switch_xml_add_child_d(xlinks0,"type",0);
1868 switch_xml_set_txt_d(xtype0,i->first.c_str());
1869
1870 /* device/errors/link/number */
1871 switch_xml_t xnumber0 = switch_xml_add_child_d(xlinks0,"number",0);
1872 switch_xml_set_txt_d(xnumber0,STR(FMT("%d") % i->second));
1873 }
1874
1875 /* device/errors/link (1) */
1876 switch_xml_t xlinks1 = switch_xml_add_child_d(xerrors,"link",0);
1877 switch_xml_set_attr_d(xlinks1,"id","1");
1878
1879 for (K3LUtil::ErrorCountType::iterator i = link1.begin(); i != link1.end(); i++)
1880 {
1881 /* device/errors/link/type */
1882 switch_xml_t xtype1 = switch_xml_add_child_d(xlinks1,"type",0);
1883 switch_xml_set_txt_d(xtype1,i->first.c_str());
1884
1885 /* device/errors/link/number */
1886 switch_xml_t xnumber1 = switch_xml_add_child_d(xlinks1,"number",0);
1887 switch_xml_set_txt_d(xnumber1,STR(FMT("%d") % i->second));
1888 }
1889 } break;
1890 }
1891
1892 break;
1893 }
1894
1895 case 1:
1896 {
1897 K3LUtil::ErrorCountType link0 = Globals::k3lutil.linkErrorCount(device, 0, (output_type == Cli::CONCISE ? Verbose::EXACT : Verbose::HUMAN));
1898
1899 switch(output_type)
1900 {
1901 case Cli::VERBOSE:
1902 {
1903 K::Logger::Logg2(C_CLI, stream, FMT("|------------------------ Link '0' on board '%d' ------------------------|") % device);
1904 K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1905 K::Logger::Logg2(C_CLI, stream, "| Error type | Number |");
1906 K::Logger::Logg2(C_CLI, stream, "|-----------------------------------------------------------------------|");
1907
1908 for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1909 K::Logger::Logg2(C_CLI, stream, FMT("| %52s | %-14d |") % i->first % i->second);
1910 } break;
1911
1912 case Cli::CONCISE:
1913 {
1914 for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1915 K::Logger::Logg2(C_CLI, stream, FMT("%d:0:%s:%d") % device % i->first % i->second);
1916 } break;
1917
1918 case Cli::XML:
1919 {
1920 /* device */
1921 xdev = switch_xml_add_child_d(root,"device",0);
1922 switch_xml_set_attr_d(xdev,"id",STR(FMT("%d") % device));
1923
1924 /* device/errors */
1925 switch_xml_t xerrors = switch_xml_add_child_d(xdev,"errors",0);
1926
1927 /* device/errors/link (0) */
1928 switch_xml_t xlinks0 = switch_xml_add_child_d(xerrors,"link",0);
1929 switch_xml_set_attr_d(xlinks0,"id","0");
1930
1931 for (K3LUtil::ErrorCountType::iterator i = link0.begin(); i != link0.end(); i++)
1932 {
1933 /* device/errors/link/type */
1934 switch_xml_t xtype0 = switch_xml_add_child_d(xlinks0,"type",0);
1935 switch_xml_set_txt_d(xtype0,i->first.c_str());
1936
1937 /* device/errors/link/number */
1938 switch_xml_t xnumber0 = switch_xml_add_child_d(xlinks0,"number",0);
1939 switch_xml_set_txt_d(xnumber0,STR(FMT("%d") % i->second));
1940 }
1941 } break;
1942 }
1943
1944 break;
1945 }
1946
1947 case 0:
1948 {
1949 if (output_type != Cli::XML && output_type != Cli::CONCISE)
1950 K::Logger::Logg2(C_CLI, stream, FMT("| No links detected on board %d! |") % device);
1951
1952 break;
1953 }
1954 }
1955 }
1956
execute(int argc,char * argv[])1957 bool Cli::_KhompShowLinks::execute(int argc, char *argv[])
1958 {
1959 if(argc < 2 || argc > 5)
1960 {
1961 printUsage(stream);
1962 return false;
1963 }
1964
1965 unsigned int dev = UINT_MAX;
1966 int concise = 0, verbose = 0, as_xml = 0, errors = 0;
1967 OutputType output_type = Cli::VERBOSE;
1968
1969 errors = ( (argc > 2) && (!strcasecmp(argv[2],"errors")) ? 1 : 0 );
1970
1971 concise = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"concise")) ? 1 : 0 );
1972 verbose = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"verbose")) ? 1 : 0 );
1973 as_xml = ( (argc > (2+errors)) && (!strcasecmp(argv[(2+errors)],"xml")) ? 1 : 0 );
1974
1975 if(argc > (2+errors+concise+verbose+as_xml))
1976 {
1977 dev = atoi(argv[(2+errors+concise+verbose+as_xml)]);
1978
1979 if (!Globals::k3lapi.valid_device(dev))
1980 {
1981 K::Logger::Logg2(C_CLI, stream, "ERROR: no such device!");
1982 return false;
1983 }
1984 }
1985
1986
1987 if (!concise && !as_xml)
1988 {
1989 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
1990 if(!errors)
1991 {
1992 K::Logger::Logg2(C_CLI, stream, "|--------------------------- Khomp Links List ---------------------------|");
1993 }
1994 else
1995 {
1996 K::Logger::Logg2(C_CLI, stream, "|-------------------- Khomp Errors Counters on Links -------------------|");
1997 }
1998 }
1999
2000 if(concise) output_type = Cli::CONCISE;
2001 if(as_xml)
2002 {
2003 output_type = Cli::XML;
2004 createRoot("links");
2005 }
2006
2007 if (dev == UINT_MAX)
2008 {
2009 for (dev = 0; dev < Globals::k3lapi.device_count(); dev++)
2010 {
2011 if(!errors)
2012 {
2013 showLinks (dev, output_type);
2014 }
2015 else
2016 {
2017 showErrors(dev, output_type);
2018 }
2019 }
2020 }
2021 else
2022 {
2023 if(!errors)
2024 {
2025 showLinks (dev, output_type);
2026 }
2027 else
2028 {
2029 showErrors(dev, output_type);
2030 }
2031 }
2032
2033 if (!concise && !as_xml)
2034 {
2035 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2036 }
2037
2038 if (as_xml)
2039 {
2040 printXMLOutput(stream);
2041 clearRoot();
2042 }
2043
2044 return true;
2045 }
2046
clearLink(unsigned int device,unsigned int link)2047 void Cli::_KhompClearLinks::clearLink(unsigned int device, unsigned int link)
2048 {
2049 try
2050 {
2051 Globals::k3lapi.command(device, link, CM_CLEAR_LINK_ERROR_COUNTER);
2052 }
2053 catch(K3LAPI::failed_command & e)
2054 {
2055 K::Logger::Logg2(C_CLI, stream,
2056 FMT("ERROR: Command has failed with error '%s'")
2057 % Verbose::status((KLibraryStatus)e.rc).c_str());
2058 }
2059 }
2060
execute(int argc,char * argv[])2061 bool Cli::_KhompClearLinks::execute(int argc, char *argv[])
2062 {
2063 if(argc < 2 || argc > 4)
2064 {
2065 printUsage(stream);
2066 return false;
2067 }
2068
2069 unsigned int dev = UINT_MAX;
2070 unsigned int obj = UINT_MAX;
2071
2072 if(argc > 2)
2073 {
2074 dev = atoi(argv[2]);
2075
2076 if (!Globals::k3lapi.valid_device(dev))
2077 {
2078 K::Logger::Logg2(C_CLI, stream,
2079 FMT("ERROR: no such device %d!") % dev);
2080 return false;
2081 }
2082
2083 if(argc > 3)
2084 {
2085 obj = atoi(argv[3]);
2086
2087 if(!Globals::k3lapi.valid_link(dev, obj))
2088 {
2089 K::Logger::Logg2(C_CLI, stream,
2090 FMT("ERROR: No such link %d on device %d!") % obj % dev);
2091 return false;
2092 }
2093 }
2094 }
2095
2096 if(dev == UINT_MAX)
2097 {
2098 K::Logger::Logg2(C_CLI, stream,
2099 "NOTICE: Reseting error count of all links...");
2100
2101 for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2102 {
2103 unsigned int link_count = Globals::k3lutil.physicalLinkCount(d, true);
2104
2105 for (unsigned int o = 0; o < link_count; o++)
2106 clearLink(d, o);
2107 }
2108 }
2109 else
2110 {
2111 if (obj == UINT_MAX)
2112 {
2113 K::Logger::Logg2(C_CLI, stream,
2114 FMT("NOTICE: Reseting error count of all links on device %d...")
2115 % dev);
2116 unsigned int link_count = Globals::k3lutil.physicalLinkCount(dev, true);
2117
2118 for (unsigned int o = 0; o < link_count; o++)
2119 clearLink(dev, o);
2120 }
2121 else
2122 {
2123 K::Logger::Logg2(C_CLI, stream,
2124 FMT("NOTICE: Reseting error count of link %d on device %d...")
2125 % obj % dev);
2126
2127 clearLink(dev, obj);
2128 }
2129 }
2130
2131 return true;
2132 }
2133
execute(int argc,char * argv[])2134 bool Cli::_KhompClearStatistics::execute(int argc, char *argv[])
2135 {
2136 if(argc < 2 || argc > 4)
2137 {
2138 printUsage(stream);
2139 return false;
2140 }
2141
2142 try
2143 {
2144
2145 unsigned int dev = UINT_MAX;
2146 unsigned int obj = UINT_MAX;
2147
2148 if(argc > 2)
2149 {
2150 dev = atoi(argv[2]);
2151
2152 if (!Globals::k3lapi.valid_device(dev))
2153 {
2154 K::Logger::Logg2(C_CLI, stream,
2155 FMT("ERROR: no such device %d!") % dev);
2156 return false;
2157 }
2158
2159 if(argc > 3)
2160 {
2161 obj = atoi(argv[3]);
2162
2163
2164 if(!Globals::k3lapi.valid_channel(dev, obj))
2165 {
2166 K::Logger::Logg2(C_CLI, stream,
2167 FMT("ERROR: No such channel %d on device %d!") % obj % dev);
2168 return false;
2169 }
2170 }
2171 }
2172
2173 if(dev == UINT_MAX)
2174 {
2175 K::Logger::Logg2(C_CLI, stream, "NOTICE: Reseting statistics of all channels...");
2176
2177 for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2178 {
2179 for (unsigned int o = 0; o < Globals::k3lapi.channel_count(d); o++)
2180 Board::get(d, o)->clearStatistics();
2181 }
2182 }
2183 else
2184 {
2185 if (obj == UINT_MAX)
2186 {
2187 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Reseting statistics of all channels from board %d...") % dev);
2188
2189 for (unsigned int o = 0; o < Globals::k3lapi.channel_count(dev); o++)
2190 Board::get(dev, o)->clearStatistics();
2191 }
2192 else
2193 {
2194 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Reseting statistics of channel %d from board %d") % obj % dev);
2195 Board::get(dev, obj)->clearStatistics();
2196 }
2197 }
2198
2199 }
2200 catch (K3LAPITraits::invalid_channel & err)
2201 {
2202 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
2203 return false;
2204 }
2205
2206 return true;
2207 }
2208
execute(int argc,char * argv[])2209 bool Cli::_KhompDumpConfig::execute(int argc, char *argv[])
2210 {
2211 if (argc != 2)
2212 {
2213 printUsage(stream);
2214 return false;
2215 }
2216
2217 const Config::StringSet opts = Globals::options.options();
2218
2219 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2220 K::Logger::Logg2(C_CLI, stream, "|--------------------------- Khomp Options Dump -------------------------|");
2221 K::Logger::Logg2(C_CLI, stream, "|------------------------------------------------------------------------|");
2222
2223 for (Config::StringSet::const_iterator itr = opts.begin(); itr != opts.end(); ++itr)
2224 { try
2225 {
2226 if(removeUnavaible((*itr))) continue;
2227 K::Logger::Logg2(C_CLI, stream, FMT("| %-24s => %42s |")
2228 % (*itr) % Globals::options.get(&(Opt::_options), (*itr)));
2229 }
2230 catch(Config::EmptyValue &e)
2231 {
2232 K::Logger::Logg(C_ERROR, FMT("%s (%s)") % e.what() % (*itr));
2233 }
2234 }
2235
2236 K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
2237
2238 return true;
2239 }
2240
resetLink(unsigned int device,unsigned int link)2241 void Cli::_KhompResetLinks::resetLink(unsigned int device, unsigned int link)
2242 {
2243 try
2244 {
2245 Globals::k3lapi.command(device, link, CM_RESET_LINK);
2246 }
2247 catch(K3LAPI::failed_command & e)
2248 {
2249 K::Logger::Logg2(C_CLI, stream,
2250 FMT("ERROR: Command has failed with error '%s'")
2251 % Verbose::status((KLibraryStatus)e.rc).c_str());
2252 }
2253 }
2254
execute(int argc,char * argv[])2255 bool Cli::_KhompResetLinks::execute(int argc, char *argv[])
2256 {
2257 if(argc < 2 || argc > 4)
2258 {
2259 printUsage(stream);
2260 return false;
2261 }
2262
2263 unsigned int dev = UINT_MAX;
2264 unsigned int obj = UINT_MAX;
2265
2266 if(argc > 2)
2267 {
2268 dev = atoi(argv[2]);
2269
2270 if (!Globals::k3lapi.valid_device(dev))
2271 {
2272 K::Logger::Logg2(C_CLI, stream,
2273 FMT("ERROR: no such device %d!") % dev);
2274 return false;
2275 }
2276
2277 if(argc > 3)
2278 {
2279 obj = atoi(argv[3]);
2280
2281 if(!Globals::k3lapi.valid_link(dev, obj))
2282 {
2283 K::Logger::Logg2(C_CLI, stream,
2284 FMT("ERROR: No such link %d on device %d!") % obj % dev);
2285 return false;
2286 }
2287 }
2288 }
2289
2290 if(dev == UINT_MAX)
2291 {
2292 K::Logger::Logg2(C_CLI, stream,
2293 "NOTICE: Reseting all links...");
2294
2295 for (unsigned int d = 0; d < Globals::k3lapi.device_count(); d++)
2296 {
2297 unsigned int link_count = Globals::k3lutil.physicalLinkCount(d, true);
2298
2299 for (unsigned int o = 0; o < link_count; o++)
2300 resetLink(d, o);
2301 }
2302 }
2303 else
2304 {
2305 if (obj == UINT_MAX)
2306 {
2307 K::Logger::Logg2(C_CLI, stream,
2308 FMT("NOTICE: Reseting all links on device %d...")
2309 % dev);
2310 unsigned int link_count = Globals::k3lutil.physicalLinkCount(dev, true);
2311
2312 for (unsigned int o = 0; o < link_count; o++)
2313 resetLink(dev, o);
2314 }
2315 else
2316 {
2317 K::Logger::Logg2(C_CLI, stream,
2318 FMT("NOTICE: Reseting link %d on device %d...")
2319 % obj % dev);
2320
2321 resetLink(dev, obj);
2322 }
2323 }
2324
2325 return true;
2326 }
2327
execute(int argc,char * argv[])2328 bool Cli::_KhompSMS::execute(int argc, char *argv[])
2329 {
2330 if(argc < 4)
2331 {
2332 printUsage(stream);
2333 return false;
2334 }
2335
2336 std::string devs(argv[1]);
2337 std::string numb(argv[2]);
2338 std::string mesg(argv[3]);
2339
2340 for (unsigned int i = 4; i < (unsigned int)argc; i++)
2341 {
2342 mesg += " ";
2343 mesg += argv[i];
2344 }
2345
2346 Board::KhompPvt * pvt = NULL;
2347
2348 bool enable_retry = false;
2349
2350 size_t pos = numb.find('r');
2351 if (pos != std::string::npos)
2352 {
2353 numb.erase(pos,1);
2354 enable_retry = true;
2355 }
2356
2357 std::string begin;
2358
2359 if(devs[0] != 'b' && devs[0] != 'B')
2360 {
2361 begin = "b";
2362 }
2363
2364 std::string complete = begin + devs + "/" + numb + "/" + mesg;
2365 int cause = (int)SWITCH_CAUSE_NONE;
2366
2367 try
2368 {
2369 for (unsigned int ntry = 0; ntry < 15; ++ntry)
2370 {
2371 ScopedAllocLock alloc_lock;
2372
2373 pvt = processSMSString(complete.c_str(), &cause);
2374
2375 /* NOTE: go directly to the pvt check below! */
2376 if (!enable_retry || pvt)
2377 break;
2378
2379 alloc_lock.unlock();
2380
2381 K::Logger::Logg2(C_CLI, stream, FMT("WARNING: '%s': No available channel, trying again...") % devs);
2382 usleep(2500000);
2383 }
2384
2385 if (!pvt)
2386 {
2387 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: '%s': No available channel %s") % devs % (enable_retry ? "after 15 retries, giving up!" : ""));
2388 return false;
2389 }
2390
2391 ScopedPvtLock lock(pvt);
2392
2393 if(!pvt->application(SMS_SEND, NULL, complete.c_str()))
2394 {
2395 K::Logger::Logg2(C_CLI, stream, "ERROR: Message could not be sent");
2396 return false;
2397 }
2398
2399 }
2400 catch(ScopedLockFailed & err)
2401 {
2402 if(err._fail == ScopedLockFailed::ALLOC_FAILED)
2403 {
2404 K::Logger::Logg2(C_CLI, stream, "ERROR: unable to global alloc lock");
2405 }
2406 else
2407 {
2408 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: unable to lock: %s!") % err._msg.c_str());
2409 }
2410 return false;
2411 }
2412
2413 K::Logger::Logg2(C_CLI, stream, "Message sent successfully!");
2414
2415 return true;
2416 }
2417
execute(int argc,char * argv[])2418 bool Cli::_KhompLogConsole::execute(int argc, char *argv[])
2419 {
2420 if (argc < 3)
2421 {
2422 printUsage(stream);
2423 return false;
2424 }
2425
2426 bool invert = false;
2427 bool unique = false;
2428
2429 std::string extra(argv[2]);
2430
2431 unsigned int total_args = argc - 2; /* remove "khomp log console" */
2432
2433 if (extra == "no")
2434 {
2435 invert = true;
2436 --total_args;
2437 }
2438 else if (extra == "just")
2439 {
2440 unique = true;
2441 --total_args;
2442 }
2443
2444 unsigned int first_args = argc - total_args;
2445
2446 std::string options;
2447
2448 for (unsigned int i = first_args; i < (unsigned int)argc; i++)
2449 {
2450 options += argv[i];
2451 options += ",";
2452 }
2453
2454 K::Logger::processLogConsole(stream, options, invert, unique);
2455 return true;
2456 }
2457
execute(int argc,char * argv[])2458 bool Cli::_KhompLogDisk::execute(int argc, char *argv[])
2459 {
2460 if (argc < 3)
2461 {
2462 printUsage(stream);
2463 return false;
2464 }
2465
2466 bool invert = false;
2467 bool unique = false;
2468
2469 std::string extra(argv[2]);
2470
2471 unsigned int total_args = argc - 2; /* remove "khomp log disk" */
2472
2473 if (extra == "no")
2474 {
2475 invert = true;
2476 --total_args;
2477 }
2478 else if (extra == "just")
2479 {
2480 unique = true;
2481 --total_args;
2482 }
2483
2484 unsigned int first_args = argc - total_args;
2485
2486 std::string options;
2487
2488 for (unsigned int i = first_args; i < (unsigned int)argc; i++)
2489 {
2490 options += argv[i];
2491 options += ",";
2492 }
2493
2494 K::Logger::processLogDisk(stream, options, invert, unique);
2495 return true;
2496 }
2497
execute(int argc,char * argv[])2498 bool Cli::_KhompLogStatus::execute(int argc, char *argv[])
2499 {
2500 if(argc != 2)
2501 {
2502 printUsage(stream);
2503 return false;
2504 }
2505
2506 Strings::Merger m1;
2507
2508 bool flag1_errors = K::Logger::Logg.classe(C_ERROR).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2509 bool flag1_warnings = K::Logger::Logg.classe(C_WARNING).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2510 bool flag1_messages = K::Logger::Logg.classe(C_MESSAGE).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2511 bool flag1_events = K::Logger::Logg.classe(C_EVENT).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2512 bool flag1_commands = K::Logger::Logg.classe(C_COMMAND).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2513 bool flag1_audio = K::Logger::Logg.classe(C_AUDIO_EV).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2514 bool flag1_modem = K::Logger::Logg.classe(C_MODEM_EV).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2515 bool flag1_links = K::Logger::Logg.classe(C_LINK_STT).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2516 bool flag1_cas = K::Logger::Logg.classe(C_CAS_MSGS).get(O_CONSOLE, K::LogManager::Option::ENABLED);
2517
2518 if (flag1_errors) m1.add("errors");
2519 if (flag1_warnings) m1.add("warnings");
2520 if (flag1_messages) m1.add("messages");
2521 if (flag1_events) m1.add("events");
2522 if (flag1_commands) m1.add("commands");
2523 if (flag1_audio) m1.add("audio");
2524 if (flag1_modem) m1.add("modem");
2525 if (flag1_links) m1.add("link");
2526 if (flag1_cas) m1.add("cas");
2527
2528 K::Logger::Logg2(C_CLI, stream, " ");
2529
2530 if (!m1.empty()) K::Logger::Logg2(C_CLI, stream, FMT("Enabled console messages: %s.") % m1.merge(", "));
2531 else /* ----- */ K::Logger::Logg2(C_CLI, stream, "There are no console messages enabled.");
2532
2533 bool flag2_errors = K::Logger::Logg.classe(C_ERROR).get(O_GENERIC, K::LogManager::Option::ENABLED);
2534 bool flag2_warnings = K::Logger::Logg.classe(C_WARNING).get(O_GENERIC, K::LogManager::Option::ENABLED);
2535 bool flag2_messages = K::Logger::Logg.classe(C_MESSAGE).get(O_GENERIC, K::LogManager::Option::ENABLED);
2536 bool flag2_events = K::Logger::Logg.classe(C_EVENT).get(O_GENERIC, K::LogManager::Option::ENABLED);
2537 bool flag2_commands = K::Logger::Logg.classe(C_COMMAND).get(O_GENERIC, K::LogManager::Option::ENABLED);
2538 bool flag2_audio = K::Logger::Logg.classe(C_AUDIO_EV).get(O_GENERIC, K::LogManager::Option::ENABLED);
2539 bool flag2_modem = K::Logger::Logg.classe(C_MODEM_EV).get(O_GENERIC, K::LogManager::Option::ENABLED);
2540 bool flag2_links = K::Logger::Logg.classe(C_LINK_STT).get(O_GENERIC, K::LogManager::Option::ENABLED);
2541 bool flag2_cas = K::Logger::Logg.classe(C_CAS_MSGS).get(O_GENERIC, K::LogManager::Option::ENABLED);
2542 bool flag2_functions = K::Logger::Logg.classe(C_DBG_FUNC).enabled();
2543 bool flag2_threads = K::Logger::Logg.classe(C_DBG_THRD).enabled();
2544 bool flag2_locks = K::Logger::Logg.classe(C_DBG_LOCK).enabled();
2545 bool flag2_streams = K::Logger::Logg.classe(C_DBG_STRM).enabled();
2546
2547 Strings::Merger m2;
2548
2549 if (flag2_errors) m2.add("errors");
2550 if (flag2_warnings) m2.add("warnings");
2551 if (flag2_messages) m2.add("messages");
2552 if (flag2_events) m2.add("events");
2553 if (flag2_commands) m2.add("commands");
2554 if (flag2_audio) m2.add("audio");
2555 if (flag2_modem) m2.add("modem");
2556 if (flag2_links) m2.add("link");
2557 if (flag2_cas) m2.add("cas");
2558 if (flag2_functions) m2.add("functions");
2559 if (flag2_threads) m2.add("threads");
2560 if (flag2_locks) m2.add("locks");
2561 if (flag2_streams) m2.add("streams");
2562
2563 if (!m2.empty()) K::Logger::Logg2(C_CLI, stream, FMT("Enabled log-on-disk messages: %s.") % m2.merge(", "));
2564 else /* ----- */ K::Logger::Logg2(C_CLI, stream, "There are no log-on-disk messages enabled.");
2565
2566 if (Globals::flag_trace_rdsi) K::Logger::Logg2(C_CLI, stream, "The ISDN (RDSI) low-level tracing is enabled.");
2567
2568 K::Logger::Logg2(C_CLI, stream, " ");
2569
2570 return true;
2571 }
2572
execute(int argc,char * argv[])2573 bool Cli::_KhompLogRotate::execute(int argc, char *argv[])
2574 {
2575 if (argc != 2)
2576 {
2577 printUsage(stream);
2578 return false;
2579 }
2580
2581 if (!K::Logger::rotate())
2582 {
2583 return false;
2584 }
2585
2586 return true;
2587 }
2588
execute(int argc,char * argv[])2589 bool Cli::_KhompLogTraceK3L::execute(int argc, char *argv[])
2590 {
2591 if (argc != 4)
2592 {
2593 printUsage(stream);
2594 return false;
2595 }
2596
2597 std::string str_on("on");
2598 std::string str_off("off");
2599
2600 bool value = false;
2601
2602 if (str_on == argv[3]) value = true;
2603 else if (str_off == argv[3]) value = false;
2604 else
2605 {
2606 K::Logger::Logg2(C_CLI, stream, "ERROR: Please use 'on' or 'off' to enable or disable.");
2607 return false;
2608 }
2609
2610 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: %sbling k3l debug messages.") % (value ? "Ena" : "Disa"));
2611
2612 Logfile logfile;
2613
2614 K::LogConfig::set(logfile, "K3L", "Value", value);
2615 K::LogConfig::set(logfile, "K3L", "CallProgress", value);
2616 K::LogConfig::set(logfile, "K3L", "CallAnalyzer", value);
2617 K::LogConfig::set(logfile, "K3L", "CadenceRecog", value);
2618 K::LogConfig::set(logfile, "K3L", "CallControl", value);
2619 K::LogConfig::set(logfile, "K3L", "Fax", value);
2620
2621 if (K::LogConfig::commit(logfile))
2622 {
2623 try
2624 {
2625 Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2626 }
2627 catch(...)
2628 {
2629 LOG(ERROR,"Error while send command CM_LOG_UPDATE");
2630 }
2631 }
2632
2633 return true;
2634 }
2635
execute(int argc,char * argv[])2636 bool Cli::_KhompLogTraceISDN::execute(int argc, char *argv[])
2637 {
2638 if (argc < 4)
2639 {
2640 printUsage(stream);
2641 return false;
2642 }
2643
2644 bool active = true;
2645
2646 bool change_lapd = false;
2647 bool change_q931 = false;
2648
2649 std::string what;
2650
2651 for (unsigned int i = 3; i < (unsigned int)argc; i++)
2652 {
2653 what += argv[i];
2654 what += ",";
2655 }
2656
2657 Strings::vector_type values;
2658 Strings::tokenize(what, values, ",");
2659
2660 for (Strings::vector_type::iterator i = values.begin(); i != values.end(); i++)
2661 {
2662 if ((*i) == "q931") change_q931 = true;
2663 if ((*i) == "lapd") change_lapd = true;
2664 if ((*i) == "off") active = false;
2665 }
2666
2667 Logfile logfile;
2668
2669 K::LogConfig::set(logfile, "ISDN", "Value", active);
2670
2671 if (change_lapd || !active)
2672 K::LogConfig::set(logfile, "ISDN", "Lapd", active);
2673
2674 if (change_q931 || !active)
2675 K::LogConfig::set(logfile, "ISDN", "Q931", active);
2676
2677 if (K::LogConfig::commit(logfile))
2678 {
2679 try
2680 {
2681 Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2682
2683 if (active)
2684 {
2685 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Activating the following ISDN debug option(s): %s") % what);
2686 Globals::flag_trace_rdsi = true;
2687 }
2688 else
2689 {
2690 K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating ISDN debug options");
2691 Globals::flag_trace_rdsi = false;
2692 }
2693 }
2694 catch(...)
2695 {
2696 if (active)
2697 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to activate the following ISDN debug option(s): %s") % what);
2698 else
2699 K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to deactivate ISDN debug options");
2700 }
2701
2702 return false;
2703 }
2704
2705 return true;
2706 }
2707
execute(int argc,char * argv[])2708 bool Cli::_KhompLogTraceR2::execute(int argc, char *argv[])
2709 {
2710 if (argc != 4)
2711 {
2712 printUsage(stream);
2713 return false;
2714 }
2715
2716 try
2717 {
2718 std::string str_off("off");
2719 std::string str_on("on" );
2720
2721 bool enable = false;
2722
2723 if (str_on == argv[3]) enable = true;
2724 else if (str_off == argv[3]) enable = false;
2725
2726 if (enable)
2727 {
2728 K::Logger::Logg2(C_CLI, stream, "NOTICE: All channels of all devices will be monitored!" );
2729 }
2730 else
2731 {
2732 K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating R2 debug options" );
2733 }
2734
2735 Logfile logfile;
2736
2737 K::LogConfig::set(logfile, "R2", "Value", enable);
2738 K::LogConfig::set(logfile, "R2", "Signaling", enable);
2739 K::LogConfig::set(logfile, "R2", "States", enable);
2740
2741 if (K::LogConfig::commit(logfile))
2742 {
2743 try
2744 {
2745 Globals::k3lapi.command(-1, -1, CM_LOG_UPDATE);
2746 }
2747 catch(...)
2748 {
2749 LOG(ERROR,"Error while send command CM_LOG_UPDATE");
2750 }
2751 }
2752 }
2753 catch (Strings::invalid_value e)
2754 {
2755 K::Logger::Logg2(C_CLI, stream, "ERROR: Invalid numeric value in arguments.");
2756 return false;
2757 }
2758
2759 return true;
2760 }
2761
execute(int argc,char * argv[])2762 bool Cli::_KhompGet::execute(int argc, char *argv[])
2763 {
2764 if (argc < 2)
2765 {
2766 printUsage(stream);
2767 return false;
2768 }
2769
2770 std::string arg(argv[1]);
2771
2772 try
2773 {
2774 std::string res = Globals::options.get(&Opt::_options, (const char*) argv[1]);
2775 K::Logger::Logg2(C_CLI, stream, FMT("Result for command %s is %s.") % std::string(argv[1]) % res);
2776 }catch(Config::Failure &e){
2777 K::Logger::Logg2(C_CLI, stream, e.what());
2778 }
2779
2780 return true;
2781 }
2782
execute(int argc,char * argv[])2783 bool Cli::_KhompSet::execute(int argc, char *argv[])
2784 {
2785 if (argc < 3)
2786 {
2787 printUsage(stream);
2788 return false;
2789 }
2790
2791 std::string args;
2792
2793 const unsigned int first = 2;
2794
2795 for (unsigned int i = first; i < (unsigned int)argc; i++)
2796 {
2797 if (i != first) { args += " "; }
2798
2799 args += argv[i];
2800 }
2801
2802 try
2803 {
2804 Globals::options.process(&Opt::_options, (const char *) argv[1], (const char *) args.c_str());
2805 const Config::Options::Messages msgs = Globals::options.commit(&Opt::_options, (const char *)argv[1]);
2806
2807 for (Config::Options::Messages::const_iterator i = msgs.begin(); i != msgs.end(); ++i)
2808 {
2809 K::Logger::Logg2(C_ERROR, stream, FMT("%s.") % (*i));
2810 }
2811
2812 K::Logger::Logg2(C_CLI, stream, FMT("Setting %s for value %s") % argv[1] % argv[2]);
2813 }
2814 catch (Config::Failure &e)
2815 {
2816 K::Logger::Logg2(C_ERROR,stream, FMT("config processing error: %s.") % e.what());
2817 }
2818
2819 return true;
2820 }
2821
execute(int argc,char * argv[])2822 bool Cli::_KhompRevision::execute(int argc, char *argv[])
2823 {
2824 #ifndef MOD_KHOMP_VERSION
2825 #define MOD_KHOMP_VERSION "unknown"
2826 #endif
2827
2828 #ifndef SWITCH_VERSION_FULL
2829 #define SWITCH_VERSION_FULL "unknown"
2830 #endif
2831
2832 std::string khomp_endpoint_rev(MOD_KHOMP_VERSION);
2833 std::string freeswitch_rev(SWITCH_VERSION_FULL);
2834
2835 K::Logger::Logg2(C_CLI, stream, FMT("Khomp Endpoint - %s") % khomp_endpoint_rev);
2836 K::Logger::Logg2(C_CLI, stream, FMT("FreeSWITCH - %s") % freeswitch_rev);
2837 return true;
2838 }
2839
execute(int argc,char * argv[])2840 bool Cli::_KhompSendCommand::execute(int argc, char *argv[])
2841 {
2842 if (argc < 5 || argc > 6)
2843 {
2844 printUsage(stream);
2845 return false;
2846 }
2847
2848 unsigned int dev = atoi (argv[2]);
2849
2850 if (dev >= Globals::k3lapi.device_count())
2851 {
2852 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
2853 return false;
2854 }
2855
2856 unsigned int num = atoi (argv[4]);
2857
2858 if (num >= 256)
2859 {
2860 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid command number: %d!") % num);
2861 return false;
2862 }
2863
2864 unsigned int obj = atoi (argv[3]);
2865
2866 try
2867 {
2868 switch (argc)
2869 {
2870 case 5: Globals::k3lapi.command(dev,obj, num); break;
2871 case 6: Globals::k3lapi.command(dev,obj, num,argv[5]); break;
2872 default: /* what-a-hell ?! */ break;
2873 }
2874 }
2875 catch(K3LAPI::failed_command &e)
2876 {
2877 if (K::Logger::Logg.classe(C_WARNING).enabled())
2878 {
2879 LOG(WARNING, FMT("Command '%s' has failed with error '%s'.")
2880 % Verbose::commandName(e.code) % Verbose::status((KLibraryStatus)e.rc));
2881 }
2882
2883 return false;
2884 }
2885
2886 return true;
2887 }
2888
execute(int argc,char * argv[])2889 bool Cli::_KhompSendRawCommand::execute(int argc, char *argv[])
2890 {
2891 if (argc < 6)
2892 {
2893 printUsage(stream);
2894 return false;
2895 }
2896
2897 unsigned int dev = atoi (argv[3]);
2898
2899 if (dev >= Globals::k3lapi.device_count())
2900 {
2901 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: No such device: %d!") % dev);
2902 return false;
2903 }
2904
2905 unsigned int dsp = atoi (argv[4]);
2906
2907 if (dsp >= 2)
2908 {
2909 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid DSP number: %d!") % dsp);
2910 return false;
2911 }
2912
2913 const unsigned int base = 5;
2914 char commands[(argc - base)];
2915
2916 for (int i = base, j = 0; i < argc; i++, j++)
2917 {
2918 if (sscanf(argv[i], "%hhx", &(commands[j])) != 1)
2919 {
2920 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid hexadecimal sequence: '%s'!") % argv[i]);
2921 return false;
2922 }
2923 }
2924
2925 try
2926 {
2927 Globals::k3lapi.raw_command(dev, dsp, commands, (argc - base));
2928 }
2929 catch(K3LAPI::failed_raw_command &e)
2930 {
2931 if (K::Logger::Logg.classe(C_WARNING).enabled())
2932 {
2933 LOG(WARNING, FMT("(dev=%d,dsp=%d): Raw command '%s' has failed with error '%s'.")
2934 % e.dev
2935 % e.dsp
2936 % Strings::hexadecimal(std::string((char*) commands,(argc - base)))
2937 % Verbose::status((KLibraryStatus)e.rc));
2938 }
2939
2940 return false;
2941 }
2942
2943 return true;
2944 }
2945
execute(int argc,char * argv[])2946 bool Cli::_KhompSelectSim::execute(int argc, char *argv[])
2947 {
2948 if(argc != 5)
2949 {
2950 printUsage(stream);
2951 return false;
2952 }
2953
2954 std::string dev_str(argv[2]);
2955 std::string obj_str(argv[3]);
2956 std::string num_str(argv[4]);
2957
2958 try
2959 {
2960 unsigned int dev = Strings::tolong(dev_str);
2961 unsigned int obj = Strings::tolong(obj_str);
2962
2963 if (!Globals::k3lapi.valid_device(dev))
2964 {
2965 K::Logger::Logg2(C_CLI, stream,
2966 FMT("ERROR: no such device %d!") % dev);
2967 return false;
2968 }
2969
2970 if (!Globals::k3lapi.valid_channel(dev, obj))
2971 {
2972 K::Logger::Logg2(C_CLI, stream,
2973 FMT("ERROR: No such channel %d on device %d!") % obj % dev);
2974 return false;
2975 }
2976
2977 /* just check for validity */
2978 (void)Strings::tolong(num_str);
2979
2980
2981 if(!Board::get(dev, obj)->application(SELECT_SIM_CARD, NULL, num_str.c_str()))
2982 {
2983 K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card");
2984 return false;
2985 }
2986 }
2987 catch (Strings::invalid_value & e)
2988 {
2989 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Invalid number '%s'!") % e.value());
2990 return false;
2991 }
2992 catch (K3LAPITraits::invalid_channel & err)
2993 {
2994 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: Unable to find channel %d on device %d!") % err.object % err.device );
2995 return false;
2996 }
2997 catch(...)
2998 {
2999 K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card");
3000 return false;
3001 }
3002
3003 return true;
3004 }
3005
execute(int argc,char * argv[])3006 bool Cli::_KhompKommuterOnOff::execute(int argc, char *argv[])
3007 {
3008 if(argc != 2)
3009 {
3010 printUsage(stream);
3011 return false;
3012 }
3013
3014 switch (Board::kommuter._kommuter_count)
3015 {
3016 case -1: K::Logger::Logg2(C_CLI, stream, "ERROR: libkwd.so required for kommuter could not be found." ); return false;
3017 case 0: K::Logger::Logg2(C_CLI, stream, "ERROR: none Kommuter was found on the system." ); return false;
3018 }
3019
3020 if (Opt::_options._kommuter_activation() == "auto")
3021 {
3022 K::Logger::Logg2(C_CLI, stream, "ERROR: Kommuter is set to be started automatically by kommuter-activation configuration.");
3023 return false;
3024 }
3025
3026 bool on_off = ARG_CMP(1, "on") ? true : false;
3027
3028 int ret = 0;
3029 if (on_off)
3030 {
3031 int timeout = Opt::_options._kommuter_timeout();
3032 K::Logger::Logg2(C_CLI, stream, FMT("NOTICE: Activating Kommuters with timeout of %d seconds .") % timeout);
3033 bool start_timer = false;
3034
3035 std::string param= STG(FMT("timeout=%d") % timeout);
3036
3037 for (int kommuter = 0; kommuter < Board::kommuter._kommuter_count; kommuter++)
3038 {
3039 try
3040 {
3041 Globals::k3lapi.command(-1, kommuter, CM_START_WATCHDOG, (char*) param.c_str());
3042 start_timer = true;
3043 }
3044 catch(K3LAPI::failed_command & e)
3045 {
3046 switch(e.rc)
3047 {
3048 case ksInvalidParams:
3049 K::Logger::Logg2(C_CLI,stream,FMT("ERROR: invalid timeout '%d' for Kommuter device '%d' timeout. Mininum is 0, maximum is 255.")
3050 % timeout % kommuter);
3051 break;
3052 default:
3053 K::Logger::Logg2(C_CLI,stream,FMT("ERROR: could not start the kommuter device number '%d'.") % kommuter);
3054 break;
3055 }
3056 }
3057 catch(...)
3058 {
3059 K::Logger::Logg2(C_CLI, stream, FMT("ERROR: could not start the Kommuter device number '%d'.") % kommuter);
3060 }
3061 }
3062
3063 if (timeout == 0)
3064 {
3065 DBG(FUNC, D("kommuter watchdog timer not created because timeout is 0."));
3066 return false;
3067 }
3068
3069 if (start_timer)
3070 {
3071 if (!Globals::global_timer)
3072 {
3073 K::Logger::Logg2(C_CLI, stream , "Error creating the timer for kommuter.");
3074 return true;
3075 }
3076 else if (Board::kommuter._kwtd_timer_on)
3077 {
3078 Globals::global_timer->restart( Board::kommuter._kwtd_timer_index, true );
3079 DBG(FUNC, D("kommuter watchdog timer restarted."));
3080 }
3081 else
3082 {
3083 Board::kommuter._kwtd_timer_index = Globals::global_timer->add(((timeout < 5) ? (timeout*500) : 2000), &Kommuter::wtdKickTimer);
3084 Board::kommuter._kwtd_timer_on = true;
3085 DBG(FUNC, D("kommuter watchdog timer created and started."));
3086 }
3087 }
3088 }
3089 else
3090 {
3091 K::Logger::Logg2(C_CLI, stream, "NOTICE: Deactivating Kommuters.");
3092
3093 if (Board::kommuter._kwtd_timer_on)
3094 {
3095 Globals::global_timer->del( Board::kommuter._kwtd_timer_index);
3096 Board::kommuter._kwtd_timer_on = false;
3097 }
3098
3099 for(int kommuter = 0; kommuter < Board::kommuter._kommuter_count; kommuter++)
3100 {
3101 try
3102 {
3103 Globals::k3lapi.command(-1, kommuter, CM_STOP_WATCHDOG);
3104 return true;
3105 }
3106 catch(K3LAPI::failed_command & e)
3107 {
3108 K::Logger::Logg2(C_CLI,stream,FMT("ERROR: Kommuter device '%d' was not initialized.") % kommuter);
3109 }
3110 catch(...)
3111 {
3112 K::Logger::Logg2(C_CLI, stream,FMT("ERROR: could not disable kommuter device '%d' for some unknow reason.") % kommuter);
3113 }
3114 }
3115 }
3116
3117 return false;
3118 }
3119
execute(int argc,char * argv[])3120 bool Cli::_KhompKommuterCount::execute(int argc, char *argv[])
3121 {
3122 if(argc != 2)
3123 {
3124 printUsage(stream);
3125 return false;
3126 }
3127
3128 if(Board::kommuter._kommuter_count == -1)
3129 {
3130 K::Logger::Logg2(C_CLI, stream,
3131 "ERROR: libkwd.so required for kommuter could not be found." );
3132 return false;
3133 }
3134
3135 K::Logger::Logg2(C_CLI, stream,
3136 FMT("Kommuter devices detected = [%d]")
3137 % Board::kommuter._kommuter_count);
3138
3139 return true;
3140 }
3141
3142