Gazebo Transport

API Reference

11.4.1
gz/transport/RepHandler.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #ifndef GZ_TRANSPORT_REPHANDLER_HH_
19 #define GZ_TRANSPORT_REPHANDLER_HH_
20 
21 #ifdef _MSC_VER
22 #pragma warning(push, 0)
23 #endif
24 #include <google/protobuf/message.h>
25 #ifdef _MSC_VER
26 #pragma warning(pop)
27 #endif
28 
29 #if GOOGLE_PROTOBUF_VERSION > 2999999 && GOOGLE_PROTOBUF_VERSION < 4022000
30 #include <google/protobuf/stubs/casts.h>
31 #endif
32 
33 #include <functional>
34 #include <iostream>
35 #include <memory>
36 #include <string>
37 
38 #include "gz/transport/config.hh"
39 #include "gz/transport/Export.hh"
41 #include "gz/transport/Uuid.hh"
42 
43 namespace ignition::transport
44 {
45  // Inline bracket to help doxygen filtering.
46  inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {
47  //
50  class IGNITION_TRANSPORT_VISIBLE IRepHandler
51  {
53  public: IRepHandler()
54  : hUuid(Uuid().ToString())
55  {
56  }
57 
59  public: virtual ~IRepHandler() = default;
60 
65  public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
66  transport::ProtoMsg &_msgRep) = 0;
67 
74  public: virtual bool RunCallback(const std::string &_req,
75  std::string &_rep) = 0;
76 
79  public: std::string HandlerUuid() const
80  {
81  return this->hUuid;
82  }
83 
86  public: virtual std::string ReqTypeName() const = 0;
87 
90  public: virtual std::string RepTypeName() const = 0;
91 
92 #ifdef _WIN32
93 // Disable warning C4251 which is triggered by
94 // std::string
95 #pragma warning(push)
96 #pragma warning(disable: 4251)
97 #endif
98  protected: std::string hUuid;
100 #ifdef _WIN32
101 #pragma warning(pop)
102 #endif
103  };
104 
109  // the service call. 'Rep' is the protobuf message type that will be filled
111  template <typename Req, typename Rep> class RepHandler
112  : public IRepHandler
113  {
114  // Documentation inherited.
115  public: RepHandler() = default;
116 
123  public: void SetCallback(
124  const std::function<bool(const Req &, Rep &)> &_cb)
125  {
126  this->cb = _cb;
127  }
128 
129  // Documentation inherited.
130  public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
131  transport::ProtoMsg &_msgRep)
132  {
133  // Execute the callback (if existing)
134  if (!this->cb)
135  {
136  std::cerr << "RepHandler::RunLocalCallback() error: "
137  << "Callback is NULL" << std::endl;
138  return false;
139  }
140 
141 
142 #if GOOGLE_PROTOBUF_VERSION >= 5028000
143  const auto msgReq =
144  google::protobuf::DynamicCastMessage<Req>(&_msgReq);
145  auto msgRep =
146  google::protobuf::DynamicCastMessage<Rep>(&_msgRep);
147 #elif GOOGLE_PROTOBUF_VERSION >= 4022000
148  auto msgReq =
149  google::protobuf::internal::DownCast<const Req*>(&_msgReq);
150  auto msgRep = google::protobuf::internal::DownCast<Rep*>(&_msgRep);
151 #elif GOOGLE_PROTOBUF_VERSION > 2999999
152  auto msgReq = google::protobuf::down_cast<const Req*>(&_msgReq);
153  auto msgRep = google::protobuf::down_cast<Rep*>(&_msgRep);
154 #else
155  auto msgReq =
156  google::protobuf::internal::down_cast<const Req*>(&_msgReq);
157  auto msgRep = google::protobuf::internal::down_cast<Rep*>(&_msgRep);
158 #endif
159 
160  // Verify the dynamically casted messages are valid
161  if (msgReq == nullptr || msgRep == nullptr)
162  {
163  if (msgReq == nullptr)
164  {
165  if (_msgReq.GetDescriptor() != nullptr)
166  {
167  std::cerr << "RepHandler::RunLocalCallback() error: "
168  << "Failed to cast the request of the type "
169  << _msgReq.GetDescriptor()->full_name()
170  << " to the specified type" << '\n';
171  }
172  else
173  {
174  std::cerr << "RepHandler::RunLocalCallback() error: "
175  << "Failed to cast the request of an unknown type"
176  << " to the specified type" << '\n';
177  }
178  }
179  if (msgRep == nullptr)
180  {
181  if (_msgRep.GetDescriptor() != nullptr)
182  {
183  std::cerr << "RepHandler::RunLocalCallback() error: "
184  << "Failed to cast the response of the type "
185  << _msgRep.GetDescriptor()->full_name()
186  << " to the specified type" << '\n';
187  }
188  else
189  {
190  std::cerr << "RepHandler::RunLocalCallback() error: "
191  << "Failed to cast the response of an unknown type"
192  << " to the specified type" << '\n';
193  }
194  }
195  std::cerr.flush();
196  return false;
197  }
198 
199  return this->cb(*msgReq, *msgRep);
200  }
201 
202  // Documentation inherited.
203  public: bool RunCallback(const std::string &_req,
204  std::string &_rep)
205  {
206  // Check if we have a callback registered.
207  if (!this->cb)
208  {
209  std::cerr << "RepHandler::RunCallback() error: "
210  << "Callback is NULL" << std::endl;
211  return false;
212  }
213 
214  // Instantiate the specific protobuf message associated to this topic.
215  auto msgReq = this->CreateMsg(_req);
216  if (!msgReq)
217  {
218  return false;
219  }
220 
221  Rep msgRep;
222  if (!this->cb(*msgReq, msgRep))
223  return false;
224 
225  if (!msgRep.SerializeToString(&_rep))
226  {
227  std::cerr << "RepHandler::RunCallback(): Error serializing the "
228  << "response" << std::endl;
229  return false;
230  }
231 
232  return true;
233  }
234 
235  // Documentation inherited.
236  public: virtual std::string ReqTypeName() const
237  {
238  return std::string(Req().GetTypeName());
239  }
240 
241  // Documentation inherited.
242  public: virtual std::string RepTypeName() const
243  {
244  return std::string(Rep().GetTypeName());
245  }
246 
250  private: std::shared_ptr<Req> CreateMsg(const std::string &_data) const
251  {
252  // Instantiate a specific protobuf message
253  std::shared_ptr<Req> msgPtr(new Req());
254 
255  // Create the message using some serialized data
256  if (!msgPtr->ParseFromString(_data))
257  {
258  std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed"
259  << std::endl;
260  }
261 
262  return msgPtr;
263  }
264 
266  private: std::function<bool(const Req &, Rep &)> cb;
267  };
268  }
269 }
270 
271 #endif
bool RunLocalCallback(const transport::ProtoMsg &_msgReq, transport::ProtoMsg &_msgRep)
Executes the local callback registered for this handler.
Definition: gz/transport/RepHandler.hh:130
STL class.
STL class.
google::protobuf::Message ProtoMsg
Definition: gz/transport/TransportTypes.hh:68
virtual std::string RepTypeName() const =0
Get the message type name used in the service response.
std::string HandlerUuid() const
Get the unique UUID of this handler.
Definition: gz/transport/RepHandler.hh:79
virtual bool RunCallback(const std::string &_req, std::string &_rep)=0
Executes the callback registered for this handler.
A portable class for representing a Universally Unique Identifier.
Definition: gz/transport/Uuid.hh:43
void SetCallback(const std::function< bool(const Req &, Rep &)> &_cb)
Set the callback for this handler.
Definition: gz/transport/RepHandler.hh:123
virtual ~IRepHandler()=default
Destructor.
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: gz/transport/RepHandler.hh:236
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: gz/transport/RepHandler.hh:242
virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq, transport::ProtoMsg &_msgRep)=0
Executes the local callback registered for this handler.
with the service response.
Definition: gz/transport/RepHandler.hh:111
std::string hUuid
Unique handler's UUID.
Definition: gz/transport/RepHandler.hh:99
T endl(T... args)
Definition: gz/transport/AdvertiseOptions.hh:28
IRepHandler()
Constructor.
Definition: gz/transport/RepHandler.hh:53
Interface class used to manage a replier handler.
Definition: gz/transport/RepHandler.hh:50
virtual std::string ReqTypeName() const =0
Get the message type name used in the service request.
bool RunCallback(const std::string &_req, std::string &_rep)
Executes the callback registered for this handler.
Definition: gz/transport/RepHandler.hh:203