mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[3793] {create,parse}{Command,Answer} methods updated to new format
createCommand, parseCommand, createAnswer, parseAnswer updated to an new format described here: http://kea.isc.org/wiki/StatsDesign
This commit is contained in:
@@ -17,7 +17,6 @@ lib_LTLIBRARIES = libkea-cc.la
|
||||
libkea_cc_la_SOURCES = data.cc data.h
|
||||
libkea_cc_la_SOURCES += logger.cc logger.h
|
||||
nodist_libkea_cc_la_SOURCES = cc_messages.cc cc_messages.h
|
||||
libkea_cc_la_SOURCES += proto_defs.cc proto_defs.h
|
||||
libkea_cc_la_LIBADD = $(top_builddir)/src/lib/log/libkea-log.la
|
||||
|
||||
CLEANFILES = *.gcno *.gcda session_config.h cc_messages.cc cc_messages.h \
|
||||
@@ -32,11 +31,6 @@ s-messages: cc_messages.mes
|
||||
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/cc/cc_messages.mes
|
||||
touch $@
|
||||
|
||||
BUILT_SOURCES = session_config.h cc_messages.cc cc_messages.h proto_defs.h
|
||||
|
||||
# This rule is here, but we added proto_defs.h to the git repo,
|
||||
# so the script is no longer needed.
|
||||
#proto_defs.h: $(top_srcdir)/src/lib/util/python/const2hdr.py proto_defs.cc
|
||||
# $(PYTHON) $(top_srcdir)/src/lib/util/python/const2hdr.py $(srcdir)/proto_defs.cc $@
|
||||
BUILT_SOURCES = session_config.h cc_messages.cc cc_messages.h
|
||||
|
||||
EXTRA_DIST = cc_messages.mes
|
||||
|
@@ -1,58 +0,0 @@
|
||||
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <cc/proto_defs.h>
|
||||
|
||||
namespace isc {
|
||||
namespace cc {
|
||||
|
||||
// Aside from defining the values for the C++ library, this file is also
|
||||
// used as direct input of the generator of the python counterpart. Please,
|
||||
// keep the syntax here simple and check the generated file
|
||||
// (lib/python/isc/cc/proto_defs.py) is correct and sane.
|
||||
|
||||
// The constants used in the CC protocol
|
||||
// First the header names
|
||||
const char* const CC_HEADER_TYPE = "type";
|
||||
const char* const CC_HEADER_FROM = "from";
|
||||
const char* const CC_HEADER_TO = "to";
|
||||
const char* const CC_HEADER_GROUP = "group";
|
||||
const char* const CC_HEADER_INSTANCE = "instance";
|
||||
const char* const CC_HEADER_SEQ = "seq";
|
||||
const char* const CC_HEADER_WANT_ANSWER = "want_answer";
|
||||
const char* const CC_HEADER_REPLY = "reply";
|
||||
// The commands in the "type" header
|
||||
const char* const CC_COMMAND_SEND = "send";
|
||||
const char* const CC_COMMAND_SUBSCRIBE = "subscribe";
|
||||
const char* const CC_COMMAND_UNSUBSCRIBE = "unsubscribe";
|
||||
const char* const CC_COMMAND_GET_LNAME = "getlname";
|
||||
const char* const CC_COMMAND_PING = "ping";
|
||||
const char* const CC_COMMAND_PONG = "pong";
|
||||
const char* const CC_COMMAND_STOP = "stop";
|
||||
// The wildcards of some headers
|
||||
const char* const CC_TO_WILDCARD = "*";
|
||||
const char* const CC_INSTANCE_WILDCARD = "*";
|
||||
// Prefixes for groups
|
||||
const char* const CC_GROUP_NOTIFICATION_PREFIX = "notifications/";
|
||||
// Reply codes
|
||||
const int CC_REPLY_NO_RECPT = -1;
|
||||
const int CC_REPLY_SUCCESS = 0;
|
||||
// Payload in the message
|
||||
const char *const CC_PAYLOAD_LNAME = "lname";
|
||||
const char *const CC_PAYLOAD_RESULT = "result";
|
||||
const char *const CC_PAYLOAD_COMMAND = "command";
|
||||
const char *const CC_PAYLOAD_NOTIFICATION = "notification";
|
||||
|
||||
}
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
// This file is generated from ./proto_defs.cc
|
||||
// by the const2hdr.py script.
|
||||
// Do not edit, all changes will be lost.
|
||||
|
||||
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef KEA_COMMON_DEFS_H
|
||||
#define KEA_COMMON_DEFS_H
|
||||
|
||||
// \file proto_defs.h
|
||||
// \brief Common shared constants
|
||||
|
||||
// This file contains common definitions of constasts used across the sources.
|
||||
// It includes, but is not limited to the definitions of messages sent from
|
||||
// one process to another. Since the names should be self-explanatory and
|
||||
// the variables here are used mostly to synchronize the same values across
|
||||
// multiple programs, separate documentation for each variable is not provided.
|
||||
|
||||
namespace isc {
|
||||
namespace cc {
|
||||
|
||||
// Aside from defining the values for the C++ library, this file is also
|
||||
// used as direct input of the generator of the python counterpart. Please,
|
||||
// keep the syntax here simple and check the generated file
|
||||
// (lib/python/isc/cc/proto_defs.py) is correct and sane.
|
||||
|
||||
// The constants used in the CC protocol
|
||||
// First the header names
|
||||
extern const char* const CC_HEADER_TYPE;
|
||||
extern const char* const CC_HEADER_FROM;
|
||||
extern const char* const CC_HEADER_TO;
|
||||
extern const char* const CC_HEADER_GROUP;
|
||||
extern const char* const CC_HEADER_INSTANCE;
|
||||
extern const char* const CC_HEADER_SEQ;
|
||||
extern const char* const CC_HEADER_WANT_ANSWER;
|
||||
extern const char* const CC_HEADER_REPLY;
|
||||
// The commands in the "type" header
|
||||
extern const char* const CC_COMMAND_SEND;
|
||||
extern const char* const CC_COMMAND_SUBSCRIBE;
|
||||
extern const char* const CC_COMMAND_UNSUBSCRIBE;
|
||||
extern const char* const CC_COMMAND_GET_LNAME;
|
||||
extern const char* const CC_COMMAND_PING;
|
||||
extern const char* const CC_COMMAND_PONG;
|
||||
extern const char* const CC_COMMAND_STOP;
|
||||
// The wildcards of some headers
|
||||
extern const char* const CC_TO_WILDCARD;
|
||||
extern const char* const CC_INSTANCE_WILDCARD;
|
||||
// Prefixes for groups
|
||||
extern const char* const CC_GROUP_NOTIFICATION_PREFIX;
|
||||
// Reply codes
|
||||
extern const int CC_REPLY_NO_RECPT;
|
||||
extern const int CC_REPLY_SUCCESS;
|
||||
// Payload in the message
|
||||
extern const char *const CC_PAYLOAD_LNAME;
|
||||
extern const char *const CC_PAYLOAD_RESULT;
|
||||
extern const char *const CC_PAYLOAD_COMMAND;
|
||||
extern const char *const CC_PAYLOAD_NOTIFICATION;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -53,70 +53,78 @@ using isc::data::JSONError;
|
||||
namespace isc {
|
||||
namespace config {
|
||||
|
||||
/// Creates a standard config/command protocol answer message
|
||||
const char *CONTROL_COMMAND="command";
|
||||
|
||||
const char *CONTROL_RESULT="result";
|
||||
const char *CONTROL_TEXT="text";
|
||||
const char *CONTROL_ARGUMENTS="arguments";
|
||||
|
||||
// Full version, with status, text and arguments
|
||||
ConstElementPtr
|
||||
createAnswer(const int status_code, const std::string& text,
|
||||
const ConstElementPtr& arg) {
|
||||
if (status_code != 0 && text.empty()) {
|
||||
isc_throw(CtrlChannelError, "Text has to be provided for status_code != 0");
|
||||
}
|
||||
|
||||
ElementPtr answer = Element::createMap();
|
||||
ElementPtr result = Element::create(status_code);
|
||||
answer->set(CONTROL_RESULT, result);
|
||||
|
||||
if (!text.empty()) {
|
||||
answer->set(CONTROL_TEXT, Element::create(text));
|
||||
}
|
||||
if (arg) {
|
||||
answer->set(CONTROL_ARGUMENTS, arg);
|
||||
}
|
||||
return (answer);
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
createAnswer() {
|
||||
ElementPtr answer = Element::createMap();
|
||||
ElementPtr answer_content = Element::createList();
|
||||
answer_content->add(Element::create(isc::cc::CC_REPLY_SUCCESS));
|
||||
answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
|
||||
|
||||
return (answer);
|
||||
return (createAnswer(0, string(""), ConstElementPtr()));
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
createAnswer(const int rcode, ConstElementPtr arg) {
|
||||
if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
|
||||
isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
|
||||
}
|
||||
ElementPtr answer = Element::createMap();
|
||||
ElementPtr answer_content = Element::createList();
|
||||
answer_content->add(Element::create(rcode));
|
||||
answer_content->add(arg);
|
||||
answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
|
||||
|
||||
return (answer);
|
||||
createAnswer(const int status_code, const std::string& text) {
|
||||
return (createAnswer(status_code, text, ElementPtr()));
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
createAnswer(const int rcode, const std::string& arg) {
|
||||
ElementPtr answer = Element::createMap();
|
||||
ElementPtr answer_content = Element::createList();
|
||||
answer_content->add(Element::create(rcode));
|
||||
answer_content->add(Element::create(arg));
|
||||
answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content);
|
||||
|
||||
return (answer);
|
||||
createAnswer(const int status_code, const ConstElementPtr& arg) {
|
||||
return (createAnswer(status_code, "", arg));
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
parseAnswer(int &rcode, ConstElementPtr msg) {
|
||||
if (msg &&
|
||||
msg->getType() == Element::map &&
|
||||
msg->contains(isc::cc::CC_PAYLOAD_RESULT)) {
|
||||
ConstElementPtr result = msg->get(isc::cc::CC_PAYLOAD_RESULT);
|
||||
if (result->getType() != Element::list) {
|
||||
isc_throw(CCSessionError, "Result element in answer message is not a list");
|
||||
} else if (result->get(0)->getType() != Element::integer) {
|
||||
isc_throw(CCSessionError, "First element of result is not an rcode in answer message");
|
||||
parseAnswer(int &rcode, const ConstElementPtr& msg) {
|
||||
if (!msg) {
|
||||
isc_throw(CtrlChannelError, "No answer specified");
|
||||
}
|
||||
rcode = result->get(0)->intValue();
|
||||
if (result->size() > 1) {
|
||||
if (rcode == 0 || result->get(1)->getType() == Element::string) {
|
||||
return (result->get(1));
|
||||
} else {
|
||||
isc_throw(CCSessionError, "Error description in result with rcode != 0 is not a string");
|
||||
if (msg->getType() != Element::map) {
|
||||
isc_throw(CtrlChannelError,
|
||||
"Invalid answer Element specified, expected map");
|
||||
}
|
||||
} else {
|
||||
if (rcode == 0) {
|
||||
return (ElementPtr());
|
||||
} else {
|
||||
isc_throw(CCSessionError, "Result with rcode != 0 does not have an error description");
|
||||
if (!msg->contains(CONTROL_RESULT)) {
|
||||
isc_throw(CtrlChannelError,
|
||||
"Invalid answer specified, does not contain mandatory 'result'");
|
||||
}
|
||||
|
||||
ConstElementPtr result = msg->get(CONTROL_RESULT);
|
||||
if (result->getType() != Element::integer) {
|
||||
isc_throw(CtrlChannelError,
|
||||
"Result element in answer message is not a string");
|
||||
}
|
||||
} else {
|
||||
isc_throw(CCSessionError, "No result part in answer message");
|
||||
|
||||
rcode = result->intValue();
|
||||
|
||||
// If there are arguments, return them.
|
||||
ConstElementPtr args = msg->get(CONTROL_ARGUMENTS);
|
||||
if (args) {
|
||||
return (args);
|
||||
}
|
||||
|
||||
// There are no arguments, let's try to return just the text status
|
||||
return (msg->get(CONTROL_TEXT));
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
@@ -126,37 +134,37 @@ createCommand(const std::string& command) {
|
||||
|
||||
ConstElementPtr
|
||||
createCommand(const std::string& command, ConstElementPtr arg) {
|
||||
ElementPtr cmd = Element::createMap();
|
||||
ElementPtr cmd_parts = Element::createList();
|
||||
cmd_parts->add(Element::create(command));
|
||||
ElementPtr query = Element::createMap();
|
||||
ElementPtr cmd = Element::create(command);
|
||||
query->set(CONTROL_COMMAND, cmd);
|
||||
if (arg) {
|
||||
cmd_parts->add(arg);
|
||||
query->set(CONTROL_ARGUMENTS, arg);
|
||||
}
|
||||
cmd->set(isc::cc::CC_PAYLOAD_COMMAND, cmd_parts);
|
||||
return (cmd);
|
||||
return (query);
|
||||
}
|
||||
|
||||
std::string
|
||||
parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
|
||||
if (command &&
|
||||
command->getType() == Element::map &&
|
||||
command->contains(isc::cc::CC_PAYLOAD_COMMAND)) {
|
||||
ConstElementPtr cmd = command->get(isc::cc::CC_PAYLOAD_COMMAND);
|
||||
if (cmd->getType() == Element::list &&
|
||||
!cmd->empty() &&
|
||||
cmd->get(0)->getType() == Element::string) {
|
||||
if (cmd->size() > 1) {
|
||||
arg = cmd->get(1);
|
||||
} else {
|
||||
arg = Element::createMap();
|
||||
if (!command) {
|
||||
isc_throw(CtrlChannelError, "No command specified");
|
||||
}
|
||||
return (cmd->get(0)->stringValue());
|
||||
} else {
|
||||
isc_throw(CCSessionError, "Command part in command message missing, empty, or not a list");
|
||||
if (command->getType() != Element::map) {
|
||||
isc_throw(CtrlChannelError, "Invalid command Element specified, expected map");
|
||||
}
|
||||
} else {
|
||||
isc_throw(CCSessionError, "Command Element empty or not a map with \"command\"");
|
||||
if (!command->contains(CONTROL_COMMAND)) {
|
||||
isc_throw(CtrlChannelError,
|
||||
"Invalid answer specified, does not contain mandatory 'command'");
|
||||
}
|
||||
|
||||
ConstElementPtr cmd = command->get(CONTROL_COMMAND);
|
||||
if (cmd->getType() != Element::string) {
|
||||
isc_throw(CtrlChannelError,
|
||||
"'command' element in command message is not a string");
|
||||
}
|
||||
|
||||
arg = command->get(CONTROL_ARGUMENTS);
|
||||
|
||||
return (cmd->stringValue());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include <config/module_spec.h>
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <cc/proto_defs.h>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
@@ -28,112 +27,97 @@
|
||||
namespace isc {
|
||||
namespace config {
|
||||
|
||||
///
|
||||
/// \brief Creates a standard config/command level success answer message
|
||||
/// (i.e. of the form { "result": [ 0 ] }
|
||||
/// \return Standard command/config success answer message
|
||||
extern const char *CONTROL_COMMAND;
|
||||
|
||||
extern const char *CONTROL_RESULT;
|
||||
extern const char *CONTROL_TEXT;
|
||||
extern const char *CONTROL_ARGUMENTS;
|
||||
|
||||
const int CONTROL_RESULT_SUCCESS = 0;
|
||||
const int CONTROL_RESULT_ERROR = 1;
|
||||
|
||||
/// @brief Creates a standard config/command level success answer message
|
||||
/// (i.e. of the form { "result": 0 }
|
||||
/// @return Standard command/config success answer message
|
||||
isc::data::ConstElementPtr createAnswer();
|
||||
|
||||
/// @brief Creates a standard config/command level answer message
|
||||
/// (i.e. of the form { "result": 1, "text": "Invalid command received" }
|
||||
///
|
||||
/// \brief Creates a standard config/command level answer message
|
||||
/// (i.e. of the form { "result": [ rcode, arg ] }
|
||||
/// @param status_code The return code (0 for success)
|
||||
/// @param status_text A string to put into the "text" argument
|
||||
/// @return Standard command/config answer message
|
||||
isc::data::ConstElementPtr createAnswer(const int status_code,
|
||||
const std::string& status_text);
|
||||
|
||||
/// @brief Creates a standard config/command level answer message
|
||||
/// (i.e. of the form { "result": status_code, "arguments": arg }
|
||||
///
|
||||
/// @param status_code The return code (0 for success)
|
||||
/// @param status_text A string to put into the "text" argument
|
||||
/// @return Standard command/config answer message
|
||||
isc::data::ConstElementPtr createAnswer(const int status_code,
|
||||
const isc::data::ConstElementPtr& arg);
|
||||
|
||||
/// @brief Creates a standard config/command level answer message
|
||||
/// (i.e. of the form { "result": X, "[ rcode, arg ] }
|
||||
/// If rcode != 0, arg must be a StringElement
|
||||
///
|
||||
/// \param rcode The return code (0 for success)
|
||||
/// \param arg For rcode == 0, this is an optional argument of any
|
||||
/// Element type. For rcode == 1, this argument is mandatory,
|
||||
/// and must be a StringElement containing an error description
|
||||
/// \return Standard command/config answer message
|
||||
isc::data::ConstElementPtr createAnswer(const int rcode,
|
||||
isc::data::ConstElementPtr arg);
|
||||
/// @param status_code The return code (0 for success)
|
||||
/// @param arg For status_code == 0, this is an optional argument of any
|
||||
/// Element type. For status_code == 1, this argument is mandatory,
|
||||
/// and may be any type of ElementPtr.
|
||||
/// @return Standard command/config answer message
|
||||
isc::data::ConstElementPtr createAnswer(const int status_code,
|
||||
const std::string& status,
|
||||
const isc::data::ConstElementPtr& arg);
|
||||
|
||||
/// @brief Parses a standard config/command level answer message.
|
||||
///
|
||||
/// \brief Creates a standard config/command level answer message
|
||||
/// (i.e. of the form { "result": [ rcode, arg ] }
|
||||
///
|
||||
/// \param rcode The return code (0 for success)
|
||||
/// \param arg A string to put into the StringElement argument
|
||||
/// \return Standard command/config answer message
|
||||
isc::data::ConstElementPtr createAnswer(const int rcode,
|
||||
const std::string& arg);
|
||||
|
||||
///
|
||||
/// Parses a standard config/command level answer message
|
||||
///
|
||||
/// \param rcode This value will be set to the return code contained in
|
||||
/// @param status_code This value will be set to the return code contained in
|
||||
/// the message
|
||||
/// \param msg The message to parse
|
||||
/// \return The optional argument in the message, or an empty ElementPtr
|
||||
/// @param msg The message to parse
|
||||
/// @return The optional argument in the message, or an empty ElementPtr
|
||||
/// if there was no argument. If rcode != 0, this contains a
|
||||
/// StringElement with the error description.
|
||||
isc::data::ConstElementPtr parseAnswer(int &rcode,
|
||||
isc::data::ConstElementPtr msg);
|
||||
isc::data::ConstElementPtr parseAnswer(int &status_code,
|
||||
const isc::data::ConstElementPtr& msg);
|
||||
|
||||
/// @brief Creates a standard config/command command message with no
|
||||
/// argument (of the form { "command": "my_command" }
|
||||
///
|
||||
/// \brief Creates a standard config/command command message with no
|
||||
/// argument (of the form { "command": [ "my_command" ] }
|
||||
///
|
||||
/// \param command The command string
|
||||
/// \return The created message
|
||||
/// @param command The command string
|
||||
/// @return The created message
|
||||
isc::data::ConstElementPtr createCommand(const std::string& command);
|
||||
|
||||
/// @brief Creates a standard config/command command message with the
|
||||
/// given argument (of the form { "command": "my_command", "arguments": arg }
|
||||
///
|
||||
/// \brief Creates a standard config/command command message with the
|
||||
/// given argument (of the form { "command": [ "my_command", arg ] }
|
||||
///
|
||||
/// \param command The command string
|
||||
/// \param arg The optional argument for the command. This can be of
|
||||
/// @param command The command string
|
||||
/// @param arg The optional argument for the command. This can be of
|
||||
/// any Element type, but it should conform to the .spec file.
|
||||
/// \return The created message
|
||||
/// @return The created message
|
||||
isc::data::ConstElementPtr createCommand(const std::string& command,
|
||||
isc::data::ConstElementPtr arg);
|
||||
|
||||
///
|
||||
/// \brief Parses the given command into a string containing the actual
|
||||
/// @brief Parses the given command into a string containing the actual
|
||||
/// command and an ElementPtr containing the optional argument.
|
||||
///
|
||||
/// Raises a CCSessionError if this is not a well-formed command
|
||||
/// @throw Raises a CtrlChannelError if this is not a well-formed command
|
||||
///
|
||||
/// Example code: (command_message is a ConstElementPtr that is
|
||||
/// passed here)
|
||||
/// \code
|
||||
/// ElementPtr command_message = Element::fromJSON("{ \"command\": [\"foo\", { \"bar\": 123 } ] }");
|
||||
/// try {
|
||||
/// ConstElementPtr args;
|
||||
/// std::string command_str = parseCommand(args, command_message);
|
||||
/// if (command_str == "foo") {
|
||||
/// std::cout << "The command 'foo' was given" << std::endl;
|
||||
/// if (args->contains("bar")) {
|
||||
/// std::cout << "It had argument name 'bar' set, which has"
|
||||
/// << "value "
|
||||
/// << args->get("bar")->intValue();
|
||||
/// }
|
||||
/// } else {
|
||||
/// std::cout << "Unknown command '" << command_str << std::endl;
|
||||
/// }
|
||||
/// } catch (CCSessionError cse) {
|
||||
/// std::cerr << "Bad command in CC Session: "
|
||||
/// << cse.what() << std::endl;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \param arg This value will be set to the ElementPtr pointing to
|
||||
/// @param arg This value will be set to the ElementPtr pointing to
|
||||
/// the argument, or to an empty Map (ElementPtr) if there was none.
|
||||
/// \param command The command message containing the command (as made
|
||||
/// @param command The command message containing the command (as made
|
||||
/// by createCommand()
|
||||
/// \return The command name
|
||||
std::string parseCommand(isc::data::ConstElementPtr& arg,
|
||||
isc::data::ConstElementPtr command);
|
||||
|
||||
|
||||
///
|
||||
/// \brief A standard cc session exception that is thrown if a function
|
||||
/// @brief A standard control channel exception that is thrown if a function
|
||||
/// is there is a problem with one of the messages
|
||||
///
|
||||
// todo: include types and called function in the exception
|
||||
class CCSessionError : public isc::Exception {
|
||||
class CtrlChannelError : public isc::Exception {
|
||||
public:
|
||||
CCSessionError(const char* file, size_t line, const char* what) :
|
||||
CtrlChannelError(const char* file, size_t line, const char* what) :
|
||||
isc::Exception(file, line, what) {}
|
||||
};
|
||||
|
||||
|
@@ -24,7 +24,6 @@
|
||||
|
||||
using namespace isc::data;
|
||||
using namespace isc::config;
|
||||
using namespace isc::cc;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
@@ -50,16 +49,17 @@ protected:
|
||||
TEST_F(CCSessionTest, createAnswer) {
|
||||
ConstElementPtr answer;
|
||||
answer = createAnswer();
|
||||
EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str());
|
||||
EXPECT_EQ("{ \"result\": 0 }", answer->str());
|
||||
answer = createAnswer(1, "error");
|
||||
EXPECT_EQ("{ \"result\": [ 1, \"error\" ] }", answer->str());
|
||||
EXPECT_EQ("{ \"result\": 1, \"text\": \"error\" }", answer->str());
|
||||
|
||||
EXPECT_THROW(createAnswer(1, ElementPtr()), CCSessionError);
|
||||
EXPECT_THROW(createAnswer(1, Element::create(1)), CCSessionError);
|
||||
EXPECT_THROW(createAnswer(1, ElementPtr()), CtrlChannelError);
|
||||
EXPECT_THROW(createAnswer(1, Element::create(1)), CtrlChannelError);
|
||||
|
||||
ConstElementPtr arg = el("[ \"just\", \"some\", \"data\" ]");
|
||||
answer = createAnswer(0, arg);
|
||||
EXPECT_EQ("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }", answer->str());
|
||||
EXPECT_EQ("{ \"arguments\": [ \"just\", \"some\", \"data\" ], \"result\": 0 }",
|
||||
answer->str());
|
||||
}
|
||||
|
||||
TEST_F(CCSessionTest, parseAnswer) {
|
||||
@@ -67,27 +67,26 @@ TEST_F(CCSessionTest, parseAnswer) {
|
||||
ConstElementPtr arg;
|
||||
int rcode;
|
||||
|
||||
EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("1")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("[]")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"something\": 1 }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 0 }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 1 }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ] }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ] }")), CCSessionError);
|
||||
EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("1")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("[]")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"something\": 1 }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 0 ] }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ] }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ] }")), CtrlChannelError);
|
||||
|
||||
answer = el("{ \"result\": [ 0 ] }");
|
||||
answer = el("{ \"result\": 0 }");
|
||||
arg = parseAnswer(rcode, answer);
|
||||
EXPECT_EQ(0, rcode);
|
||||
EXPECT_TRUE(isNull(arg));
|
||||
|
||||
answer = el("{ \"result\": [ 1, \"error\"] }");
|
||||
answer = el("{ \"result\": 1, \"text\": \"error\" }");
|
||||
arg = parseAnswer(rcode, answer);
|
||||
EXPECT_EQ(1, rcode);
|
||||
EXPECT_EQ("error", arg->stringValue());
|
||||
|
||||
answer = el("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }");
|
||||
answer = el("{ \"result\": 0, \"arguments\": [ \"just\", \"some\", \"data\" ] }");
|
||||
arg = parseAnswer(rcode, answer);
|
||||
EXPECT_EQ(0, rcode);
|
||||
EXPECT_EQ("[ \"just\", \"some\", \"data\" ]", arg->str());
|
||||
@@ -98,19 +97,22 @@ TEST_F(CCSessionTest, createCommand) {
|
||||
ConstElementPtr arg;
|
||||
|
||||
command = createCommand("my_command");
|
||||
ASSERT_EQ("{ \"command\": [ \"my_command\" ] }", command->str());
|
||||
ASSERT_EQ("{ \"command\": \"my_command\" }", command->str());
|
||||
|
||||
arg = el("1");
|
||||
command = createCommand("my_command", arg);
|
||||
ASSERT_EQ("{ \"command\": [ \"my_command\", 1 ] }", command->str());
|
||||
ASSERT_EQ("{ \"arguments\": 1, \"command\": \"my_command\" }",
|
||||
command->str());
|
||||
|
||||
arg = el("[ \"a\", \"b\" ]");
|
||||
command = createCommand("my_cmd", arg);
|
||||
ASSERT_EQ("{ \"command\": [ \"my_cmd\", [ \"a\", \"b\" ] ] }", command->str());
|
||||
ASSERT_EQ("{ \"arguments\": [ \"a\", \"b\" ], \"command\": \"my_cmd\" }",
|
||||
command->str());
|
||||
|
||||
arg = el("{ \"a\": \"map\" }");
|
||||
command = createCommand("foo", arg);
|
||||
ASSERT_EQ("{ \"command\": [ \"foo\", { \"a\": \"map\" } ] }", command->str());
|
||||
ASSERT_EQ("{ \"arguments\": { \"a\": \"map\" }, \"command\": \"foo\" }",
|
||||
command->str());
|
||||
}
|
||||
|
||||
TEST_F(CCSessionTest, parseCommand) {
|
||||
@@ -118,24 +120,26 @@ TEST_F(CCSessionTest, parseCommand) {
|
||||
std::string cmd;
|
||||
|
||||
// should throw
|
||||
EXPECT_THROW(parseCommand(arg, ElementPtr()), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("1")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ }")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"not a command\": 1 }")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": 1 }")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": [] }")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": [ 1 ] }")), CCSessionError);
|
||||
EXPECT_THROW(parseCommand(arg, ElementPtr()), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("1")), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"not a command\": 1 }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": 1 }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": [] }")), CtrlChannelError);
|
||||
EXPECT_THROW(parseCommand(arg, el("{ \"command\": [ 1 ] }")), CtrlChannelError);
|
||||
|
||||
cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\" ] }"));
|
||||
cmd = parseCommand(arg, el("{ \"command\": \"my_command\" }"));
|
||||
EXPECT_EQ("my_command", cmd);
|
||||
EXPECT_EQ(*arg, *Element::createMap());
|
||||
EXPECT_FALSE(arg);
|
||||
|
||||
cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\", 1 ] }"));
|
||||
cmd = parseCommand(arg, el("{ \"command\": \"my_command\", \"arguments\": 1 }"));
|
||||
ASSERT_TRUE(arg);
|
||||
EXPECT_EQ("my_command", cmd);
|
||||
EXPECT_EQ("1", arg->str());
|
||||
|
||||
parseCommand(arg, el("{ \"command\": [ \"my_command\", [ \"some\", \"argument\", \"list\" ] ] }"));
|
||||
parseCommand(arg, el("{ \"command\": \"my_command\", \"arguments\": [ \"some\", \"argument\", \"list\" ] }"));
|
||||
EXPECT_EQ("my_command", cmd);
|
||||
ASSERT_TRUE(arg);
|
||||
EXPECT_EQ("[ \"some\", \"argument\", \"list\" ]", arg->str());
|
||||
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <cc/proto_defs.h>
|
||||
#include <config/ccsession.h>
|
||||
#include <dhcpsrv/testutils/config_result_check.h>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
@@ -28,15 +28,16 @@ using namespace isc::data;
|
||||
|
||||
bool errorContainsPosition(ConstElementPtr error_element,
|
||||
const std::string& file_name) {
|
||||
if (error_element->contains(isc::cc::CC_PAYLOAD_RESULT)) {
|
||||
ConstElementPtr result = error_element->get(isc::cc::CC_PAYLOAD_RESULT);
|
||||
if ((result->getType() != Element::list) || (result->size() < 2) ||
|
||||
(result->get(1)->getType() != Element::string)) {
|
||||
if (error_element->contains(isc::config::CONTROL_RESULT)) {
|
||||
ConstElementPtr result = error_element->get(isc::config::CONTROL_RESULT);
|
||||
ConstElementPtr text = error_element->get(isc::config::CONTROL_TEXT);
|
||||
if (!result || (result->getType() != Element::integer) || !text
|
||||
|| (text->getType() != Element::string)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Get the error message in the textual format.
|
||||
std::string error_string = result->get(1)->stringValue();
|
||||
std::string error_string = text->stringValue();
|
||||
|
||||
// The position of the data element causing an error has the following
|
||||
// format: <filename>:<linenum>:<pos>. The <filename> has been specified
|
||||
|
Reference in New Issue
Block a user