Gazebo Transport

API Reference

14.0.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
45{
46 namespace transport
47 {
48 // Inline bracket to help doxygen filtering.
49 inline namespace GZ_TRANSPORT_VERSION_NAMESPACE {
50 //
53 class GZ_TRANSPORT_VISIBLE IRepHandler
54 {
56 public: IRepHandler()
57 : hUuid(Uuid().ToString())
58 {
59 }
60
62 public: virtual ~IRepHandler() = default;
63
68 public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
69 transport::ProtoMsg &_msgRep) = 0;
70
77 public: virtual bool RunCallback(const std::string &_req,
78 std::string &_rep) = 0;
79
82 public: std::string HandlerUuid() const
83 {
84 return this->hUuid;
85 }
86
89 public: virtual std::string ReqTypeName() const = 0;
90
93 public: virtual std::string RepTypeName() const = 0;
94
95#ifdef _WIN32
96// Disable warning C4251 which is triggered by
97// std::string
98#pragma warning(push)
99#pragma warning(disable: 4251)
100#endif
102 protected: std::string hUuid;
103#ifdef _WIN32
104#pragma warning(pop)
105#endif
106 };
107
112 // the service call. 'Rep' is the protobuf message type that will be filled
114 template <typename Req, typename Rep> class RepHandler
115 : public IRepHandler
116 {
117 // Documentation inherited.
118 public: RepHandler() = default;
119
126 public: void SetCallback(
127 const std::function<bool(const Req &, Rep &)> &_cb)
128 {
129 this->cb = _cb;
130 }
131
132 // Documentation inherited.
133 public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq,
134 transport::ProtoMsg &_msgRep)
135 {
136 // Execute the callback (if existing)
137 if (!this->cb)
138 {
139 std::cerr << "RepHandler::RunLocalCallback() error: "
140 << "Callback is NULL" << std::endl;
141 return false;
142 }
143
144#if GOOGLE_PROTOBUF_VERSION >= 5028000
145 const auto msgReq =
146 google::protobuf::DynamicCastMessage<Req>(&_msgReq);
147 auto msgRep =
148 google::protobuf::DynamicCastMessage<Rep>(&_msgRep);
149#elif GOOGLE_PROTOBUF_VERSION >= 4022000
150 auto msgReq =
151 google::protobuf::internal::DownCast<const Req*>(&_msgReq);
152 auto msgRep = google::protobuf::internal::DownCast<Rep*>(&_msgRep);
153#elif GOOGLE_PROTOBUF_VERSION > 2999999
154 auto msgReq = google::protobuf::down_cast<const Req*>(&_msgReq);
155 auto msgRep = google::protobuf::down_cast<Rep*>(&_msgRep);
156#else
157 auto msgReq =
158 google::protobuf::internal::down_cast<const Req*>(&_msgReq);
159 auto msgRep = google::protobuf::internal::down_cast<Rep*>(&_msgRep);
160#endif
161
162 // Verify the dynamically casted messages are valid
163 if (msgReq == nullptr || msgRep == nullptr)
164 {
165 if (msgReq == nullptr)
166 {
167 if (_msgReq.GetDescriptor() != nullptr)
168 {
169 std::cerr << "RepHandler::RunLocalCallback() error: "
170 << "Failed to cast the request of the type "
171 << _msgReq.GetDescriptor()->full_name()
172 << " to the specified type" << '\n';
173 }
174 else
175 {
176 std::cerr << "RepHandler::RunLocalCallback() error: "
177 << "Failed to cast the request of an unknown type"
178 << " to the specified type" << '\n';
179 }
180 }
181 if (msgRep == nullptr)
182 {
183 if (_msgRep.GetDescriptor() != nullptr)
184 {
185 std::cerr << "RepHandler::RunLocalCallback() error: "
186 << "Failed to cast the response of the type "
187 << _msgRep.GetDescriptor()->full_name()
188 << " to the specified type" << '\n';
189 }
190 else
191 {
192 std::cerr << "RepHandler::RunLocalCallback() error: "
193 << "Failed to cast the response of an unknown type"
194 << " to the specified type" << '\n';
195 }
196 }
197 std::cerr.flush();
198 return false;
199 }
200
201 return this->cb(*msgReq, *msgRep);
202 }
203
204 // Documentation inherited.
205 public: bool RunCallback(const std::string &_req,
206 std::string &_rep)
207 {
208 // Check if we have a callback registered.
209 if (!this->cb)
210 {
211 std::cerr << "RepHandler::RunCallback() error: "
212 << "Callback is NULL" << std::endl;
213 return false;
214 }
215
216 // Instantiate the specific protobuf message associated to this topic.
217 auto msgReq = this->CreateMsg(_req);
218 if (!msgReq)
219 {
220 return false;
221 }
222
223 Rep msgRep;
224 if (!this->cb(*msgReq, msgRep))
225 return false;
226
227 if (!msgRep.SerializeToString(&_rep))
228 {
229 std::cerr << "RepHandler::RunCallback(): Error serializing the "
230 << "response" << std::endl;
231 return false;
232 }
233
234 return true;
235 }
236
237 // Documentation inherited.
238 public: virtual std::string ReqTypeName() const
239 {
240 return Req().GetTypeName();
241 }
242
243 // Documentation inherited.
244 public: virtual std::string RepTypeName() const
245 {
246 return Rep().GetTypeName();
247 }
248
252 private: std::shared_ptr<Req> CreateMsg(const std::string &_data) const
253 {
254 // Instantiate a specific protobuf message
255 std::shared_ptr<Req> msgPtr(new Req());
256
257 // Create the message using some serialized data
258 if (!msgPtr->ParseFromString(_data))
259 {
260 std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed"
261 << std::endl;
262 }
263
264 return msgPtr;
265 }
266
268 private: std::function<bool(const Req &, Rep &)> cb;
269 };
270 }
271 }
272}
273
274#endif