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