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 ¶ms)>; 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 &)> &¶ms = [](JsonObjectBuilder & /* builder */) {}) 80 { 81 Send([id, method, ¶ms](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