LCOV - code coverage report
Current view: top level - eventdispatcher - connection_with_send_message.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 83 1.2 %
Date: 2019-08-08 02:52:36 Functions: 2 15 13.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Snap Communicator -- classes to ease handling communication between processes
       2             : // Copyright (c) 2012-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // This program is free software; you can redistribute it and/or modify
       5             : // it under the terms of the GNU General Public License as published by
       6             : // the Free Software Foundation; either version 2 of the License, or
       7             : // (at your option) any later version.
       8             : //
       9             : // This program is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : // GNU General Public License for more details.
      13             : //
      14             : // You should have received a copy of the GNU General Public License
      15             : // along with this program; if not, write to the Free Software
      16             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      17             : 
      18             : /** \file
      19             :  * \brief Implementation of the Connection with Send Message class.
      20             :  *
      21             :  * This is a base class which ease the implementation of a connection
      22             :  * which is able to send and receive messages.
      23             :  */
      24             : 
      25             : 
      26             : // self
      27             : //
      28             : #include    "eventdispatcher/connection_with_send_message.h"
      29             : 
      30             : #include    "eventdispatcher/dispatcher_support.h"
      31             : #include    "eventdispatcher/exception.h"
      32             : 
      33             : 
      34             : // snaplogger lib
      35             : //
      36             : #include    "snaplogger/logger.h"
      37             : #include    "snaplogger/message.h"
      38             : 
      39             : 
      40             : // snapdev lib
      41             : //
      42             : //#include "snapdev/not_reached.h"
      43             : #include    "snapdev/not_used.h"
      44             : //#include "snapdev/string_replace_many.h"
      45             : 
      46             : 
      47             : // boost lib
      48             : //
      49             : #include    <boost/algorithm/string/join.hpp>
      50             : 
      51             : 
      52             : //// libaddr lib
      53             : ////
      54             : //#include "libaddr/addr_parser.h"
      55             : //
      56             : //
      57             : //// C++ lib
      58             : ////
      59             : //#include <sstream>
      60             : //#include <limits>
      61             : //#include <atomic>
      62             : //
      63             : //
      64             : //// C lib
      65             : ////
      66             : //#include <fcntl.h>
      67             : //#include <poll.h>
      68             : //#include <unistd.h>
      69             : //#include <sys/eventfd.h>
      70             : //#include <sys/inotify.h>
      71             : //#include <sys/ioctl.h>
      72             : //#include <sys/resource.h>
      73             : //#include <sys/syscall.h>
      74             : //#include <sys/time.h>
      75             : 
      76             : 
      77             : // last include
      78             : //
      79             : #include <snapdev/poison.h>
      80             : 
      81             : 
      82             : 
      83             : 
      84             : namespace ed
      85             : {
      86             : 
      87             : 
      88             : 
      89             : /** \brief Initialize a connection_with_send_message object.
      90             :  *
      91             :  * This constructor initializes a connectopm which supports a send_message()
      92             :  * function. This allows that object to send a certain number of default
      93             :  * messages such as the UNKNOWN message automatically.
      94             :  */
      95           0 : connection_with_send_message::~connection_with_send_message()
      96             : {
      97           0 : }
      98             : 
      99             : 
     100             : 
     101             : /** \brief Build the HELP reply and send it.
     102             :  *
     103             :  * When a daemon registers with the snapcommunicator, it sends a REGISTER
     104             :  * command. As a result, the daemon is sent a HELP command which must be
     105             :  * answered with a COMMAND and the list of commands that this connection
     106             :  * supports.
     107             :  *
     108             :  * \note
     109             :  * If the environment logger is not currently configured, this message
     110             :  * gets ignored.
     111             :  *
     112             :  * \param[in] message  The HELP message.
     113             :  *
     114             :  * \sa msg_ready()
     115             :  */
     116           0 : void connection_with_send_message::msg_help(message & msg)
     117             : {
     118           0 :     snap::NOTUSED(msg);
     119             : 
     120           0 :     bool need_user_help(true);
     121           0 :     string_list_t commands;
     122             : 
     123             :     dispatcher_base * d;
     124           0 :     dispatcher_support * ds(dynamic_cast<dispatcher_support *>(this));
     125           0 :     if(ds != nullptr)
     126             :     {
     127             :         // we extract the bare pointer because in the other case
     128             :         // we only get a bare pointer... (which we can't safely
     129             :         // put in a shared pointer, although we could attempt to
     130             :         // use shared_from_this() but we could have a class without
     131             :         // it?)
     132             :         //
     133           0 :         d = ds->get_dispatcher().get();
     134             :     }
     135             :     else
     136             :     {
     137           0 :         d = dynamic_cast<dispatcher_base *>(this);
     138             :     }
     139           0 :     if(d != nullptr)
     140             :     {
     141           0 :         need_user_help = d->get_commands(commands);
     142             :     }
     143             : 
     144             :     // the user has "unknown" commands (as far as the dispatcher is concerned)
     145             :     // in his list of commands so we have to let him enter them "manually"
     146             :     //
     147             :     // this happens whenever there is an entry which is a regular expression
     148             :     // or something similar which we just cannot grab
     149             :     //
     150           0 :     if(need_user_help)
     151             :     {
     152           0 :         help(commands);
     153             :     }
     154             : 
     155             :     // the list of commands just cannot be empty
     156             :     //
     157           0 :     if(commands.empty())
     158             :     {
     159             :         throw event_dispatcher_implementation_error(
     160             :                 "connection_with_send_message::msg_help()"
     161           0 :                 " is not able to determine the commands this messenger supports");
     162             :     }
     163             : 
     164             :     // Now prepare the COMMAND message and send it
     165             :     //
     166             :     // Note: we turn off the caching on this message, it does not make sense
     167             :     //       because if snapcommunicator is not running, then caching won't
     168             :     //       happen work anyway (i.e. snapcommunicator has to send HELP first
     169             :     //       and then we send the reply, if it has to restart, then just
     170             :     //       sending COMMANDS will fail.)
     171             :     //
     172           0 :     message reply;
     173           0 :     reply.set_command("COMMANDS");
     174           0 :     reply.add_parameter("list", boost::algorithm::join(commands, ","));
     175           0 :     if(!send_message(reply, false))
     176             :     {
     177             :         SNAP_LOG_WARNING
     178           0 :             << "could not reply to \""
     179           0 :             << msg.get_command()
     180           0 :             << "\" with a COMMANDS message.";
     181             :     }
     182           0 : }
     183             : 
     184             : 
     185             : /** \brief Reply to the watchdog message ALIVE.
     186             :  *
     187             :  * To check whether a service is alive, send the ALIVE message. This
     188             :  * function builds a ABSOLUTELY reply and attaches the "serial" parameter
     189             :  * as is if present. It will also include the original "timestamp" parameter
     190             :  * when present.
     191             :  *
     192             :  * The function also adds one field named "reply_timestamp" with the Unix
     193             :  * time when the reply is being sent.
     194             :  *
     195             :  * \note
     196             :  * The "serial" parameter is expected to be used to make sure that no messages
     197             :  * are lost, or if loss is expected, to see whether loss is heavy or not.
     198             :  *
     199             :  * \note
     200             :  * The "serial" and "timestamp" parameters do not get checked. If present
     201             :  * in the original message, they get copied verbatim to the destination.
     202             :  * This allows you to include anything you want in those parameters although
     203             :  * we suggest you use the "timestamp" only for a value representing time.
     204             :  *
     205             :  * \param[in] message  The STOP message.
     206             :  */
     207           0 : void connection_with_send_message::msg_alive(message & msg)
     208             : {
     209           0 :     message absolutely;
     210           0 :     absolutely.reply_to(msg);
     211           0 :     absolutely.set_command("ABSOLUTELY");
     212           0 :     if(msg.has_parameter("serial"))
     213             :     {
     214           0 :         absolutely.add_parameter("serial", msg.get_parameter("serial"));
     215             :     }
     216           0 :     if(msg.has_parameter("timestamp"))
     217             :     {
     218           0 :         absolutely.add_parameter("timestamp", msg.get_parameter("timestamp"));
     219             :     }
     220           0 :     absolutely.add_parameter("reply_timestamp", time(nullptr));
     221           0 :     if(!send_message(absolutely, false))
     222             :     {
     223             :         SNAP_LOG_WARNING
     224           0 :             << "could not reply to \""
     225           0 :             << msg.get_command()
     226           0 :             << "\" with an ABSOLULTELY message.";
     227             :     }
     228           0 : }
     229             : 
     230             : 
     231             : /** \brief Reconfigure the logger.
     232             :  *
     233             :  * Whenever the logrotate runs or some changes are maed to the log
     234             :  * definitions, the corresponding daemons need to reconfigure their
     235             :  * logger to make use of the new file and settings. This command is
     236             :  * used for the purpose.
     237             :  *
     238             :  * \note
     239             :  * If the environment logger is not currently configured, this message
     240             :  * gets ignored.
     241             :  *
     242             :  * \param[in] message  The STOP message.
     243             :  */
     244           0 : void connection_with_send_message::msg_log(message & msg)
     245             : {
     246           0 :     snap::NOTUSED(msg);
     247             : 
     248           0 :     if(snaplogger::is_configured())
     249             :     {
     250             :         // send log in the old file and format
     251             :         //
     252             :         SNAP_LOG_INFO
     253           0 :             << "-------------------- Logging reconfiguration request.";
     254             : 
     255             :         // reconfigure
     256             :         //
     257           0 :         snaplogger::reopen();
     258             : 
     259             :         // send log to new file and format
     260             :         //
     261             :         SNAP_LOG_INFO
     262           0 :             << "-------------------- Logging reconfiguration done.";
     263             :     }
     264           0 : }
     265             : 
     266             : 
     267             : /** \brief Call you stop() function with true.
     268             :  *
     269             :  * This command means that someone is asking your daemon to quit as soon as
     270             :  * possible because the Snap! environment is being asked to shutdown.
     271             :  *
     272             :  * The value 'true' means that all the daemons are being asked to stop and
     273             :  * not just you.
     274             :  *
     275             :  * \param[in] message  The STOP message.
     276             :  *
     277             :  * \sa msg_stop()
     278             :  */
     279           0 : void connection_with_send_message::msg_quitting(message & msg)
     280             : {
     281           0 :     snap::NOTUSED(msg);
     282             : 
     283           0 :     stop(true);
     284           0 : }
     285             : 
     286             : 
     287             : /** \brief Call you ready() function with the message.
     288             :  *
     289             :  * All daemons using the snapcommunicator daemon have to have a ready()
     290             :  * function which gets called once the HELP and COMMAND message were
     291             :  * handled. This is why your daemon is expected to be ready to start
     292             :  * working. Some daemon, though, start working immediately no matter
     293             :  * what (i.e. snapwatchdog and snapfirewall do work either way.)
     294             :  *
     295             :  * \param[in] message  The READY message.
     296             :  *
     297             :  * \sa msg_help()
     298             :  */
     299           0 : void connection_with_send_message::msg_ready(message & msg)
     300             : {
     301             :     // pass the message so any additional info can be accessed.
     302             :     //
     303           0 :     ready(msg);
     304           0 : }
     305             : 
     306             : 
     307             : /** \brief Call you stop() function with false.
     308             :  *
     309             :  * This command means that someone is asking your daemon to stop.
     310             :  *
     311             :  * The value 'false' means just your daemon was asked to stop and not the
     312             :  * entire system to shutdown (otherwise you would receive a QUITTING command
     313             :  * instead.)
     314             :  *
     315             :  * \param[in] message  The STOP message.
     316             :  *
     317             :  * \sa msg_quitting()
     318             :  */
     319           0 : void connection_with_send_message::msg_stop(message & msg)
     320             : {
     321           0 :     snap::NOTUSED(msg);
     322             : 
     323           0 :     stop(false);
     324           0 : }
     325             : 
     326             : 
     327             : /** \brief Handle the UNKNOWN message.
     328             :  *
     329             :  * Whenever we send a command to another daemon, that command can be refused
     330             :  * by sending an UNKNOWN reply. This function handles the UNKNOWN command
     331             :  * by simply recording that as an error in the logs.
     332             :  *
     333             :  * \param[in] message  The UNKNOWN message we just received.
     334             :  */
     335           0 : void connection_with_send_message::msg_log_unknown(message & msg)
     336             : {
     337             :     // we sent a command that the other end did not understand
     338             :     // and got an UNKNOWN reply
     339             :     //
     340             :     SNAP_LOG_ERROR
     341           0 :         << "we sent unknown command \""
     342           0 :         << msg.get_parameter("command")
     343           0 :         << "\" and probably did not get the expected result.";
     344           0 : }
     345             : 
     346             : 
     347             : /** \brief Send the UNKNOWN message as a reply.
     348             :  *
     349             :  * This function replies to the \p message with the UNKNOWN message as
     350             :  * expected by all our `snap_connection`'s when a service receives a
     351             :  * message it does not know how to handle.
     352             :  *
     353             :  * It is expected to be used in your dispatcher_match array.
     354             :  *
     355             :  * \note
     356             :  * This function is virtual which allows you to add it to your array of
     357             :  * of dispatcher_match items. The following shows an example of what that
     358             :  * can look like.
     359             :  *
     360             :  * \code
     361             :  *  {
     362             :  *      ...
     363             :  *
     364             :  *      // ALWAYS LAST
     365             :  *      {
     366             :  *          nullptr
     367             :  *        , &my_service_connection::msg_reply_with_unknown
     368             :  *        , &snap::dispatcher<my_service_connection>::dispatcher_match::always_match
     369             :  *      }
     370             :  *  };
     371             :  * \endcode
     372             :  *
     373             :  * \param[in] message  The messageto reply to.
     374             :  */
     375           0 : void connection_with_send_message::msg_reply_with_unknown(message & msg)
     376             : {
     377           0 :     message unknown;
     378           0 :     unknown.reply_to(msg);
     379           0 :     unknown.set_command("UNKNOWN");
     380           0 :     unknown.add_parameter("command", msg.get_command());
     381           0 :     if(!send_message(unknown, false))
     382             :     {
     383             :         SNAP_LOG_WARNING
     384           0 :             << "could not reply to \""
     385           0 :             << msg.get_command()
     386           0 :             << "\" with UNKNOWN message.";
     387             :     }
     388           0 : }
     389             : 
     390             : 
     391             : /** \brief The default help() function does nothing.
     392             :  *
     393             :  * This implementation does nothing. It is expected that you reimplement
     394             :  * this function depending on your daemon's need.
     395             :  *
     396             :  * The help() function gets called whenever the list of commands can't be
     397             :  * 100% defined automatically.
     398             :  *
     399             :  * Your function is expected to add commands to the \p commands parameter
     400             :  * as in:
     401             :  *
     402             :  * \code
     403             :  *      commands << "MSG1";
     404             :  *      commands << "MSG2";
     405             :  *      commands << "MSG3";
     406             :  * \endcode
     407             :  *
     408             :  * This allows you to handle those three messages with a single entry in
     409             :  * your list of dispatcher_match objects with a regular expression such
     410             :  * as "MSG[1-3]".
     411             :  *
     412             :  * \param[in,out] commands  List of commands to update.
     413             :  */
     414           0 : void connection_with_send_message::help(string_list_t & commands)
     415             : {
     416           0 :     snap::NOTUSED(commands);
     417             : 
     418             :     // do nothing by default -- user is expected to overload this function
     419           0 : }
     420             : 
     421             : 
     422             : /** \brief The default ready() function does nothing.
     423             :  *
     424             :  * This implementation does nothing. It is expected that you reimplement
     425             :  * this function depending on your daemon's need. Most often this function
     426             :  * is the one that really starts your daemons process.
     427             :  *
     428             :  * \param[in,out] message  The READY message.
     429             :  */
     430           0 : void connection_with_send_message::ready(message & msg)
     431             : {
     432           0 :     snap::NOTUSED(msg);
     433             : 
     434             :     // do nothing by default -- user is expected to overload this function
     435             :     //
     436             :     SNAP_LOG_WARNING
     437           0 :         << "default ready() function was called.";
     438           0 : }
     439             : 
     440             : 
     441             : /** \brief The default stop() function does nothing.
     442             :  *
     443             :  * This implementation does nothing. It is expected that you reimplement
     444             :  * this function depending on your daemon's need.
     445             :  *
     446             :  * \param[in] quitting  Whether the QUITTING (true) or STOP (false) command
     447             :  *                      was received.
     448             :  */
     449           0 : void connection_with_send_message::stop(bool quitting)
     450             : {
     451           0 :     snap::NOTUSED(quitting);
     452             : 
     453             :     // do nothing by default -- user is expected to overload this function
     454             :     //
     455             :     SNAP_LOG_WARNING
     456           0 :         << "default stop() function was called.";
     457           0 : }
     458             : 
     459             : 
     460             : 
     461           6 : } // namespace ed
     462             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12