• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_TOOLING_INSPECTOR_ENDPOINT_H
17 #define PANDA_TOOLING_INSPECTOR_ENDPOINT_H
18 
19 #include "macros.h"
20 #include "utils/json_builder.h"
21 #include "utils/logger.h"
22 
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wshadow"
25 #include "websocketpp/common/connection_hdl.hpp"
26 #include "websocketpp/frame.hpp"
27 #pragma GCC diagnostic pop
28 
29 #include <functional>
30 #include <optional>
31 #include <string>
32 #include <unordered_map>
33 #include <utility>
34 
35 namespace panda {
36 class JsonObject;
37 }  // namespace panda
38 
39 namespace panda::tooling::inspector {
40 class EndpointBase {
41 public:
42     using Id = double;
43 
44 private:
45     using MethodHandler = std::function<void(std::optional<Id>, const JsonObject &params)>;
46     using ResultHandler = std::function<void(const JsonObject &)>;
47 
48 public:
OnCall(const char * method,MethodHandler && handler)49     void OnCall(const char *method, MethodHandler &&handler)
50     {
51         methodHandlers_[method] = std::move(handler);
52     }
53 
54 protected:
55     void HandleMessage(const std::string &message);
56 
OnResult(Id id,ResultHandler && handler)57     void OnResult(Id id, ResultHandler &&handler)
58     {
59         resultHandlers_[id] = std::move(handler);
60     }
61 
62 private:
63     std::unordered_map<std::string, MethodHandler> methodHandlers_;
64     std::unordered_map<Id, ResultHandler> resultHandlers_;
65 };
66 
67 // JSON-RPC endpoint handling the Inspector protocol.
68 template <typename WsEndpoint>
69 class Endpoint : public EndpointBase {
70 public:
Endpoint()71     Endpoint()
72     {
73         endpoint_.set_message_handler([this](auto /* hdl */, auto message) { HandleMessage(message->get_payload()); });
74     }
75 
76 protected:
77     void Call(
78         std::optional<Id> id, const char *method,
79         std::function<void(JsonObjectBuilder &)> &&params = [](JsonObjectBuilder & /* builder */) {})
80     {
81         Send([id, method, &params](JsonObjectBuilder &call) {
82             if (id) {
83                 call.AddProperty("id", *id);
84             }
85 
86             call.AddProperty("method", method);
87             call.AddProperty("params", std::move(params));
88         });
89     }
90 
91     template <typename Result>
Reply(Id id,Result && result)92     void Reply(Id id, Result &&result)
93     {
94         Send([id, &result](JsonObjectBuilder &reply) {
95             reply.AddProperty("id", id);
96             reply.AddProperty("result", std::forward<Result>(result));
97         });
98     }
99 
GetPinnedConnection()100     typename WsEndpoint::connection_ptr GetPinnedConnection()
101     {
102         ASSERT_PRINT(connection_, "No pinned connection");
103         return connection_;
104     }
105 
Pin(const websocketpp::connection_hdl & hdl)106     bool Pin(const websocketpp::connection_hdl &hdl)
107     {
108         if (connection_) {
109             return false;
110         }
111 
112         connection_ = endpoint_.get_con_from_hdl(hdl);
113         return true;
114     }
115 
Unpin(const websocketpp::connection_hdl & hdl)116     void Unpin(const websocketpp::connection_hdl &hdl)
117     {
118         (void)hdl;
119         CHECK_EQ(hdl.lock(), connection_);
120         connection_.reset();
121     }
122 
123     WsEndpoint endpoint_;  // NOLINT(misc-non-private-member-variables-in-classes)
124 
125 private:
126     template <typename BuildFunction>
Send(BuildFunction && build)127     void Send(BuildFunction &&build)
128     {
129         JsonObjectBuilder builder;
130         build(builder);
131         auto message = std::move(builder).Build();
132         LOG(DEBUG, DEBUGGER) << "Sending " << message;
133         GetPinnedConnection()->send(message, websocketpp::frame::opcode::text);
134     }
135 
136     typename WsEndpoint::connection_ptr connection_;
137 };
138 }  // namespace panda::tooling::inspector
139 
140 #endif  // PANDA_TOOLING_INSPECTOR_ENDPOINT_H
141