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