455{
  456  bool dump = false;
  457  uint32_t type = 
unkn;
 
  458  bool uses_roy = false;
  459  bool use_gui = false;
  460  bool lm_mode = false;
  461 
  462  std::string dom_names = std::getenv("HOME") + std::string("/.doms.csk");
  463  dom_map_type dom_names_map;
  464 
  465  std::ofstream output_file;
  466 
  467  unsigned int port = 0;
  468 
  469  std::string filename;
  470  std::string roy_setup;
  471 
  472  std::string lserver = "localhost:5553";
  473  std::string tag;
  474  boost::asio::ip::tcp::endpoint endpoint;
  475 
  476  po::options_description desc("Generic options");
  477  desc.add_options()
  478    ("help,h",    "Print this help and exit.")
  479    ("version,v", "Print the version and exit.")
  480    (
  481     "map"
  482     , po::value<std::string>(&dom_names)->value_name("filename")
  483     , "File that specifies a conversion from DOM IDs to a human readable name."
  484     )
  485#ifdef CURSES_FOUND
  486    ("gui,g", "Use GUI (avalilable in UDP-monitoring and Ligier modes only).")
  487#endif
  488    ("ligier,l", "Set Ligier mode.")
  489    ("udp,u", "Force UDP mode (default).");
  490 
  491  po::options_description lmdesc("Ligier-mode options");
  492  lmdesc.add_options()
  493    (
  494     "server,s"
  495     , po::value<std::string>(&lserver)
  496     ->default_value("localhost:5553")
  497     ->value_name("server:[port]")
  498     , "Set the Ligier server endpoint to read data from."
  499     )
  500    (
  501     "tag,t"
  502     , po::value<std::string>(&tag)
  503     ->default_value("IO_MONIT")
  504     ->value_name("tag")
  505     , "Set the Ligier tag to read data from."
  506     );
  507 
  508  po::options_description umdesc("UDP-mode options");
  509  umdesc.add_options()
  510    ("optical,o",
  511     po::value<unsigned int>(&port)
  513     ->value_name("port"),
  514     "Set the expected data type to optical. If a port is not \
  515provided the default one is used (56015).")
  516    ("acoustic,a",
  517     po::value<unsigned int>(&port)
  519     ->value_name("port"),
  520     "Set the expected data type to acoustic. If a port is not \
  521provided the default one is used (56016).")
  522    ("monitoring,m",
  523     po::value<unsigned int>(&port)
  525     ->value_name("port"),
  526     "Set the expected data type to monitoring. If a port is \
  527not provided the default one is used (56017).")
  528    ("port,p",
  529     po::value<unsigned int>(&port)->value_name("port"),
  530     "Listen on the specified port, automatically determining the \
  531data type.")
  532    ("dumpfile,f",
  533     po::value<std::string>(&filename)->value_name("filename"),
  534     "Dumps the acquired data to a file.")
  535    ("royweb,r",
  536     po::value<std::string>(&roy_setup)
  537     ->implicit_value("HR_%n.%c:localhost:9999")
  538     ->value_name("format:host:port"),
  539     "Send the monitoring hit rates to the specified ROyWeb \
  540server. The syntax is format:server_ip:server_port. \
  541The format parameter can contain the following placeholders: %d for \
  542DOM ID, %n for DOM name (if available, otherwise the DOM ID is used) \
  543and %c for channel ID.");
  544 
  545  std::string templ;
  546  std::string roy_server;
  547  int roy_port = 0;
  548 
  549  try {
  550    po::options_description global;
  551    global.add(desc).add(lmdesc).add(umdesc);
  552 
  553    po::variables_map vm;
  554    po::store(
  555              po::command_line_parser(argc, argv).options(global).run()
  556              , vm
  557              );
  558 
  559    if (vm.count("help")) {
  560      std::cout
  561        << desc   << '\n'
  562        << umdesc << '\n'
  563        << lmdesc << '\n';
  564      return EXIT_SUCCESS;
  565    }
  566 
  567    if (vm.count("version")) {
  568      std::cout << clbsk::version::v() << std::endl;
  569      return EXIT_SUCCESS;
  570    }
  571 
  572    po::notify(vm);
  573 
  574#ifdef CURSES_FOUND
  575    use_gui = vm.count("gui");
  576#endif
  577 
  578    lm_mode = vm.count("ligier");
  579 
  580    if (lm_mode && vm.count("udp")) {
  581      throw std::runtime_error("You can specify only one mode. Both provided.");
  582    }
  583 
  584    if (vm.count("map")) {
  585      std::ifstream 
map(dom_names.c_str());
 
  586 
  588        throw std::runtime_error(
  589                                 std::string("Error reading map file: ")
  590                                 + std::strerror(errno)
  591                                 );
  592      }
  593 
  595    } else {
  596      std::ifstream 
map(dom_names.c_str());
 
  597 
  599    }
  600 
  601    if (lm_mode) {
  602      po::variables_map vm;
  603      po::options_description options;
  604      options.add(lmdesc).add(desc);
  605 
  606      po::store(
  607                po::command_line_parser(argc, argv).options(options).run()
  608                , vm
  609                );
  610 
  611      po::notify(vm);
  612 
  614 
  616    } else {
  617      po::variables_map vm;
  618      po::options_description options;
  619      options.add(desc).add(umdesc);
  620 
  621      po::store(
  622                po::command_line_parser(argc, argv).options(options).run()
  623                , vm
  624                );
  625 
  626      po::notify(vm);
  627 
  628      unsigned int counter = 0;
  629      if (vm.count("port")) {
  631        ++counter;
  632      }
  633      if (vm.count("optical")) {
  635        ++counter;
  636      }
  637      if (vm.count("acoustic")) {
  639        ++counter;
  640      }
  641      if (vm.count("monitoring")) {
  643        ++counter;
  644      }
  645 
  646      if (counter != 1) {
  647        if (counter) {
  648          throw std::runtime_error("More than one port provided.");
  649        } else {
  650          throw std::runtime_error("You must specify at least one port.");
  651        }
  652      }
  653 
  654      if (use_gui && type != 
tmch) {
 
  655        throw std::runtime_error("GUI is only available in monitoring mode");
  656      }
  657 
  658      if (vm.count("royweb")) {
  660          throw std::runtime_error("you can use ROyWeb only with the"
  661                                   " monitoring channel");
  662        }
  663 
  664        uses_roy = true;
  665        std::replace(roy_setup.begin(), roy_setup.end(), ':', ' ');
  666        std::istringstream ss(roy_setup);
  667        int param_count = 0;
  668        if (ss >> templ) {
  669          ++param_count;
  670        }
  671        if (ss >> roy_server) {
  672          ++param_count;
  673        }
  674        if (ss >> roy_port) {
  675          ++param_count;
  676        }
  677 
  678        if (param_count != 3) {
  679          throw std::runtime_error("you must specify all the parameters"
  680                                   " or accept all the default one to use with ROyWeb.");
  681        }
  682      }
  683 
  684      if (vm.count("dumpfile")) {
  685        output_file.open(filename.c_str(), std::ios::binary);
  686        if (! output_file) {
  687          throw std::runtime_error(
  688                                   "Unable to open file "
  689                                   + filename
  690                                   + " for writing: "
  691                                   + strerror(errno)
  692                                   );
  693        }
  694        dump = true;
  695      }
  696    }
  697  } catch (const po::error& e) {
  698    std::cerr
  699      << "CLBSwissKnife: Error: " << e.what() << '\n'
  700      << desc   << '\n'
  701      << umdesc << '\n'
  702      << lmdesc << '\n';
  703 
  704    return EXIT_FAILURE;
  705  } catch (const std::runtime_error& e) {
  706    std::cerr << "CLBSwissKnife: Error: " << e.what() << std::endl;
  707    return EXIT_FAILURE;
  708  }
  709 
  710  boost::asio::io_service io_service;
  712 
  713  
  715 
  716  if (lm_mode) { 
  717    if (use_gui) { 
  718#ifdef CURSES_FOUND
  719      ChList stats;
  720 
  721      boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
  722 
  723      boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
  724 
  725      boost::asio::signal_set window_resize(io_service, SIGWINCH);
  726 
  728      gui::ScreenInitialiser init;
  729 
  730      gui::Screen screen(io_service, lserver, stats);
  731 
  732      keyb.async_read_some(
  733                           boost::asio::buffer(&key, sizeof(key)),
  734                           boost::bind(
  736                                       boost::ref(keyb),
  737                                       boost::ref(key),
  738                                       boost::ref(screen),
  739                                       boost::asio::placeholders::error,
  740                                       boost::asio::placeholders::bytes_transferred
  741                                       )
  742                           );
  743 
  744      timer.async_wait(
  745                       boost::bind(
  747                                   boost::ref(timer),
  748                                   boost::ref(screen),
  749                                   boost::asio::placeholders::error
  750                                   )
  751                       );
  752 
  754                                                 io_service
  755                                                 , tag
  756                                                 , endpoint
  757                                                 , buffer
  759                                                 , clbsk::consumer::Gui(
terminal_width, dom_names_map, stats, screen)
 
  760                                                 );
  761 
  762      window_resize.async_wait(
  763                               boost::bind(
  765                                           boost::ref(window_resize),
  766                                           boost::ref(screen),
  767                                           boost::asio::placeholders::error,
  768                                           boost::asio::placeholders::signal_number
  769                                           )
  770                               );
  771 
  772      io_service.run();
  773#endif
  774    } else { 
  775      std::cout << "Listening from: " << endpoint << ':' << tag << '\n';
  776      boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
  777 
  778      signals_handler.async_wait(
  779                                 boost::bind(
  781                                             boost::ref(signals_handler),
  783                                             boost::asio::placeholders::error,
  784                                             boost::asio::placeholders::signal_number
  785                                             )
  786                                 );
  787 
  789                                                        io_service
  790                                                        , tag
  791                                                        , endpoint
  792                                                        , buffer
  795                                                        );
  796 
  797      io_service.run();
  798    }
  799  } else { 
  800    std::cout << "Listening port: " << port << '\n' << "Data type: ";
  801 
  803      std::cout << "Acoustic\n";
  804    } 
else if (type == 
ttdc) {
 
  805      std::cout << "Optical\n";
  806    } 
else if (type == 
tmch) {
 
  807      std::cout << "Monitoring\n";
  808    } else {
  809      std::cout << "Automatically determined\n";
  810    }
  811 
  812    clbsk::consumer::ConsumerSet consumer_set;
  813 
  814    trm::MonStreamer ms(roy_server, roy_port);
  815 
  816    if (uses_roy) {
  817      std::cout
  818        << "Using ROyWeb ("
  819        << roy_server
  820        << ", "
  821        << roy_port
  822        << ") with tag format "
  823        << templ << std::endl;
  824 
  825      consumer_set.add(
  826                       clbsk::consumer::Roy(
  827                                            dom_names_map
  828                                            , templ
  829                                            , ms
  830                                            )
  831                       );
  832    }
  833 
  834    if (dump) {
  835      consumer_set.add(clbsk::consumer::File(output_file));
  836    }
  837 
  838    if (use_gui) { 
  839#ifdef CURSES_FOUND
  840      ChList stats;
  841 
  842      boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
  843 
  844      boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
  845 
  846      boost::asio::signal_set window_resize(io_service, SIGWINCH);
  847 
  849      gui::ScreenInitialiser init;
  850 
  851      std::string const heading
  852        = "UDP " + boost::lexical_cast<std::string>(port);
  853 
  854      gui::Screen screen(io_service, heading, stats);
  855 
  856      keyb.async_read_some(
  857                           boost::asio::buffer(&key, sizeof(key)),
  858                           boost::bind(
  860                                       boost::ref(keyb),
  861                                       boost::ref(key),
  862                                       boost::ref(screen),
  863                                       boost::asio::placeholders::error,
  864                                       boost::asio::placeholders::bytes_transferred
  865                                       )
  866                           );
  867 
  868      timer.async_wait(
  869                       boost::bind(
  871                                   boost::ref(timer),
  872                                   boost::ref(screen),
  873                                   boost::asio::placeholders::error
  874                                   )
  875                       );
  876 
  877      window_resize.async_wait(
  878                               boost::bind(
  880                                           boost::ref(window_resize),
  881                                           boost::ref(screen),
  882                                           boost::asio::placeholders::error,
  883                                           boost::asio::placeholders::signal_number
  884                                           )
  885                               );
  886 
  887      consumer_set.add(
  888                       clbsk::consumer::Gui(
  890                                            , dom_names_map
  891                                            , stats
  892                                            , screen
  893                                            )
  894                       );
  895 
  897                                                      io_service
  898                                                      , port
  899                                                      , buffer
  901                                                      , consumer_set
  902                                                      );
  903 
  904      io_service.run();
  905#endif
  906    } else { 
  907      consumer_set.add(
  908                       clbsk::consumer::Scrollback(
  910                                                   , type
  911                                                   , dom_names_map
  912                                                   )
  913                       );
  914 
  915      boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
  916 
  917      signals_handler.async_wait(
  918                                 boost::bind(
  920                                             , boost::ref(signals_handler)
  922                                             , boost::asio::placeholders::error
  923                                             , boost::asio::placeholders::signal_number
  924                                             )
  925                                 );
  926 
  928                                                      io_service
  929                                                      , port
  930                                                      , buffer
  932                                                      , consumer_set
  933                                                      );
  934 
  935      io_service.run();
  936    }
  937  }
  938}
static const unsigned int default_moni_port
 
static const unsigned int default_acou_port
 
static const size_t buffer_size
 
static const unsigned int default_opto_port
 
boost::asio::ip::tcp::endpoint make_endpoint(std::string const &address)
 
static const unsigned int taes
 
static const unsigned int ttdc
 
static const unsigned int tmch
 
dom_map_type load_dom_map(std::istream &map)
 
void async_commit(boost::asio::deadline_timer &timer, gui::Screen &screen, boost::system::error_code const &error)
 
void async_win_resize(boost::asio::signal_set &window_resize, gui::Screen &screen, boost::system::error_code const &error, int signum)
 
void async_cin(boost::asio::posix::stream_descriptor &keyb, char &key, gui::Screen &screen, const boost::system::error_code &error, std::size_t bytes_transferred)
 
struct __attribute__((__packed__)) InfoWord