Gazebo Transport

API Reference

15.0.0~pre1
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
104 protected: void CreateZenohQueriable(
106 const std::string &_service);
107#endif
108
109#ifdef _WIN32
110// Disable warning C4251 which is triggered by
111// std::string
112#pragma warning(push)
113#pragma warning(disable: 4251)
114#endif
117#ifdef _WIN32
118#pragma warning(pop)
119#endif
120 };
121
126 // the service call. 'Rep' is the protobuf message type that will be filled
128 template <typename Req, typename Rep> class RepHandler
129 : public IRepHandler
130 {
131 // Documentation inherited.
132 using IRepHandler::IRepHandler;
133
140 public: void SetCallback(
141 const std::function<bool(const Req &, Rep &)> &_cb)
142 {
143 this->cb = _cb;
144 }
145
146#ifdef HAVE_ZENOH
155 public: void SetCallback(
156 const std::function<bool(const Req &, Rep &)> &_cb,
158 const std::string &_service)
159 {
160 this->SetCallback(std::move(_cb));
161 this->CreateZenohQueriable(_session, _service);
162 }
163#endif
164
165 // Documentation inherited.
166 public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
167 transport::ProtoMsg &_msgRep)
168 {
169 // Execute the callback (if existing)
170 if (!this->cb)
171 {
172 std::cerr << "RepHandler::RunLocalCallback() error: "
173 << "Callback is NULL" << std::endl;
174 return false;
175 }
176
177#if GOOGLE_PROTOBUF_VERSION >= 5028000
178 const auto msgReq =
179 google::protobuf::DynamicCastMessage<Req>(&_msgReq);
180 auto msgRep =
181 google::protobuf::DynamicCastMessage<Rep>(&_msgRep);
182#elif GOOGLE_PROTOBUF_VERSION >= 4022000
183 auto msgReq =
184 google::protobuf::internal::DownCast<const Req*>(&_msgReq);
185 auto msgRep = google::protobuf::internal::DownCast<Rep*>(&_msgRep);
186#elif GOOGLE_PROTOBUF_VERSION > 2999999
187 auto msgReq = google::protobuf::down_cast<const Req*>(&_msgReq);
188 auto msgRep = google::protobuf::down_cast<Rep*>(&_msgRep);
189#else
190 auto msgReq =
191 google::protobuf::internal::down_cast<const Req*>(&_msgReq);
192 auto msgRep = google::protobuf::internal::down_cast<Rep*>(&_msgRep);
193#endif
194
195 // Verify the dynamically casted messages are valid
196 if (msgReq == nullptr || msgRep == nullptr)
197 {
198 if (msgReq == nullptr)
199 {
200 if (_msgReq.GetDescriptor() != nullptr)
201 {
202 std::cerr << "RepHandler::RunLocalCallback() error: "
203 << "Failed to cast the request of the type "
204 << _msgReq.GetDescriptor()->full_name()
205 << " to the specified type" << '\n';
206 }
207 else
208 {
209 std::cerr << "RepHandler::RunLocalCallback() error: "
210 << "Failed to cast the request of an unknown type"
211 << " to the specified type" << '\n';
212 }
213 }
214 if (msgRep == nullptr)
215 {
216 if (_msgRep.GetDescriptor() != nullptr)
217 {
218 std::cerr << "RepHandler::RunLocalCallback() error: "
219 << "Failed to cast the response of the type "
220 << _msgRep.GetDescriptor()->full_name()
221 << " to the specified type" << '\n';
222 }
223 else
224 {
225 std::cerr << "RepHandler::RunLocalCallback() error: "
226 << "Failed to cast the response of an unknown type"
227 << " to the specified type" << '\n';
228 }
229 }
230 std::cerr.flush();
231 return false;
232 }
233
234 return this->cb(*msgReq, *msgRep);
235 }
236
237 // Documentation inherited.
238 public: bool RunCallback(const std::string &_req,
239 std::string &_rep)
240 {
241 // Check if we have a callback registered.
242 if (!this->cb)
243 {
244 std::cerr << "RepHandler::RunCallback() error: "
245 << "Callback is NULL" << std::endl;
246 return false;
247 }
248
249 // Instantiate the specific protobuf message associated to this topic.
250 auto msgReq = this->CreateMsg(_req);
251 if (!msgReq)
252 {
253 return false;
254 }
255
256 Rep msgRep;
257 if (!this->cb(*msgReq, msgRep))
258 return false;
259
260 if (!msgRep.SerializeToString(&_rep))
261 {
262 std::cerr << "RepHandler::RunCallback(): Error serializing the "
263 << "response" << std::endl;
264 return false;
265 }
266
267 return true;
268 }
269
270 // Documentation inherited.
271 public: virtual std::string ReqTypeName() const
272 {
273 return std::string(Req().GetTypeName());
274 }
275
276 // Documentation inherited.
277 public: virtual std::string RepTypeName() const
278 {
279 return std::string(Rep().GetTypeName());
280 }
281
285 private: std::shared_ptr<Req> CreateMsg(const std::string &_data) const
286 {
287 // Instantiate a specific protobuf message
288 auto msgPtr = std::make_shared<Req>();
289
290 // Create the message using some serialized data
291 if (!msgPtr->ParseFromString(_data))
292 {
293 std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed"
294 << std::endl;
295 }
296
297 return msgPtr;
298 }
299
301 private: std::function<bool(const Req &, Rep &)> cb;
302 };
303 }
304}
305
306#endif