135 #include <boost/asio.hpp> 
  136 #include <boost/program_options.hpp> 
  138 #include <sys/ioctl.h> 
  144 #if BOOST_VERSION >= 107000 
  145 #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) 
  147 #define GET_IO_SERVICE(s) ((s).get_io_service()) 
  150 #include "structs.hpp" 
  151 #include "datatypes.hpp" 
  152 #include "version.hpp" 
  153 #include "ligier_helper.hpp" 
  154 #include "consumers.hpp" 
  155 #include "dom_map.hpp" 
  159   static bool const is_a_tty = isatty(1);
 
  166     ioctl(1, TIOCGWINSZ, &sz);
 
  171 namespace po = boost::program_options;
 
  182     boost::asio::signal_set& set,
 
  184     boost::system::error_code 
const& error,
 
  188 template<
class Consumer>
 
  205       boost::system::error_code 
const& error
 
  209     if (error && error != boost::asio::error::operation_aborted) {
 
  212     } 
else if (error == boost::asio::error::operation_aborted) {
 
  216       boost::asio::async_read(
 
  222             , boost::asio::placeholders::error
 
  223             , boost::asio::placeholders::bytes_transferred
 
  237             , boost::asio::placeholders::error
 
  245     if (error && error != boost::asio::error::operation_aborted) {
 
  247       m_timer.expires_from_now(boost::posix_time::seconds(1));
 
  253             , boost::asio::placeholders::error
 
  256     } 
else if (error == boost::asio::error::operation_aborted) {
 
  260       boost::asio::async_write(
 
  262         , boost::asio::buffer(
m_buffer, size)
 
  266             , boost::asio::placeholders::error
 
  267             , boost::asio::placeholders::bytes_transferred
 
  274       boost::system::error_code 
const& error
 
  275     , std::size_t bytes_transferred
 
  277     if (error && error != boost::asio::error::operation_aborted) {
 
  280     } 
else if (error == boost::asio::error::operation_aborted) {
 
  282       boost::asio::async_read(
 
  288             , boost::asio::placeholders::error
 
  289             , boost::asio::placeholders::bytes_transferred
 
  296       boost::system::error_code 
const& error
 
  297     , std::size_t bytes_transferred
 
  299     if (error && error != boost::asio::error::operation_aborted) {
 
  302     } 
else if (error == boost::asio::error::operation_aborted) {
 
  306       boost::asio::async_read(
 
  308         , boost::asio::buffer(
m_buffer + 16, size)
 
  312             , boost::asio::placeholders::error
 
  313             , boost::asio::placeholders::bytes_transferred
 
  321     boost::system::error_code ec;
 
  323     m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
 
  331           , boost::asio::placeholders::error
 
  342       boost::asio::io_service& service
 
  343     , std::string 
const& tag
 
  344     , boost::asio::ip::tcp::endpoint 
const& endpoint
 
  347     , Consumer 
const& consumer
 
  361           , boost::asio::placeholders::error
 
  367 template<
class Consumer>
 
  378       boost::system::error_code 
const& error
 
  379     , std::size_t bytes_transferred
 
  392           , boost::asio::placeholders::error
 
  393           , boost::asio::placeholders::bytes_transferred
 
  401       boost::asio::io_service& service
 
  405     , Consumer 
const& consumer
 
  408         , boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)
 
  415     boost::asio::ip::udp::socket::receive_buffer_size option(3554432);
 
  417     boost::asio::ip::udp::socket::receive_buffer_size option(33554432);
 
  426           , boost::asio::placeholders::error
 
  427           , boost::asio::placeholders::bytes_transferred
 
  435     std::string 
const& address
 
  437   boost::asio::io_service service;
 
  438   boost::asio::ip::tcp::resolver resolver(service);
 
  440   std::string::size_type 
const pos = address.find(
":");
 
  442   std::string 
const host = pos == std::string::npos ? address : address.substr(0, pos);
 
  443   std::string 
const port = pos == std::string::npos ? 
"5553"  : address.substr(pos + 1);
 
  445   boost::asio::ip::tcp::resolver::query query(
 
  446       boost::asio::ip::tcp::v4()
 
  451   return *resolver.resolve(query);
 
  454 int main(
int argc, 
char* argv[])
 
  457   uint32_t type = 
unkn;
 
  458   bool uses_roy = 
false;
 
  459   bool use_gui = 
false;
 
  460   bool lm_mode = 
false;
 
  462   std::string dom_names = std::getenv(
"HOME") + std::string(
"/.doms.csk");
 
  463   dom_map_type dom_names_map;
 
  465   std::ofstream output_file;
 
  467   unsigned int port = 0;
 
  469   std::string filename;
 
  470   std::string roy_setup;
 
  472   std::string lserver = 
"localhost:5553";
 
  474   boost::asio::ip::tcp::endpoint endpoint;
 
  476   po::options_description desc(
"Generic options");
 
  478     (
"help,h",    
"Print this help and exit.")
 
  479     (
"version,v", 
"Print the version and exit.")
 
  482       , po::value<std::string>(&dom_names)->value_name(
"filename")
 
  483       , 
"File that specifies a conversion from DOM IDs to a human readable name." 
  486     (
"gui,g", 
"Use GUI (avalilable in UDP-monitoring and Ligier modes only).")
 
  488     (
"ligier,l", 
"Set Ligier mode.")
 
  489     (
"udp,u", 
"Force UDP mode (default).");
 
  491   po::options_description lmdesc(
"Ligier-mode options");
 
  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." 
  502       , po::value<std::string>(&tag)
 
  503           ->default_value(
"IO_MONIT")
 
  505       , 
"Set the Ligier tag to read data from." 
  508   po::options_description umdesc(
"UDP-mode options");
 
  511           po::value<unsigned int>(&port)
 
  513               ->value_name(
"port"),
 
  514           "Set the expected data type to optical. If a port is not \ 
  515 provided the default one is used (56015).")
 
  517           po::value<unsigned int>(&port)
 
  519               ->value_name(
"port"),
 
  520           "Set the expected data type to acoustic. If a port is not \ 
  521 provided the default one is used (56016).")
 
  523           po::value<unsigned int>(&port)
 
  525               ->value_name(
"port"),
 
  526           "Set the expected data type to monitoring. If a port is \ 
  527 not provided the default one is used (56017).")
 
  529           po::value<unsigned int>(&port)->value_name(
"port"),
 
  530           "Listen on the specified port, automatically determining the \ 
  533           po::value<std::string>(&filename)->value_name(
"filename"),
 
  534           "Dumps the acquired data to a file.")
 
  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 \ 
  540 server. The syntax is format:server_ip:server_port. \ 
  541 The format parameter can contain the following placeholders: %d for \ 
  542 DOM ID, %n for DOM name (if available, otherwise the DOM ID is used) \ 
  543 and %c for channel ID.");
 
  546   std::string roy_server;
 
  550     po::options_description global;
 
  551     global.add(desc).add(lmdesc).add(umdesc);
 
  553     po::variables_map vm;
 
  555         po::command_line_parser(argc, argv).options(global).run()
 
  559     if (vm.count(
"help")) {
 
  567     if (vm.count(
"version")) {
 
  575     use_gui = vm.count(
"gui");
 
  578     lm_mode = vm.count(
"ligier");
 
  580     if (lm_mode && vm.count(
"udp")) {
 
  581       throw std::runtime_error(
"You can specify only one mode. Both provided.");
 
  584     if (vm.count(
"map")) {
 
  585       std::ifstream 
map(dom_names.c_str());
 
  588         throw std::runtime_error(
 
  589             std::string(
"Error reading map file: ")
 
  590             + std::strerror(errno)
 
  596       std::ifstream 
map(dom_names.c_str());
 
  602       po::variables_map vm;
 
  603       po::options_description options;
 
  604       options.add(lmdesc).add(desc);
 
  607           po::command_line_parser(argc, argv).options(options).run()
 
  617       po::variables_map vm;
 
  618       po::options_description options;
 
  619       options.add(desc).add(umdesc);
 
  622           po::command_line_parser(argc, argv).options(options).run()
 
  628       unsigned int counter = 0;
 
  629       if (vm.count(
"port")) {
 
  633       if (vm.count(
"optical")) {
 
  637       if (vm.count(
"acoustic")) {
 
  641       if (vm.count(
"monitoring")) {
 
  648           throw std::runtime_error(
"More than one port provided.");
 
  650           throw std::runtime_error(
"You must specify at least one port.");
 
  654       if (use_gui && type != 
tmch) {
 
  655         throw std::runtime_error(
"GUI is only available in monitoring mode");
 
  658       if (vm.count(
"royweb")) {
 
  660           throw std::runtime_error(
"you can use ROyWeb only with the" 
  661           " monitoring channel");
 
  665         std::replace(roy_setup.begin(), roy_setup.end(), 
':', 
' ');
 
  666         std::istringstream ss(roy_setup);
 
  671         if (ss >> roy_server) {
 
  674         if (ss >> roy_port) {
 
  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.");
 
  684       if (vm.count(
"dumpfile")) {
 
  685         output_file.open(filename.c_str(), std::ios::binary);
 
  687           throw std::runtime_error(
 
  688               "Unable to open file " 
  697   } 
catch (
const po::error& e) {
 
  699       << 
"CLBSwissKnife: Error: " << e.what() << 
'\n' 
  705   } 
catch (
const std::runtime_error& e) {
 
  706     std::cerr << 
"CLBSwissKnife: Error: " << e.what() << std::endl;
 
  710   boost::asio::io_service io_service;
 
  721       boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
 
  723       boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
 
  725       boost::asio::signal_set window_resize(io_service, SIGWINCH);
 
  728       gui::ScreenInitialiser init;
 
  730       gui::Screen screen(io_service, lserver, stats);
 
  732       keyb.async_read_some(
 
  733           boost::asio::buffer(&key, 
sizeof(key)),
 
  739               boost::asio::placeholders::error,
 
  740               boost::asio::placeholders::bytes_transferred
 
  749               boost::asio::placeholders::error
 
  759         , clbsk::consumer::Gui(
terminal_width, dom_names_map, stats, screen)
 
  762       window_resize.async_wait(
 
  765               boost::ref(window_resize),
 
  767               boost::asio::placeholders::error,
 
  768               boost::asio::placeholders::signal_number
 
  775       std::cout << 
"Listening from: " << endpoint << 
':' << tag << 
'\n';
 
  776       boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
 
  778       signals_handler.async_wait(
 
  781               boost::ref(signals_handler),
 
  783               boost::asio::placeholders::error,
 
  784               boost::asio::placeholders::signal_number
 
  800     std::cout << 
"Listening port: " << port << 
'\n' << 
"Data type: ";
 
  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";
 
  809       std::cout << 
"Automatically determined\n";
 
  812     clbsk::consumer::ConsumerSet consumer_set;
 
  814     trm::MonStreamer ms(roy_server, roy_port);
 
  822         << 
") with tag format " 
  823         << templ << std::endl;
 
  826           clbsk::consumer::Roy(
 
  835       consumer_set.add(clbsk::consumer::File(output_file));
 
  842       boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
 
  844       boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
 
  846       boost::asio::signal_set window_resize(io_service, SIGWINCH);
 
  849       gui::ScreenInitialiser init;
 
  851       std::string 
const heading
 
  852         = 
"UDP " + boost::lexical_cast<std::string>(port);
 
  854       gui::Screen screen(io_service, heading, stats);
 
  856       keyb.async_read_some(
 
  857           boost::asio::buffer(&key, 
sizeof(key)),
 
  863               boost::asio::placeholders::error,
 
  864               boost::asio::placeholders::bytes_transferred
 
  873               boost::asio::placeholders::error
 
  877       window_resize.async_wait(
 
  880               boost::ref(window_resize),
 
  882               boost::asio::placeholders::error,
 
  883               boost::asio::placeholders::signal_number
 
  888           clbsk::consumer::Gui(
 
  908           clbsk::consumer::Scrollback(
 
  915       boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
 
  917       signals_handler.async_wait(
 
  920             , boost::ref(signals_handler)
 
  922             , boost::asio::placeholders::error
 
  923             , boost::asio::placeholders::signal_number
 
  941     boost::asio::signal_set& set,
 
  943     boost::system::error_code 
const& error,
 
  948     if (signum == SIGINT) {
 
  953         std::cout << 
"\033]2;thank you for flying with CLBSwissKnife!\007";
 
  954         std::cout << 
"\rBye bye!\n";
 
  957     } 
else if (signum == SIGWINCH) {
 
  966             boost::asio::placeholders::error,
 
  967             boost::asio::placeholders::signal_number
 
TString replace(const TString &target, const TRegexp ®exp, const T &replacement)
Replace regular expression in input by given replacement.
 
void header_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
 
LigierDataHandler & operator=(LigierDataHandler const &)
 
LigierDataHandler(LigierDataHandler const &)
 
void subscribe_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
 
boost::asio::ip::tcp::endpoint m_endpoint
 
void connect_handle(boost::system::error_code const &error)
 
LigierDataHandler(boost::asio::io_service &service, std::string const &tag, boost::asio::ip::tcp::endpoint const &endpoint, char *buffer, std::size_t buffer_size, Consumer const &consumer)
 
boost::asio::deadline_timer m_timer
 
void data_handle(boost::system::error_code const &error, std::size_t size)
 
LigierDataHandler< Consumer > this_type
 
std::size_t const m_buffer_size
 
boost::asio::ip::tcp::socket m_socket
 
void timeout_handle(boost::system::error_code const &error)
 
std::size_t m_buffer_size
 
boost::asio::ip::udp::socket m_socket
 
UdpDataHandler< Consumer > this_type
 
UdpDataHandler(boost::asio::io_service &service, int port, char *buffer, std::size_t buffer_size, Consumer const &consumer)
 
void data_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
 
static const unsigned int default_moni_port
 
int main(int argc, char *argv[])
 
static const unsigned int default_acou_port
 
static const size_t buffer_size
 
void handle_signal(boost::asio::signal_set &set, int &terminal_width, boost::system::error_code const &error, int signum)
 
static const unsigned int default_opto_port
 
#define GET_IO_SERVICE(s)
Program name: CLBSwissKnife.
 
boost::asio::ip::tcp::endpoint make_endpoint(std::string const &address)
 
static int terminal_width
 
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
 
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
 
std::size_t read_data_size(char const *const buffer)
 
std::size_t prepare_tag(char *buffer, std::size_t max_size, std::string const &tag)