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)