Skip to content

Commit 7289a97

Browse files
authored
Merge pull request #76 from c-jimenez/dev/add_callerror_support
Dev/add callerror support
2 parents e448308 + 096b4f6 commit 7289a97

File tree

7 files changed

+234
-66
lines changed

7 files changed

+234
-66
lines changed

src/messages/GenericMessageSender.h

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ enum class CallResult
3636
/** @brief Message will be sent later */
3737
Delayed,
3838
/** @brief Message cannot be send or no response has been received */
39-
Failed
39+
Failed,
40+
/** @brief A call error message has been received */
41+
Error
4042
};
4143

4244
/** @brief Generic message sender with C++ data type to JSON conversion */
@@ -79,6 +81,46 @@ class GenericMessageSender
7981
ResponseType& response,
8082
IRequestFifo* request_fifo = nullptr,
8183
unsigned int connector_id = 0)
84+
{
85+
std::string error;
86+
std::string message;
87+
return call(action, request, response, error, message, request_fifo, connector_id);
88+
}
89+
90+
/**
91+
* @brief Execute a call request
92+
* @param action RPC action for the request
93+
* @param request Request payload
94+
* @param response Response payload
95+
* @param error Error (Empty if not a CallError)
96+
* @param message Error message (Empty if not a CallError)
97+
* @return Result of the call request (See CallResult documentation)
98+
*/
99+
template <typename RequestType, typename ResponseType>
100+
CallResult call(const std::string& action, const RequestType& request, ResponseType& response, std::string& error, std::string& message)
101+
{
102+
return call(action, request, response, error, message, nullptr, 0);
103+
}
104+
105+
/**
106+
* @brief Execute a call request
107+
* @param action RPC action for the request
108+
* @param request Request payload
109+
* @param response Response payload
110+
* @param error Error (Empty if not a CallError)
111+
* @param message Error message (Empty if not a CallError)
112+
* @param request_fifo Pointer to the request FIFO to use when messages cannot be sent.
113+
* @param connector_id Id of the connector associated to the request.
114+
* @return Result of the call request (See CallResult documentation)
115+
*/
116+
template <typename RequestType, typename ResponseType>
117+
CallResult call(const std::string& action,
118+
const RequestType& request,
119+
ResponseType& response,
120+
std::string& error,
121+
std::string& message,
122+
IRequestFifo* request_fifo,
123+
unsigned int connector_id)
82124
{
83125
CallResult ret = CallResult::Failed;
84126

@@ -97,17 +139,25 @@ class GenericMessageSender
97139
if (!request_fifo || request_fifo->empty())
98140
{
99141
// Execute call
100-
rapidjson::Document resp;
101-
resp.Parse("{}");
102-
if (m_rpc.call(action, payload, resp, m_timeout))
142+
rapidjson::Document rpc_frame;
143+
rapidjson::Value resp;
144+
if (m_rpc.call(action, payload, rpc_frame, resp, error, message, m_timeout))
103145
{
104-
// Convert response
105-
const char* error_code = nullptr;
106-
std::string error_message;
107-
resp_converter->setAllocator(&resp.GetAllocator());
108-
if (resp_converter->fromJson(resp, response, error_code, error_message))
146+
// Check error
147+
if (error.empty())
148+
{
149+
// Convert response
150+
const char* error_code = nullptr;
151+
std::string error_message;
152+
resp_converter->setAllocator(&rpc_frame.GetAllocator());
153+
if (resp_converter->fromJson(resp, response, error_code, error_message))
154+
{
155+
ret = CallResult::Ok;
156+
}
157+
}
158+
else
109159
{
110-
ret = CallResult::Ok;
160+
ret = CallResult::Error;
111161
}
112162
}
113163
else
@@ -149,17 +199,27 @@ class GenericMessageSender
149199
if (resp_converter)
150200
{
151201
// Execute call
152-
rapidjson::Document resp;
153-
resp.Parse("{}");
154-
if (m_rpc.call(action, request, resp, m_timeout))
202+
rapidjson::Document rpc_frame;
203+
rapidjson::Value resp;
204+
std::string error;
205+
std::string message;
206+
if (m_rpc.call(action, request, rpc_frame, resp, error, message, m_timeout))
155207
{
156-
// Convert response
157-
const char* error_code = nullptr;
158-
std::string error_message;
159-
resp_converter->setAllocator(&resp.GetAllocator());
160-
if (resp_converter->fromJson(resp, response, error_code, error_message))
208+
// Check error
209+
if (error.empty())
210+
{
211+
// Convert response
212+
const char* error_code = nullptr;
213+
std::string error_message;
214+
resp_converter->setAllocator(&rpc_frame.GetAllocator());
215+
if (resp_converter->fromJson(resp, response, error_code, error_message))
216+
{
217+
ret = CallResult::Ok;
218+
}
219+
}
220+
else
161221
{
162-
ret = CallResult::Ok;
222+
ret = CallResult::Error;
163223
}
164224
}
165225
}

src/rpc/IRpc.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,19 @@ class IRpc
5050
* @brief Call a remote action and wait for its response
5151
* @param action Remote action
5252
* @param payload JSON payload for the action
53+
* @param rpc_frame Full JSON response received
5354
* @param response JSON response received
55+
* @param error Error code (empty if no error)
56+
* @param message Error message (empty if no error)
5457
* @param timeout Response timeout
5558
* @return true if a response has been received, false otherwise
5659
*/
5760
virtual bool call(const std::string& action,
5861
const rapidjson::Document& payload,
59-
rapidjson::Document& response,
62+
rapidjson::Document& rpc_frame,
63+
rapidjson::Value& response,
64+
std::string& error,
65+
std::string& message,
6066
std::chrono::milliseconds timeout = std::chrono::seconds(2)) = 0;
6167

6268
/**

src/rpc/RpcBase.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,14 @@ RpcBase::~RpcBase()
4545
stop();
4646
}
4747

48-
/** @copydoc bool IRpc::call(const std::string&, const rapidjson::Document&, rapidjson::Document&, std::chrono::milliseconds) */
48+
/** @copydoc bool IRpc::call(const std::string&, const rapidjson::Document&, rapidjson::Document&, rapidjson::Value&,
49+
* std::string&, std::string&, std::chrono::milliseconds) */
4950
bool RpcBase::call(const std::string& action,
5051
const rapidjson::Document& payload,
51-
rapidjson::Document& response,
52+
rapidjson::Document& rpc_frame,
53+
rapidjson::Value& response,
54+
std::string& error,
55+
std::string& message,
5256
std::chrono::milliseconds timeout)
5357
{
5458
bool ret = false;
@@ -110,7 +114,18 @@ bool RpcBase::call(const std::string& action,
110114
// Extract response
111115
if (rpc_message)
112116
{
113-
response.CopyFrom(rpc_message->payload, response.GetAllocator());
117+
rpc_frame.Swap(rpc_message->rpc_frame);
118+
response.Swap(rpc_message->payload);
119+
error.clear();
120+
message.clear();
121+
if (!rpc_message->error.IsNull())
122+
{
123+
error = rpc_message->error.GetString();
124+
}
125+
if (!rpc_message->message.IsNull())
126+
{
127+
message = rpc_message->message.GetString();
128+
}
114129
delete rpc_message;
115130
}
116131
else
@@ -233,14 +248,14 @@ void RpcBase::processReceivedData(const void* data, size_t size)
233248
switch (msg_type)
234249
{
235250
case MessageType::CALL:
236-
valid = decodeCall(unique_id, rpc_frame[2], rpc_frame[3]);
251+
valid = decodeCall(unique_id, rpc_frame, rpc_frame[2], rpc_frame[3]);
237252
break;
238253
case MessageType::CALLRESULT:
239-
valid = decodeCallResult(unique_id, rpc_frame[2]);
254+
valid = decodeCallResult(unique_id, rpc_frame, rpc_frame[2]);
240255
break;
241256
case MessageType::CALLERROR:
242257
default:
243-
valid = decodeCallError(unique_id, rpc_frame[2], rpc_frame[3], rpc_frame[4]);
258+
valid = decodeCallError(unique_id, rpc_frame, rpc_frame[2], rpc_frame[3], rpc_frame[4]);
244259
break;
245260
}
246261
if (!valid)
@@ -283,15 +298,18 @@ bool RpcBase::send(const std::string& msg)
283298
}
284299

285300
/** @brief Decode a CALL message */
286-
bool RpcBase::decodeCall(const std::string& unique_id, const rapidjson::Value& action, const rapidjson::Value& payload)
301+
bool RpcBase::decodeCall(const std::string& unique_id,
302+
rapidjson::Document& rpc_frame,
303+
const rapidjson::Value& action,
304+
rapidjson::Value& payload)
287305
{
288306
bool ret = false;
289307

290308
// Check types
291309
if (action.IsString() && payload.IsObject())
292310
{
293311
// Add request to the queue
294-
RpcMessage* msg = new RpcMessage(unique_id, action.GetString(), payload);
312+
RpcMessage* msg = new RpcMessage(unique_id, action.GetString(), rpc_frame, payload);
295313
m_requests_queue.push(msg);
296314

297315
ret = true;
@@ -301,15 +319,15 @@ bool RpcBase::decodeCall(const std::string& unique_id, const rapidjson::Value& a
301319
}
302320

303321
/** @brief Decode a CALLRESULT message */
304-
bool RpcBase::decodeCallResult(const std::string& unique_id, const rapidjson::Value& payload)
322+
bool RpcBase::decodeCallResult(const std::string& unique_id, rapidjson::Document& rpc_frame, rapidjson::Value& payload)
305323
{
306324
bool ret = false;
307325

308326
// Check types
309327
if (payload.IsObject())
310328
{
311329
// Add result to the queue
312-
RpcMessage* msg = new RpcMessage(unique_id, payload);
330+
RpcMessage* msg = new RpcMessage(unique_id, rpc_frame, payload);
313331
m_results_queue.push(msg);
314332

315333
ret = true;
@@ -319,17 +337,21 @@ bool RpcBase::decodeCallResult(const std::string& unique_id, const rapidjson::Va
319337
}
320338

321339
/** @brief Decode a CALLERROR message */
322-
bool RpcBase::decodeCallError(const std::string& unique_id,
323-
const rapidjson::Value& error,
324-
const rapidjson::Value& message,
325-
const rapidjson::Value& payload)
340+
bool RpcBase::decodeCallError(const std::string& unique_id,
341+
rapidjson::Document& rpc_frame,
342+
rapidjson::Value& error,
343+
rapidjson::Value& message,
344+
rapidjson::Value& payload)
326345
{
327346
bool ret = false;
328347

329348
// Check types
330349
if (error.IsString() && message.IsString() && payload.IsObject())
331350
{
332-
(void)unique_id;
351+
// Add error to the queue
352+
RpcMessage* msg = new RpcMessage(unique_id, rpc_frame, payload, &error, &message);
353+
m_results_queue.push(msg);
354+
333355
ret = true;
334356
}
335357

src/rpc/RpcBase.h

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,14 @@ class RpcBase : public IRpc
4444

4545
// IRpc interface
4646

47-
/** @copydoc bool IRpc::call(const std::string&, const rapidjson::Document&, rapidjson::Document&, std::chrono::milliseconds) */
47+
/** @copydoc bool IRpc::call(const std::string&, const rapidjson::Document&, rapidjson::Document&, rapidjson::Value&,
48+
* std::string&, std::string&, std::chrono::milliseconds) */
4849
bool call(const std::string& action,
4950
const rapidjson::Document& payload,
50-
rapidjson::Document& response,
51+
rapidjson::Document& rpc_frame,
52+
rapidjson::Value& response,
53+
std::string& error,
54+
std::string& message,
5155
std::chrono::milliseconds timeout = std::chrono::seconds(2)) override;
5256

5357
/** @copydoc void IRpc::registerListener(IListener&) */
@@ -86,18 +90,34 @@ class RpcBase : public IRpc
8690
/** @brief RPC message */
8791
struct RpcMessage
8892
{
89-
RpcMessage(const std::string& _unique_id, const char* _action, const rapidjson::Value& _payload)
90-
: unique_id(_unique_id), action(_action), payload()
93+
RpcMessage(const std::string& _unique_id, const char* _action, rapidjson::Document& _rpc_frame, rapidjson::Value& _payload)
94+
: unique_id(_unique_id), action(_action), rpc_frame(std::move(_rpc_frame)), payload(), error(), message()
9195
{
92-
payload.CopyFrom(_payload, payload.GetAllocator());
96+
payload.Swap(_payload);
9397
}
94-
RpcMessage(const std::string& _unique_id, const rapidjson::Value& _payload) : unique_id(_unique_id), action(), payload()
98+
RpcMessage(const std::string& _unique_id,
99+
rapidjson::Document& _rpc_frame,
100+
rapidjson::Value& _payload,
101+
rapidjson::Value* _error = nullptr,
102+
rapidjson::Value* _message = nullptr)
103+
: unique_id(_unique_id), action(), rpc_frame(std::move(_rpc_frame)), payload(), error(), message()
95104
{
96-
payload.CopyFrom(_payload, payload.GetAllocator());
105+
payload.Swap(_payload);
106+
if (_error)
107+
{
108+
error.Swap(*_error);
109+
}
110+
if (_message)
111+
{
112+
message.Swap(*_message);
113+
}
97114
}
98115
const std::string unique_id;
99116
const std::string action;
100-
rapidjson::Document payload;
117+
rapidjson::Document rpc_frame;
118+
rapidjson::Value payload;
119+
rapidjson::Value error;
120+
rapidjson::Value message;
101121
};
102122

103123
/** @brief RPC listener */
@@ -119,16 +139,20 @@ class RpcBase : public IRpc
119139
bool send(const std::string& msg);
120140

121141
/** @brief Decode a CALL message */
122-
bool decodeCall(const std::string& unique_id, const rapidjson::Value& action, const rapidjson::Value& payload);
142+
bool decodeCall(const std::string& unique_id,
143+
rapidjson::Document& rpc_frame,
144+
const rapidjson::Value& action,
145+
rapidjson::Value& payload);
123146

124147
/** @brief Decode a CALLRESULT message */
125-
bool decodeCallResult(const std::string& unique_id, const rapidjson::Value& payload);
148+
bool decodeCallResult(const std::string& unique_id, rapidjson::Document& rpc_frame, rapidjson::Value& payload);
126149

127150
/** @brief Decode a CALLERROR message */
128-
bool decodeCallError(const std::string& unique_id,
129-
const rapidjson::Value& error,
130-
const rapidjson::Value& message,
131-
const rapidjson::Value& payload);
151+
bool decodeCallError(const std::string& unique_id,
152+
rapidjson::Document& rpc_frame,
153+
rapidjson::Value& error,
154+
rapidjson::Value& message,
155+
rapidjson::Value& payload);
132156

133157
/** @brief Send a CALLERROR message */
134158
void sendCallError(const std::string& unique_id, const char* error, const std::string& message);

0 commit comments

Comments
 (0)