• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "protocol_handler.h"
17 
18 #include "agent/debugger_impl.h"
19 
20 namespace panda::ecmascript::tooling {
WaitForDebugger()21 void ProtocolHandler::WaitForDebugger()
22 {
23     waitingForDebugger_ = true;
24     ProcessCommand();
25 }
26 
RunIfWaitingForDebugger()27 void ProtocolHandler::RunIfWaitingForDebugger()
28 {
29     waitingForDebugger_ = false;
30 }
31 
DispatchCommand(std::string && msg)32 void ProtocolHandler::DispatchCommand(std::string &&msg)
33 {
34     LOG_DEBUGGER(DEBUG) << "ProtocolHandler::DispatchCommand: " << msg;
35     std::unique_lock<std::mutex> queueLock(requestLock_);
36     requestQueue_.push(std::move(msg));
37     requestQueueCond_.notify_one();
38 }
39 
40 // called after DispatchCommand
GetDispatchStatus()41 int32_t ProtocolHandler::GetDispatchStatus()
42 {
43     if (isDispatchingMessage_ || waitingForDebugger_) {
44         return DispatchStatus::DISPATCHING;
45     }
46     std::unique_lock<std::mutex> queueLock(requestLock_);
47     if (requestQueue_.empty()) {
48         return DispatchStatus::DISPATCHED;
49     }
50     return DispatchStatus::UNKNOWN;
51 }
52 
ProcessCommand()53 void ProtocolHandler::ProcessCommand()
54 {
55     std::queue<std::string> dispatchingQueue;
56     do {
57         {
58             std::unique_lock<std::mutex> queueLock(requestLock_);
59             if (requestQueue_.empty()) {
60                 if (!waitingForDebugger_) {
61                     return;
62                 }
63                 requestQueueCond_.wait(queueLock);
64             }
65             requestQueue_.swap(dispatchingQueue);
66         }
67 
68         isDispatchingMessage_ = true;
69         while (!dispatchingQueue.empty()) {
70             std::string msg = std::move(dispatchingQueue.front());
71             dispatchingQueue.pop();
72 
73             [[maybe_unused]] LocalScope scope(vm_);
74             auto exception = DebuggerApi::GetAndClearException(vm_);
75             dispatcher_.Dispatch(DispatchRequest(msg));
76             DebuggerApi::SetException(vm_, exception);
77         }
78         isDispatchingMessage_ = false;
79     } while (true);
80 }
81 
SendResponse(const DispatchRequest & request,const DispatchResponse & response,const PtBaseReturns & result)82 void ProtocolHandler::SendResponse(const DispatchRequest &request, const DispatchResponse &response,
83     const PtBaseReturns &result)
84 {
85     LOG_DEBUGGER(INFO) << "ProtocolHandler::SendResponse: "
86                         << (response.IsOk() ? "success" : "failed: " + response.GetMessage());
87 
88     std::unique_ptr<PtJson> reply = PtJson::CreateObject();
89     reply->Add("id", request.GetCallId());
90     std::unique_ptr<PtJson> resultObj;
91     if (response.IsOk()) {
92         resultObj = result.ToJson();
93     } else {
94         resultObj = CreateErrorReply(response);
95     }
96     reply->Add("result", resultObj);
97     SendReply(*reply);
98     reply->ReleaseRoot();
99 }
100 
SendNotification(const PtBaseEvents & events)101 void ProtocolHandler::SendNotification(const PtBaseEvents &events)
102 {
103     LOG_DEBUGGER(DEBUG) << "ProtocolHandler::SendNotification: " << events.GetName();
104     std::unique_ptr<PtJson> reply = events.ToJson();
105     SendReply(*reply);
106     reply->ReleaseRoot();
107 }
108 
SendReply(const PtJson & reply)109 void ProtocolHandler::SendReply(const PtJson &reply)
110 {
111     std::string str = reply.Stringify();
112     if (str.empty()) {
113         LOG_DEBUGGER(ERROR) << "ProtocolHandler::SendReply: json stringify error";
114         return;
115     }
116 
117     callback_(reinterpret_cast<const void *>(vm_), str);
118 }
119 
CreateErrorReply(const DispatchResponse & response)120 std::unique_ptr<PtJson> ProtocolHandler::CreateErrorReply(const DispatchResponse &response)
121 {
122     std::unique_ptr<PtJson> result = PtJson::CreateObject();
123 
124     if (!response.IsOk()) {
125         result->Add("code", static_cast<int32_t>(response.GetError()));
126         result->Add("message", response.GetMessage().c_str());
127     }
128 
129     return result;
130 }
131 }  // namespace panda::ecmascript::tooling
132