Gazebo Transport

API Reference

15.1.0
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)
23#pragma warning(disable: 4251)
24#endif
25#include <google/protobuf/message.h>
26#include <google/protobuf/stubs/common.h>
27#if GOOGLE_PROTOBUF_VERSION > 2999999 && GOOGLE_PROTOBUF_VERSION < 4022000
28#include <google/protobuf/stubs/casts.h>
29#endif
30#ifdef _MSC_VER
31#pragma warning(pop)
32#endif
33
34#include <functional>
35#include <iostream>
36#include <memory>
37#include <string>
38#include <utility>
39
40#include "gz/transport/config.hh"
41#include "gz/transport/Export.hh"
43#include "gz/transport/Uuid.hh"
44
45namespace zenoh
46{
47 // Forward declaration.
48 class Session;
49}
50
51namespace gz::transport
52{
53 // Inline bracket to help doxygen filtering.
54 inline namespace GZ_TRANSPORT_VERSION_NAMESPACE {
55 //
57 class IRepHandlerPrivate;
58
61 class GZ_TRANSPORT_VISIBLE IRepHandler
62 {
66 public: explicit IRepHandler(const std::string &_pUuid,
67 const std::string &_nUuid);
68
70 public: virtual ~IRepHandler();
71
76 public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
77 transport::ProtoMsg &_msgRep) = 0;
78
85 public: virtual bool RunCallback(const std::string &_req,
86 std::string &_rep) = 0;
87
90 public: std::string HandlerUuid() const;
91
94 public: virtual std::string ReqTypeName() const = 0;
95
98 public: virtual std::string RepTypeName() const = 0;
99
100#ifdef HAVE_ZENOH
107 protected: void CreateZenohQueriable(
109 const std::string &_service);
110
113 private: friend class Node;
114#endif
115
116#ifdef _WIN32
117// Disable warning C4251 which is triggered by
118// std::string
119#pragma warning(push)
120#pragma warning(disable: 4251)
121#endif
124#ifdef _WIN32
125#pragma warning(pop)
126#endif
127 };
128
133 // the service call. 'Rep' is the protobuf message type that will be filled
135 template <typename Req, typename Rep> class RepHandler
136 : public IRepHandler
137 {
138 // Documentation inherited.
139 using IRepHandler::IRepHandler;
140
147 public: void SetCallback(
148 const std::function<bool(const Req &, Rep &)> &_cb)
149 {
150 this->cb = _cb;
151 }
152
153#ifdef HAVE_ZENOH
165 public: void SetCallback(
166 const std::function<bool(const Req &, Rep &)> &_cb,
168 const std::string &_service)
169 {
170 this->SetCallback(std::move(_cb));
171 this->CreateZenohQueriable(_session, _service);
172 }
173#endif
174
175 // Documentation inherited.
176 public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
177 transport::ProtoMsg &_msgRep)
178 {
179 // Execute the callback (if existing)
180 if (!this->cb)
181 {
182 std::cerr << "RepHandler::RunLocalCallback() error: "
183 << "Callback is NULL" << std::endl;
184 return false;
185 }
186
187#if GOOGLE_PROTOBUF_VERSION >= 5028000
188 const auto msgReq =
189 google::protobuf::DynamicCastMessage<Req>(&_msgReq);
190 auto msgRep =
191 google::protobuf::DynamicCastMessage<Rep>(&_msgRep);
192#elif GOOGLE_PROTOBUF_VERSION >= 4022000
193 auto msgReq =
194 google::protobuf::internal::DownCast<const Req*>(&_msgReq);
195 auto msgRep = google::protobuf::internal::DownCast<Rep*>(&_msgRep);
196#elif GOOGLE_PROTOBUF_VERSION > 2999999
197 auto msgReq = google::protobuf::down_cast<const Req*>(&_msgReq);
198 auto msgRep = google::protobuf::down_cast<Rep*>(&_msgRep);
199#else
200 auto msgReq =
201 google::protobuf::internal::down_cast<const Req*>(&_msgReq);
202 auto msgRep = google::protobuf::internal::down_cast<Rep*>(&_msgRep);
203#endif
204
205 // Verify the dynamically casted messages are valid
206 if (msgReq == nullptr || msgRep == nullptr)
207 {
208 if (msgReq == nullptr)
209 {
210 if (_msgReq.GetDescriptor() != nullptr)
211 {
212 std::cerr << "RepHandler::RunLocalCallback() error: "
213 << "Failed to cast the request of the type "
214 << _msgReq.GetDescriptor()->full_name()
215 << " to the specified type" << '\n';
216 }
217 else
218 {
219 std::cerr << "RepHandler::RunLocalCallback() error: "
220 << "Failed to cast the request of an unknown type"
221 << " to the specified type" << '\n';
222 }
223 }
224 if (msgRep == nullptr)
225 {
226 if (_msgRep.GetDescriptor() != nullptr)
227 {
228 std::cerr << "RepHandler::RunLocalCallback() error: "
229 << "Failed to cast the response of the type "
230 << _msgRep.GetDescriptor()->full_name()
231 << " to the specified type" << '\n';
232 }
233 else
234 {
235 std::cerr << "RepHandler::RunLocalCallback() error: "
236 << "Failed to cast the response of an unknown type"
237 << " to the specified type" << '\n';
238 }
239 }
240 std::cerr.flush();
241 return false;
242 }
243
244 return this->cb(*msgReq, *msgRep);
245 }
246
247 // Documentation inherited.
248 public: bool RunCallback(const std::string &_req,
249 std::string &_rep)
250 {
251 // Check if we have a callback registered.
252 if (!this->cb)
253 {
254 std::cerr << "RepHandler::RunCallback() error: "
255 << "Callback is NULL" << std::endl;
256 return false;
257 }
258
259 // Instantiate the specific protobuf message associated to this topic.
260 auto msgReq = this->CreateMsg(_req);
261 if (!msgReq)
262 {
263 return false;
264 }
265
266 Rep msgRep;
267 if (!this->cb(*msgReq, msgRep))
268 return false;
269
270 if (!msgRep.SerializeToString(&_rep))
271 {
272 std::cerr << "RepHandler::RunCallback(): Error serializing the "
273 << "response" << std::endl;
274 return false;
275 }
276
277 return true;
278 }
279
280 // Documentation inherited.
281 public: virtual std::string ReqTypeName() const
282 {
283 return std::string(Req().GetTypeName());
284 }
285
286 // Documentation inherited.
287 public: virtual std::string RepTypeName() const
288 {
289 return std::string(Rep().GetTypeName());
290 }
291
295 private: std::shared_ptr<Req> CreateMsg(const std::string &_data) const
296 {
297 // Instantiate a specific protobuf message
298 auto msgPtr = std::make_shared<Req>();
299
300 // Create the message using some serialized data
301 if (!msgPtr->ParseFromString(_data))
302 {
303 std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed"
304 << std::endl;
305 }
306
307 return msgPtr;
308 }
309
311 private: std::function<bool(const Req &, Rep &)> cb;
312 };
313 }
314}
315
316#endif