-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
jsonrpccomm.hpp
147 lines (118 loc) · 6.76 KB
/
jsonrpccomm.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// SPDX-License-Identifier: GPL-3.0-or-later
//
// Copyright (c) 2013-2023 plan44.ch / Lukas Zeller, Zurich, Switzerland
//
// Author: Lukas Zeller <[email protected]>
//
// This file is part of p44utils.
//
// p44utils is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// p44utils is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with p44utils. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef __p44utils__jsonrpccomm__
#define __p44utils__jsonrpccomm__
#include "jsoncomm.hpp"
using namespace std;
namespace p44 {
class JsonRpcError : public Error
{
public:
enum {
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603,
ServerError = -32000,
ServerErrorMax = -32099
};
typedef int32_t ErrorCodes;
static const char *domain() { return "JsonRPC"; }
virtual const char *getErrorDomain() const P44_OVERRIDE { return JsonRpcError::domain(); };
JsonRpcError(ErrorCode aError) : Error(aError) {};
#if ENABLE_NAMED_ERRORS
protected:
virtual const char* errorName() const P44_OVERRIDE;
#endif // ENABLE_NAMED_ERRORS
};
class JsonRpcComm;
/// callback for delivering a received JSON-RPC method or notification request
/// @param aMethod If this is a method call, this is the JSON-RPC (2.0) method or notification requested by the peer.
/// @param aJsonRpcId the client id. The handler must use this id when calling sendResult(). If this is a notification request, aJsonRpcId is NULL.
typedef boost::function<void (const char *aMethod, const JsonObjectPtr aJsonRpcId, JsonObjectPtr aParams)> JsonRpcRequestCB;
/// callback for delivering a received JSON-RPC method result
/// @param aResponseId the response Id (always integer for requests we send, as the id originates from us)
/// @param aError the referenced ErrorPtr will be set when an error occurred.
/// If the error returned is an JsonRpcError, aError.getErrorCode() will return the "code" member from the JSON-RPC error object,
/// and aError.description() will return the "message" member from the JSON-RPC error object.
/// aResultOrErrorData will contain the "data" member from the JSON-RPC error object, if any.
/// @param aResultOrErrorData the result object in case of success, or the "data" member from the JSON-RPC error object
/// in case of an error returned via JSON-RPC from the remote peer.
typedef boost::function<void (int32_t aResponseId, ErrorPtr &aError, JsonObjectPtr aResultOrErrorData)> JsonRpcResponseCB;
typedef boost::intrusive_ptr<JsonRpcComm> JsonRpcCommPtr;
/// A class providing low level access to the DALI bus
class JsonRpcComm : public JsonComm
{
typedef JsonComm inherited;
JsonRpcRequestCB jsonRequestHandler;
int32_t requestIdCounter;
bool reportAllErrors;
typedef map<int32_t, JsonRpcResponseCB> PendingAnswerMap;
PendingAnswerMap pendingAnswers;
public:
JsonRpcComm(MainLoop &aMainLoop = MainLoop::currentMainLoop());
virtual ~JsonRpcComm();
/// install callback for received JSON-RPC requests
/// @param aJsonRpcRequestHandler will be called when a JSON-RPC request has been received
void setRequestHandler(JsonRpcRequestCB aJsonRpcRequestHandler);
/// If reportAllErrors is set, all errors generated by incoming data will be reported back to the
/// sender (including JSON parsing and JSON-RPC syntax errors in responses).
/// If not set, only errors generated by actual JSON-RPC method calls will be reported
/// @param aReportAllErrors set to report all errors (default is false).
void setReportAllErrors(bool aReportAllErrors) { reportAllErrors = aReportAllErrors; };
/// send a JSON-RPC request
/// @param aMethod the JSON-RPC (2.0) method or notification request to be sent
/// @param aParams the parameters for the method or notification request as a JsonObject. Can be nullptr.
/// @param aResponseHandler if the request is a method call, this handler will be called when the method result arrives
/// Note that the aResponseHandler might not be called at all in case of lost messages etc. So do not rely on
/// this callback for chaining an execution thread.
/// @return empty or Error object in case of error
ErrorPtr sendRequest(const char *aMethod, JsonObjectPtr aParams, JsonRpcResponseCB aResponseHandler = NoOP);
/// @return Id generated for last sendRequest.
int32_t lastRequestId() { return requestIdCounter; };
/// send a JSON-RPC result (answer for successful method call)
/// @param aJsonRpcId this must be the aJsonRpcId as received in the JsonRpcRequestCB handler.
/// @param aResult the result as a JsonObject. Can be nullptr for procedure calls without return value
/// @result empty or Error object in case of error sending result response
ErrorPtr sendResult(const JsonObjectPtr aJsonRpcId, JsonObjectPtr aResult);
/// send a JSON-RPC error (answer for unsuccesful method call)
/// @param aJsonRpcId this must be the aJsonRpcId as received in the JsonRpcRequestCB handler.
/// @param aErrorCode the error code
/// @param aErrorMessage the error message or NULL to generate a standard text
/// @param aErrorData the optional "data" member for the JSON-RPC error object
/// @result empty or Error object in case of error sending error response
ErrorPtr sendError(const JsonObjectPtr aJsonRpcId, int32_t aErrorCode, const char *aErrorMessage = NULL, JsonObjectPtr aErrorData = JsonObjectPtr());
/// send p44utils::Error object as JSON-RPC error
/// @param aJsonRpcId this must be the aJsonRpcId as received in the JsonRpcRequestCB handler.
/// @param aErrorToSend From this error object, getErrorCode() and description() will be used as "code" and "message" members
/// of the JSON-RPC 2.0 error object.
/// @result empty or Error object in case of error sending error response
ErrorPtr sendError(const JsonObjectPtr aJsonRpcId, ErrorPtr aErrorToSend);
/// clear all callbacks
/// @note this is important because handlers might cause retain cycles when they have smart ptr arguments
virtual void clearCallbacks() { jsonRequestHandler = NoOP; inherited::clearCallbacks(); }
private:
void gotJson(ErrorPtr aError, JsonObjectPtr aJsonObject);
};
} // namespace p44
#endif /* defined(__p44utils__jsonrpccomm__) */