Gazebo Transport

API Reference

14.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
39#include "gz/transport/config.hh"
40#include "gz/transport/Export.hh"
42#include "gz/transport/Uuid.hh"
43
44namespace gz::transport
45{
46 // Inline bracket to help doxygen filtering.
47 inline namespace GZ_TRANSPORT_VERSION_NAMESPACE {
48 //
51 class GZ_TRANSPORT_VISIBLE IRepHandler
52 {
54 public: IRepHandler()
55 : hUuid(Uuid().ToString())
56 {
57 }
58
60 public: virtual ~IRepHandler() = default;
61
66 public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
67 transport::ProtoMsg &_msgRep) = 0;
68
75 public: virtual bool RunCallback(const std::string &_req,
76 std::string &_rep) = 0;
77
80 public: std::string HandlerUuid() const
81 {
82 return this->hUuid;
83 }
84
87 public: virtual std::string ReqTypeName() const = 0;
88
91 public: virtual std::string RepTypeName() const = 0;
92
93#ifdef _WIN32
94// Disable warning C4251 which is triggered by
95// std::string
96#pragma warning(push)
97#pragma warning(disable: 4251)
98#endif
100 protected: std::string hUuid;
101#ifdef _WIN32
102#pragma warning(pop)
103#endif
104 };
105
110 // the service call. 'Rep' is the protobuf message type that will be filled
112 template <typename Req, typename Rep> class RepHandler
113 : public IRepHandler
114 {
115 // Documentation inherited.
116 public: RepHandler() = default;
117
124 public: void SetCallback(
125 const std::function<bool(const Req &, Rep &)> &_cb)
126 {
127 this->cb = _cb;
128 }
129
130 // Documentation inherited.
131 public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
132 transport::ProtoMsg &_msgRep)
133 {
134 // Execute the callback (if existing)
135 if (!this->cb)
136 {
137 std::cerr << "RepHandler::RunLocalCallback() error: "
138 << "Callback is NULL" << std::endl;
139 return false;
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 auto msgPtr = std::make_shared<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