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