1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci */
15cc290419Sopenharmony_ci#include "daemon_forward.h"
16cc290419Sopenharmony_ci#include <cstdint>
17cc290419Sopenharmony_ci#include "securec.h"
18cc290419Sopenharmony_ci#include "daemon.h"
19cc290419Sopenharmony_ci#include "jdwp.h"
20cc290419Sopenharmony_ci
21cc290419Sopenharmony_cinamespace Hdc {
22cc290419Sopenharmony_ciHdcDaemonForward::HdcDaemonForward(HTaskInfo hTaskInfo)
23cc290419Sopenharmony_ci    : HdcForwardBase(hTaskInfo)
24cc290419Sopenharmony_ci{
25cc290419Sopenharmony_ci}
26cc290419Sopenharmony_ci
27cc290419Sopenharmony_ciHdcDaemonForward::~HdcDaemonForward()
28cc290419Sopenharmony_ci{
29cc290419Sopenharmony_ci}
30cc290419Sopenharmony_ci
31cc290419Sopenharmony_civoid HdcDaemonForward::SetupJdwpPointCallBack(uv_idle_t *handle)
32cc290419Sopenharmony_ci{
33cc290419Sopenharmony_ci    HCtxForward ctxPoint = (HCtxForward)handle->data;
34cc290419Sopenharmony_ci    uint32_t id = ctxPoint->id;
35cc290419Sopenharmony_ci    HdcDaemonForward *thisClass = reinterpret_cast<HdcDaemonForward *>(ctxPoint->thisClass);
36cc290419Sopenharmony_ci    thisClass->SetupPointContinue(ctxPoint, 1);  // It usually works
37cc290419Sopenharmony_ci    Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback);
38cc290419Sopenharmony_ci    --thisClass->refCount;
39cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "SetupJdwpPointCallBack finish id:%u", id);
40cc290419Sopenharmony_ci    return;
41cc290419Sopenharmony_ci}
42cc290419Sopenharmony_ci
43cc290419Sopenharmony_cibool HdcDaemonForward::SetupJdwpPoint(HCtxForward ctxPoint)
44cc290419Sopenharmony_ci{
45cc290419Sopenharmony_ci    HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass;
46cc290419Sopenharmony_ci    HdcJdwp *clsJdwp = (HdcJdwp *)daemon->clsJdwp;
47cc290419Sopenharmony_ci    uint32_t pid = std::stol(ctxPoint->localArgs[1]);
48cc290419Sopenharmony_ci    if (ctxPoint->checkPoint) {
49cc290419Sopenharmony_ci        uint32_t id = ctxPoint->id;
50cc290419Sopenharmony_ci        bool ret = clsJdwp->CheckPIDExist(pid);
51cc290419Sopenharmony_ci        SetupPointContinue(ctxPoint, (int)ret);
52cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Jdwp jump checkpoint id:%u", id);
53cc290419Sopenharmony_ci        return true;
54cc290419Sopenharmony_ci    }
55cc290419Sopenharmony_ci    // do slave connect
56cc290419Sopenharmony_ci    // fd[0] for forward, fd[1] for jdwp
57cc290419Sopenharmony_ci    // forward to close fd[0], fd[1] for jdwp close
58cc290419Sopenharmony_ci    int fds[2] = { 0 };
59cc290419Sopenharmony_ci    bool ret = false;
60cc290419Sopenharmony_ci    Base::CreateSocketPair(fds);
61cc290419Sopenharmony_ci    if (uv_tcp_init(loopTask, &ctxPoint->tcp)) {
62cc290419Sopenharmony_ci        return ret;
63cc290419Sopenharmony_ci    }
64cc290419Sopenharmony_ci    ctxPoint->tcp.data = ctxPoint;
65cc290419Sopenharmony_ci    if (uv_tcp_open(&ctxPoint->tcp, fds[0])) {
66cc290419Sopenharmony_ci        return ret;
67cc290419Sopenharmony_ci    }
68cc290419Sopenharmony_ci    constexpr auto len = sizeof(uint32_t);
69cc290419Sopenharmony_ci    uint8_t flag[1 + len + len];
70cc290419Sopenharmony_ci    flag[0] = SP_JDWP_NEWFD;
71cc290419Sopenharmony_ci    if (memcpy_s(flag + 1, sizeof(flag) - 1, &pid, len) ||
72cc290419Sopenharmony_ci        memcpy_s(flag + 1 + len, sizeof(flag) - len - 1, &fds[1], len)) {
73cc290419Sopenharmony_ci        return ret;
74cc290419Sopenharmony_ci    }
75cc290419Sopenharmony_ci    if (ThreadCtrlCommunicate(flag, sizeof(flag)) > 0) {
76cc290419Sopenharmony_ci        ret = true;
77cc290419Sopenharmony_ci    }
78cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD Finish,ret:%d fd0:%d fd1:%d", ret, fds[0], fds[1]);
79cc290419Sopenharmony_ci    if (!ret) {
80cc290419Sopenharmony_ci        Base::CloseSocketPair(fds);
81cc290419Sopenharmony_ci        return ret;
82cc290419Sopenharmony_ci    }
83cc290419Sopenharmony_ci
84cc290419Sopenharmony_ci    ++refCount;
85cc290419Sopenharmony_ci    Base::IdleUvTask(loopTask, ctxPoint, SetupJdwpPointCallBack);
86cc290419Sopenharmony_ci    return ret;
87cc290419Sopenharmony_ci}
88cc290419Sopenharmony_ci
89cc290419Sopenharmony_cibool HdcDaemonForward::SetupArkPoint(HCtxForward ctxPoint)
90cc290419Sopenharmony_ci{
91cc290419Sopenharmony_ci    HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass;
92cc290419Sopenharmony_ci    HdcJdwp *clsJdwp = (HdcJdwp *)daemon->clsJdwp;
93cc290419Sopenharmony_ci    std::string ark = ctxPoint->localArgs[0]; // ark
94cc290419Sopenharmony_ci    std::string svr = ctxPoint->localArgs[1]; // pid@tid@Debugger
95cc290419Sopenharmony_ci    std::size_t found = svr.find_first_of("@");
96cc290419Sopenharmony_ci    if (found == std::string::npos) {
97cc290419Sopenharmony_ci        SetupPointContinue(ctxPoint, true);
98cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "SetupArkPoint failed id:%s", svr.c_str());
99cc290419Sopenharmony_ci        ctxPoint->lastError = ark + ":" + svr + " parameter invalid";
100cc290419Sopenharmony_ci        return false;
101cc290419Sopenharmony_ci    }
102cc290419Sopenharmony_ci    std::string pidstr = svr.substr(0, found);
103cc290419Sopenharmony_ci    uint32_t pid = static_cast<uint32_t>(std::atoi(pidstr.c_str()));
104cc290419Sopenharmony_ci    bool ret = clsJdwp->CheckPIDExist(pid);
105cc290419Sopenharmony_ci    if (!ret) {
106cc290419Sopenharmony_ci        SetupPointContinue(ctxPoint, (int)ret);
107cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "SetupArkPoint failed pid:%u not exist", pid);
108cc290419Sopenharmony_ci        ctxPoint->lastError = ark + ":" + svr + " pid invalid";
109cc290419Sopenharmony_ci        return false;
110cc290419Sopenharmony_ci    }
111cc290419Sopenharmony_ci    // do slave connect
112cc290419Sopenharmony_ci    // fd[0] for forward, fd[1] for ark
113cc290419Sopenharmony_ci    ret = false;
114cc290419Sopenharmony_ci    Base::CreateSocketPair(fds);
115cc290419Sopenharmony_ci    std::string str = ark + ":" + svr;
116cc290419Sopenharmony_ci    uint32_t size = 1 + sizeof(int32_t) + str.size();
117cc290419Sopenharmony_ci    uint8_t buf[size];
118cc290419Sopenharmony_ci    buf[0] = SP_ARK_NEWFD;
119cc290419Sopenharmony_ci    if (memcpy_s(buf + 1, sizeof(int32_t), &fds[1], sizeof(int32_t)) ||
120cc290419Sopenharmony_ci        memcpy_s(buf + 1 + sizeof(int32_t), str.size(), str.c_str(), str.size())) {
121cc290419Sopenharmony_ci        Base::CloseSocketPair(fds);
122cc290419Sopenharmony_ci        return ret;
123cc290419Sopenharmony_ci    }
124cc290419Sopenharmony_ci    // buf: SP_ARK_NEWFD | fd[1] | pid@tid@Debugger
125cc290419Sopenharmony_ci    if (ThreadCtrlCommunicate(buf, size) > 0) {
126cc290419Sopenharmony_ci        ret = true;
127cc290419Sopenharmony_ci    }
128cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "SetupArkPoint Finish,ret:%d fd0:%d fd1:%d", ret, fds[0], fds[1]);
129cc290419Sopenharmony_ci    if (!ret) {
130cc290419Sopenharmony_ci        Base::CloseSocketPair(fds);
131cc290419Sopenharmony_ci        return ret;
132cc290419Sopenharmony_ci    }
133cc290419Sopenharmony_ci    ++refCount;
134cc290419Sopenharmony_ci    Base::IdleUvTask(loopTask, ctxPoint, SetupJdwpPointCallBack);
135cc290419Sopenharmony_ci    return ret;
136cc290419Sopenharmony_ci}
137cc290419Sopenharmony_ci}
138