Skip to content

Commit

Permalink
Oneway service request from the command line (#477)
Browse files Browse the repository at this point in the history
* Support request/advertise within the same process.

Signed-off-by: Carlos Agüero <[email protected]>
  • Loading branch information
caguero authored Mar 13, 2024
1 parent cfb80d2 commit 3a5553a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 21 deletions.
24 changes: 16 additions & 8 deletions src/cmd/gz.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,17 +251,25 @@ extern "C" void cmdServiceReq(const char *_service,
Node node;
bool result;

// Request the service.
bool executed = node.Request(_service, *req, _timeout, *rep, result);
if (executed)
if (!strcmp(_repType, "gz.msgs.Empty"))
{
if (result)
std::cout << rep->DebugString() << std::endl;
else
std::cout << "Service call failed" << std::endl;
// One-way service.
node.Request(_service, *req, 1000, *rep, result);
}
else
std::cerr << "Service call timed out" << std::endl;
{
// Two-way service.
bool executed = node.Request(_service, *req, _timeout, *rep, result);
if (executed)
{
if (result)
std::cout << rep->DebugString() << std::endl;
else
std::cout << "Service call failed" << std::endl;
}
else
std::cerr << "Service call timed out" << std::endl;
}
}

//////////////////////////////////////////////////
Expand Down
14 changes: 8 additions & 6 deletions src/cmd/gz.hh
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,26 @@ extern "C" void cmdServiceList();
/// E.g.: cmdTopicPub("/foo", "gz.msgs.StringMsg",
/// "'data:\"Custom data\"');
extern "C" void cmdTopicPub(const char *_topic,
const char *_msgType,
const char *_msgData);
const char *_msgType,
const char *_msgData);

/// \brief External hook to execute 'gz service -r' from the command line.
/// \param[in] _service Service name.
/// \param[in] _reqType Message type used in the request.
/// \param[in] _repType Message type used in the response.
/// If "gz.msgs.Empty" is used, the request will be one-way
/// and _repType and _timeout will be ignored.
/// \param[in] _timeout The request will timeout after '_timeout' ms.
/// \param[in] _reqData Input data sent in the request.
/// The format expected is the same used by Protobuf DebugString().
/// E.g.: cmdServiceReq("/bar", "gz.msgs.StringMsg",
/// "gz.msgs.StringMsg", 1000,
/// "'data:\"Custom data\"');
extern "C" void cmdServiceReq(const char *_service,
const char *_reqType,
const char *_repType,
const int _timeout,
const char *_reqData);
const char *_reqType,
const char *_repType,
const int _timeout,
const char *_reqData);

extern "C" {
/// \brief Enum used for specifing the message output format for functions
Expand Down
32 changes: 31 additions & 1 deletion src/cmd/gz_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ bool srvEcho(const msgs::Int32 &_req, msgs::Int32 &_rep)
return true;
}

//////////////////////////////////////////////////
/// \brief Provide a one-way service.
void srvOneway(const msgs::StringMsg &_msg)
{
g_topicCBStr = _msg.data();
}

//////////////////////////////////////////////////
/// \brief Topic callback
void topicCB(const msgs::StringMsg &_msg)
Expand Down Expand Up @@ -324,7 +331,7 @@ TEST(gzTest, TopicPublish)
}

//////////////////////////////////////////////////
/// \brief Check 'gz service -r' to request a service.
/// \brief Check 'gz service -r' to request a two-way service.
TEST(gzTest, ServiceRequest)
{
transport::Node node;
Expand All @@ -347,6 +354,29 @@ TEST(gzTest, ServiceRequest)
ASSERT_EQ(output.cout, "data: " + value + "\n\n");
}

//////////////////////////////////////////////////
/// \brief Check 'gz service -r' to request a one-way service.
TEST(gzTest, ServiceOnewayRequest)
{
g_topicCBStr = "bad_value";
transport::Node node;

// Advertise a service.
std::string service = "/oneway";
EXPECT_TRUE(node.Advertise(service, srvOneway));

msgs::StringMsg msg;
msg.set_data("good_value");

// Check the 'gz service' oneway command.
auto output = custom_exec_str(
{"service", "-s", service, "--reqtype", "gz.msgs.StringMsg",
"--req", "data: \"good_value\""});

std::this_thread::sleep_for(std::chrono::milliseconds(500));
EXPECT_EQ("good_value", g_topicCBStr);
}

//////////////////////////////////////////////////
/// \brief Check 'gz topic -e' running the publisher on a separate process.
TEST(gzTest, TopicEcho)
Expand Down
23 changes: 17 additions & 6 deletions src/cmd/service_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,20 @@ void runServiceCommand(const ServiceOptions &_opt)
cmdServiceInfo(_opt.service.c_str());
break;
case ServiceCommand::kServiceReq:
cmdServiceReq(_opt.service.c_str(),
_opt.reqType.c_str(), _opt.repType.c_str(),
_opt.timeout, _opt.reqData.c_str());
if (_opt.repType.empty())
{
// One-way service request.
cmdServiceReq(_opt.service.c_str(),
_opt.reqType.c_str(), "gz.msgs.Empty",
0, _opt.reqData.c_str());
}
else
{
// Two-way service request.
cmdServiceReq(_opt.service.c_str(),
_opt.reqType.c_str(), _opt.repType.c_str(),
_opt.timeout, _opt.reqData.c_str());
}
break;
case ServiceCommand::kNone:
default:
Expand All @@ -93,6 +104,8 @@ void addServiceFlags(CLI::App &_app)
opt->repType, "Type of a response.");
auto timeoutOpt = _app.add_option("--timeout",
opt->timeout, "Timeout in milliseconds.");
repTypeOpt = repTypeOpt->needs(timeoutOpt);
timeoutOpt = timeoutOpt->needs(repTypeOpt);

auto command = _app.add_option_group("command", "Command to be executed.");

Expand Down Expand Up @@ -123,9 +136,7 @@ the same used by Protobuf DebugString(). E.g.:
--req 'data: "Hello"'
)")
->needs(serviceOpt)
->needs(reqTypeOpt)
->needs(repTypeOpt)
->needs(timeoutOpt);
->needs(reqTypeOpt);

_app.callback([opt](){runServiceCommand(*opt); });
}
Expand Down

0 comments on commit 3a5553a

Please sign in to comment.