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 "forward.h"
16cc290419Sopenharmony_ci#include "base.h"
17cc290419Sopenharmony_ci
18cc290419Sopenharmony_cinamespace Hdc {
19cc290419Sopenharmony_ciHdcForwardBase::HdcForwardBase(HTaskInfo hTaskInfo)
20cc290419Sopenharmony_ci    : HdcTaskBase(hTaskInfo)
21cc290419Sopenharmony_ci{
22cc290419Sopenharmony_ci    fds[0] = -1;
23cc290419Sopenharmony_ci    fds[1] = -1;
24cc290419Sopenharmony_ci}
25cc290419Sopenharmony_ci
26cc290419Sopenharmony_ciHdcForwardBase::~HdcForwardBase()
27cc290419Sopenharmony_ci{
28cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "~HdcForwardBase channelId:%u", taskInfo->channelId);
29cc290419Sopenharmony_ci};
30cc290419Sopenharmony_ci
31cc290419Sopenharmony_cibool HdcForwardBase::ReadyForRelease()
32cc290419Sopenharmony_ci{
33cc290419Sopenharmony_ci    if (!HdcTaskBase::ReadyForRelease()) {
34cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "not ready for release channelId:%u", taskInfo->channelId);
35cc290419Sopenharmony_ci        return false;
36cc290419Sopenharmony_ci    }
37cc290419Sopenharmony_ci    return true;
38cc290419Sopenharmony_ci}
39cc290419Sopenharmony_ci
40cc290419Sopenharmony_civoid HdcForwardBase::StopTask()
41cc290419Sopenharmony_ci{
42cc290419Sopenharmony_ci    ctxPointMutex.lock();
43cc290419Sopenharmony_ci    vector<HCtxForward> ctxs;
44cc290419Sopenharmony_ci    map<uint32_t, HCtxForward>::iterator iter;
45cc290419Sopenharmony_ci    for (iter = mapCtxPoint.begin(); iter != mapCtxPoint.end(); ++iter) {
46cc290419Sopenharmony_ci        HCtxForward ctx = iter->second;
47cc290419Sopenharmony_ci        ctxs.push_back(ctx);
48cc290419Sopenharmony_ci    }
49cc290419Sopenharmony_ci    // FREECONTEXT in the STOP is triggered by the other party sector, no longer notifying each other.
50cc290419Sopenharmony_ci    mapCtxPoint.clear();
51cc290419Sopenharmony_ci    ctxPointMutex.unlock();
52cc290419Sopenharmony_ci    for (auto ctx: ctxs) {
53cc290419Sopenharmony_ci        FreeContext(ctx, 0, false);
54cc290419Sopenharmony_ci    }
55cc290419Sopenharmony_ci}
56cc290419Sopenharmony_ci
57cc290419Sopenharmony_civoid HdcForwardBase::OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client)
58cc290419Sopenharmony_ci{
59cc290419Sopenharmony_ci    HCtxForward ctxListen = (HCtxForward)server->data;
60cc290419Sopenharmony_ci    char buf[BUF_SIZE_DEFAULT] = { 0 };
61cc290419Sopenharmony_ci    bool ret = false;
62cc290419Sopenharmony_ci    while (true) {
63cc290419Sopenharmony_ci        if (uv_accept(server, client)) {
64cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "uv_accept id:%u type:%d remoteParamenters:%s",
65cc290419Sopenharmony_ci                ctxListen->id, ctxListen->type, ctxListen->remoteParamenters.c_str());
66cc290419Sopenharmony_ci            break;
67cc290419Sopenharmony_ci        }
68cc290419Sopenharmony_ci        ctxClient->type = ctxListen->type;
69cc290419Sopenharmony_ci        ctxClient->remoteParamenters = ctxListen->remoteParamenters;
70cc290419Sopenharmony_ci        int maxSize = sizeof(buf) - forwardParameterBufSize;
71cc290419Sopenharmony_ci        // clang-format off
72cc290419Sopenharmony_ci        if (snprintf_s(buf + forwardParameterBufSize, maxSize, maxSize - 1, "%s",
73cc290419Sopenharmony_ci                       ctxClient->remoteParamenters.c_str()) < 0) {
74cc290419Sopenharmony_ci            break;
75cc290419Sopenharmony_ci        }
76cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "OnAccept id:%u type:%d remoteParamenters:%s",
77cc290419Sopenharmony_ci            ctxClient->id, ctxClient->type, ctxClient->remoteParamenters.c_str());
78cc290419Sopenharmony_ci        SendToTask(ctxClient->id, CMD_FORWARD_ACTIVE_SLAVE, reinterpret_cast<uint8_t *>(buf),
79cc290419Sopenharmony_ci                   strlen(buf + forwardParameterBufSize) + 9); // 9: pre 8bytes preserve for param bits
80cc290419Sopenharmony_ci        ret = true;
81cc290419Sopenharmony_ci        break;
82cc290419Sopenharmony_ci    }
83cc290419Sopenharmony_ci    if (!ret) {
84cc290419Sopenharmony_ci        FreeContext(ctxClient, 0, false);
85cc290419Sopenharmony_ci    }
86cc290419Sopenharmony_ci}
87cc290419Sopenharmony_ci
88cc290419Sopenharmony_civoid HdcForwardBase::ListenCallback(uv_stream_t *server, const int status)
89cc290419Sopenharmony_ci{
90cc290419Sopenharmony_ci    HCtxForward ctxListen = (HCtxForward)server->data;
91cc290419Sopenharmony_ci    HdcForwardBase *thisClass = ctxListen->thisClass;
92cc290419Sopenharmony_ci    uv_stream_t *client = nullptr;
93cc290419Sopenharmony_ci
94cc290419Sopenharmony_ci    if (status == -1 || !ctxListen->ready) {
95cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "ListenCallback status:%d id:%u ready:%d",
96cc290419Sopenharmony_ci            status, ctxListen->id, ctxListen->ready);
97cc290419Sopenharmony_ci        thisClass->FreeContext(ctxListen, 0, false);
98cc290419Sopenharmony_ci        thisClass->TaskFinish();
99cc290419Sopenharmony_ci        return;
100cc290419Sopenharmony_ci    }
101cc290419Sopenharmony_ci    HCtxForward ctxClient = (HCtxForward)thisClass->MallocContext(true);
102cc290419Sopenharmony_ci    if (!ctxClient) {
103cc290419Sopenharmony_ci        return;
104cc290419Sopenharmony_ci    }
105cc290419Sopenharmony_ci    if (ctxListen->type == FORWARD_TCP) {
106cc290419Sopenharmony_ci        uv_tcp_init(ctxClient->thisClass->loopTask, &ctxClient->tcp);
107cc290419Sopenharmony_ci        client = (uv_stream_t *)&ctxClient->tcp;
108cc290419Sopenharmony_ci    } else {
109cc290419Sopenharmony_ci        // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM,
110cc290419Sopenharmony_ci        uv_pipe_init(ctxClient->thisClass->loopTask, &ctxClient->pipe, 0);
111cc290419Sopenharmony_ci        client = (uv_stream_t *)&ctxClient->pipe;
112cc290419Sopenharmony_ci    }
113cc290419Sopenharmony_ci    thisClass->OnAccept(server, ctxClient, client);
114cc290419Sopenharmony_ci}
115cc290419Sopenharmony_ci
116cc290419Sopenharmony_civoid *HdcForwardBase::MallocContext(bool masterSlave)
117cc290419Sopenharmony_ci{
118cc290419Sopenharmony_ci    HCtxForward ctx = nullptr;
119cc290419Sopenharmony_ci    if ((ctx = new ContextForward()) == nullptr) {
120cc290419Sopenharmony_ci        return nullptr;
121cc290419Sopenharmony_ci    }
122cc290419Sopenharmony_ci    ctx->id = Base::GetRandomU32();
123cc290419Sopenharmony_ci    ctx->masterSlave = masterSlave;
124cc290419Sopenharmony_ci    ctx->thisClass = this;
125cc290419Sopenharmony_ci    ctx->fdClass = nullptr;
126cc290419Sopenharmony_ci    ctx->tcp.data = ctx;
127cc290419Sopenharmony_ci    ctx->pipe.data = ctx;
128cc290419Sopenharmony_ci    AdminContext(OP_ADD, ctx->id, ctx);
129cc290419Sopenharmony_ci    refCount++;
130cc290419Sopenharmony_ci    return ctx;
131cc290419Sopenharmony_ci}
132cc290419Sopenharmony_ci
133cc290419Sopenharmony_civoid HdcForwardBase::FreeContextCallBack(HCtxForward ctx)
134cc290419Sopenharmony_ci{
135cc290419Sopenharmony_ci    Base::DoNextLoop(loopTask, ctx, [this](const uint8_t flag, string &msg, const void *data) {
136cc290419Sopenharmony_ci        HCtxForward ctx = (HCtxForward)data;
137cc290419Sopenharmony_ci        AdminContext(OP_REMOVE, ctx->id, nullptr);
138cc290419Sopenharmony_ci        if (ctx != nullptr) {
139cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Finally to delete id:%u", ctx->id);
140cc290419Sopenharmony_ci            delete ctx;
141cc290419Sopenharmony_ci            ctx = nullptr;
142cc290419Sopenharmony_ci        }
143cc290419Sopenharmony_ci        if (refCount > 0) {
144cc290419Sopenharmony_ci            --refCount;
145cc290419Sopenharmony_ci        }
146cc290419Sopenharmony_ci    });
147cc290419Sopenharmony_ci}
148cc290419Sopenharmony_ci
149cc290419Sopenharmony_civoid HdcForwardBase::FreeJDWP(HCtxForward ctx)
150cc290419Sopenharmony_ci{
151cc290419Sopenharmony_ci    Base::CloseFd(ctx->fd);
152cc290419Sopenharmony_ci    if (ctx->fdClass) {
153cc290419Sopenharmony_ci        ctx->fdClass->StopWorkOnThread(false, nullptr);
154cc290419Sopenharmony_ci
155cc290419Sopenharmony_ci        auto funcReqClose = [](uv_idle_t *handle) -> void {
156cc290419Sopenharmony_ci            uv_close_cb funcIdleHandleClose = [](uv_handle_t *handle) -> void {
157cc290419Sopenharmony_ci                HCtxForward ctx = (HCtxForward)handle->data;
158cc290419Sopenharmony_ci                ctx->thisClass->FreeContextCallBack(ctx);
159cc290419Sopenharmony_ci                delete (uv_idle_t *)handle;
160cc290419Sopenharmony_ci            };
161cc290419Sopenharmony_ci            HCtxForward context = (HCtxForward)handle->data;
162cc290419Sopenharmony_ci            if (context->fdClass->ReadyForRelease()) {
163cc290419Sopenharmony_ci                delete context->fdClass;
164cc290419Sopenharmony_ci                context->fdClass = nullptr;
165cc290419Sopenharmony_ci                Base::TryCloseHandle((uv_handle_t *)handle, funcIdleHandleClose);
166cc290419Sopenharmony_ci            }
167cc290419Sopenharmony_ci        };
168cc290419Sopenharmony_ci        Base::IdleUvTask(loopTask, ctx, funcReqClose);
169cc290419Sopenharmony_ci    }
170cc290419Sopenharmony_ci}
171cc290419Sopenharmony_ci
172cc290419Sopenharmony_civoid HdcForwardBase::FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNotifyRemote)
173cc290419Sopenharmony_ci{
174cc290419Sopenharmony_ci    std::lock_guard<std::mutex> lock(ctxFreeMutex);
175cc290419Sopenharmony_ci    HCtxForward ctx = nullptr;
176cc290419Sopenharmony_ci    if (!ctxIn) {
177cc290419Sopenharmony_ci        if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) {
178cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Query id:%u failed", id);
179cc290419Sopenharmony_ci            return;
180cc290419Sopenharmony_ci        }
181cc290419Sopenharmony_ci    } else {
182cc290419Sopenharmony_ci        ctx = ctxIn;
183cc290419Sopenharmony_ci    }
184cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "FreeContext id:%u, bNotifyRemote:%d, finish:%d",
185cc290419Sopenharmony_ci        ctx->id, bNotifyRemote, ctx->finish);
186cc290419Sopenharmony_ci    if (ctx->finish) {
187cc290419Sopenharmony_ci        return;
188cc290419Sopenharmony_ci    }
189cc290419Sopenharmony_ci    if (bNotifyRemote) {
190cc290419Sopenharmony_ci        SendToTask(ctx->id, CMD_FORWARD_FREE_CONTEXT, nullptr, 0);
191cc290419Sopenharmony_ci    }
192cc290419Sopenharmony_ci    uv_close_cb funcHandleClose = [](uv_handle_t *handle) -> void {
193cc290419Sopenharmony_ci        HCtxForward ctx = (HCtxForward)handle->data;
194cc290419Sopenharmony_ci        ctx->thisClass->FreeContextCallBack(ctx);
195cc290419Sopenharmony_ci    };
196cc290419Sopenharmony_ci    switch (ctx->type) {
197cc290419Sopenharmony_ci        case FORWARD_TCP:
198cc290419Sopenharmony_ci        case FORWARD_JDWP:
199cc290419Sopenharmony_ci        case FORWARD_ARK:
200cc290419Sopenharmony_ci            Base::TryCloseHandle((uv_handle_t *)&ctx->tcp, true, funcHandleClose);
201cc290419Sopenharmony_ci            break;
202cc290419Sopenharmony_ci        case FORWARD_ABSTRACT:
203cc290419Sopenharmony_ci        case FORWARD_RESERVED:
204cc290419Sopenharmony_ci        case FORWARD_FILESYSTEM:
205cc290419Sopenharmony_ci            Base::TryCloseHandle((uv_handle_t *)&ctx->pipe, true, funcHandleClose);
206cc290419Sopenharmony_ci            break;
207cc290419Sopenharmony_ci        case FORWARD_DEVICE: {
208cc290419Sopenharmony_ci            FreeJDWP(ctx);
209cc290419Sopenharmony_ci            break;
210cc290419Sopenharmony_ci        }
211cc290419Sopenharmony_ci        default:
212cc290419Sopenharmony_ci            break;
213cc290419Sopenharmony_ci    }
214cc290419Sopenharmony_ci    ctx->finish = true;
215cc290419Sopenharmony_ci}
216cc290419Sopenharmony_ci
217cc290419Sopenharmony_cibool HdcForwardBase::SendToTask(const uint32_t cid, const uint16_t command, uint8_t *bufPtr, const int bufSize)
218cc290419Sopenharmony_ci{
219cc290419Sopenharmony_ci    StartTraceScope("HdcForwardBase::SendToTask");
220cc290419Sopenharmony_ci    bool ret = false;
221cc290419Sopenharmony_ci    // usually MAX_SIZE_IOBUF*2 from HdcFileDescriptor maxIO
222cc290419Sopenharmony_ci    if (bufSize > Base::GetMaxBufSizeStable() * BUF_MULTIPLE) {
223cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SendToTask bufSize:%d", bufSize);
224cc290419Sopenharmony_ci        return false;
225cc290419Sopenharmony_ci    }
226cc290419Sopenharmony_ci    auto newBuf = new uint8_t[bufSize + BUF_EXTEND_SIZE];
227cc290419Sopenharmony_ci    if (!newBuf) {
228cc290419Sopenharmony_ci        return false;
229cc290419Sopenharmony_ci    }
230cc290419Sopenharmony_ci    *reinterpret_cast<uint32_t *>(newBuf) = htonl(cid);
231cc290419Sopenharmony_ci    if (bufSize > 0 && bufPtr != nullptr && memcpy_s(newBuf + BUF_EXTEND_SIZE, bufSize, bufPtr, bufSize) != EOK) {
232cc290419Sopenharmony_ci        delete[] newBuf;
233cc290419Sopenharmony_ci        return false;
234cc290419Sopenharmony_ci    }
235cc290419Sopenharmony_ci    ret = SendToAnother(command, newBuf, bufSize + BUF_EXTEND_SIZE);
236cc290419Sopenharmony_ci    delete[] newBuf;
237cc290419Sopenharmony_ci    return ret;
238cc290419Sopenharmony_ci}
239cc290419Sopenharmony_ci
240cc290419Sopenharmony_ci// Forward flow is small and frequency is fast
241cc290419Sopenharmony_civoid HdcForwardBase::AllocForwardBuf(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf)
242cc290419Sopenharmony_ci{
243cc290419Sopenharmony_ci    size_t size = sizeSuggested;
244cc290419Sopenharmony_ci    if (size > MAX_USBFFS_BULK) {
245cc290419Sopenharmony_ci        size = MAX_USBFFS_BULK;
246cc290419Sopenharmony_ci    }
247cc290419Sopenharmony_ci    buf->base = (char *)new char[size];
248cc290419Sopenharmony_ci    if (buf->base) {
249cc290419Sopenharmony_ci        buf->len = (size > 0) ? (size - 1) : 0;
250cc290419Sopenharmony_ci    } else {
251cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "AllocForwardBuf == null");
252cc290419Sopenharmony_ci    }
253cc290419Sopenharmony_ci}
254cc290419Sopenharmony_ci
255cc290419Sopenharmony_civoid HdcForwardBase::ReadForwardBuf(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
256cc290419Sopenharmony_ci{
257cc290419Sopenharmony_ci    HCtxForward ctx = (HCtxForward)stream->data;
258cc290419Sopenharmony_ci    if (nread < 0) {
259cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "ReadForwardBuf nread:%zd id:%u", nread, ctx->id);
260cc290419Sopenharmony_ci        ctx->thisClass->FreeContext(ctx, 0, true);
261cc290419Sopenharmony_ci        delete[] buf->base;
262cc290419Sopenharmony_ci        return;
263cc290419Sopenharmony_ci    }
264cc290419Sopenharmony_ci    if (nread == 0) {
265cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "ReadForwardBuf nread:0 id:%u", ctx->id);
266cc290419Sopenharmony_ci        delete[] buf->base;
267cc290419Sopenharmony_ci        return;
268cc290419Sopenharmony_ci    }
269cc290419Sopenharmony_ci    ctx->thisClass->SendToTask(ctx->id, CMD_FORWARD_DATA, (uint8_t *)buf->base, nread);
270cc290419Sopenharmony_ci    // clear
271cc290419Sopenharmony_ci    delete[] buf->base;
272cc290419Sopenharmony_ci}
273cc290419Sopenharmony_ci
274cc290419Sopenharmony_civoid HdcForwardBase::ConnectTarget(uv_connect_t *connection, int status)
275cc290419Sopenharmony_ci{
276cc290419Sopenharmony_ci    HCtxForward ctx = (HCtxForward)connection->data;
277cc290419Sopenharmony_ci    HdcForwardBase *thisClass = ctx->thisClass;
278cc290419Sopenharmony_ci    delete connection;
279cc290419Sopenharmony_ci    if (status < 0) {
280cc290419Sopenharmony_ci        constexpr int bufSize = 1024;
281cc290419Sopenharmony_ci        char buf[bufSize] = { 0 };
282cc290419Sopenharmony_ci        uv_err_name_r(status, buf, bufSize);
283cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "Forward connect result:%d error:%s", status, buf);
284cc290419Sopenharmony_ci    }
285cc290419Sopenharmony_ci    thisClass->SetupPointContinue(ctx, status);
286cc290419Sopenharmony_ci}
287cc290419Sopenharmony_ci
288cc290419Sopenharmony_cibool HdcForwardBase::CheckNodeInfo(const char *nodeInfo, string as[2])
289cc290419Sopenharmony_ci{
290cc290419Sopenharmony_ci    string str = nodeInfo;
291cc290419Sopenharmony_ci    size_t strLen = str.size();
292cc290419Sopenharmony_ci    if (strLen < 1) {
293cc290419Sopenharmony_ci        return false;
294cc290419Sopenharmony_ci    }
295cc290419Sopenharmony_ci    size_t pos = str.find(':');
296cc290419Sopenharmony_ci    if (pos != string::npos) {
297cc290419Sopenharmony_ci        if (pos == 0 || pos == strLen - 1) {
298cc290419Sopenharmony_ci            return false;
299cc290419Sopenharmony_ci        }
300cc290419Sopenharmony_ci        as[0] = str.substr(0, pos);
301cc290419Sopenharmony_ci        as[1] = str.substr(pos + 1);
302cc290419Sopenharmony_ci    } else {
303cc290419Sopenharmony_ci        return false;
304cc290419Sopenharmony_ci    }
305cc290419Sopenharmony_ci    if (as[0] == "tcp") {
306cc290419Sopenharmony_ci        if (as[1].size() > std::to_string(MAX_IP_PORT).size()) {
307cc290419Sopenharmony_ci            return false;
308cc290419Sopenharmony_ci        }
309cc290419Sopenharmony_ci        int port = atoi(as[1].c_str());
310cc290419Sopenharmony_ci        if (port <= 0 || port > MAX_IP_PORT) {
311cc290419Sopenharmony_ci            return false;
312cc290419Sopenharmony_ci        }
313cc290419Sopenharmony_ci    }
314cc290419Sopenharmony_ci    return true;
315cc290419Sopenharmony_ci}
316cc290419Sopenharmony_ci
317cc290419Sopenharmony_cibool HdcForwardBase::SetupPointContinue(HCtxForward ctx, int status)
318cc290419Sopenharmony_ci{
319cc290419Sopenharmony_ci    if (ctx->checkPoint) {
320cc290419Sopenharmony_ci        // send to active
321cc290419Sopenharmony_ci        uint8_t flag = status > 0;
322cc290419Sopenharmony_ci        SendToTask(ctx->id, CMD_FORWARD_CHECK_RESULT, &flag, 1);
323cc290419Sopenharmony_ci        FreeContext(ctx, 0, false);
324cc290419Sopenharmony_ci        return true;
325cc290419Sopenharmony_ci    }
326cc290419Sopenharmony_ci    if (status < 0) {
327cc290419Sopenharmony_ci        FreeContext(ctx, 0, true);
328cc290419Sopenharmony_ci        return false;
329cc290419Sopenharmony_ci    }
330cc290419Sopenharmony_ci    // send to active
331cc290419Sopenharmony_ci    if (!SendToTask(ctx->id, CMD_FORWARD_ACTIVE_MASTER, nullptr, 0)) {
332cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SetupPointContinue SendToTask failed id:%u", ctx->id);
333cc290419Sopenharmony_ci        FreeContext(ctx, 0, true);
334cc290419Sopenharmony_ci        return false;
335cc290419Sopenharmony_ci    }
336cc290419Sopenharmony_ci    return DoForwardBegin(ctx);
337cc290419Sopenharmony_ci}
338cc290419Sopenharmony_ci
339cc290419Sopenharmony_cibool HdcForwardBase::DetechForwardType(HCtxForward ctxPoint)
340cc290419Sopenharmony_ci{
341cc290419Sopenharmony_ci    string &sFType = ctxPoint->localArgs[0];
342cc290419Sopenharmony_ci    string &sNodeCfg = ctxPoint->localArgs[1];
343cc290419Sopenharmony_ci    // string to enum
344cc290419Sopenharmony_ci    if (sFType == "tcp") {
345cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_TCP;
346cc290419Sopenharmony_ci    } else if (sFType == "dev") {
347cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_DEVICE;
348cc290419Sopenharmony_ci    } else if (sFType == "localabstract") {
349cc290419Sopenharmony_ci        // daemon shell: /system/bin/socat abstract-listen:linux-abstract -
350cc290419Sopenharmony_ci        // daemon shell: /system/bin/socat - abstract-connect:linux-abstract
351cc290419Sopenharmony_ci        // host:   hdc fport tcp:8080 localabstract:linux-abstract
352cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_ABSTRACT;
353cc290419Sopenharmony_ci    } else if (sFType == "localreserved") {
354cc290419Sopenharmony_ci        sNodeCfg = harmonyReservedSocketPrefix + sNodeCfg;
355cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_RESERVED;
356cc290419Sopenharmony_ci    } else if (sFType == "localfilesystem") {
357cc290419Sopenharmony_ci        sNodeCfg = filesystemSocketPrefix + sNodeCfg;
358cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_FILESYSTEM;
359cc290419Sopenharmony_ci    } else if (sFType == "jdwp") {
360cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_JDWP;
361cc290419Sopenharmony_ci    } else if (sFType == "ark") {
362cc290419Sopenharmony_ci        ctxPoint->type = FORWARD_ARK;
363cc290419Sopenharmony_ci    } else {
364cc290419Sopenharmony_ci        return false;
365cc290419Sopenharmony_ci    }
366cc290419Sopenharmony_ci    return true;
367cc290419Sopenharmony_ci}
368cc290419Sopenharmony_ci
369cc290419Sopenharmony_cibool HdcForwardBase::SetupTCPPoint(HCtxForward ctxPoint)
370cc290419Sopenharmony_ci{
371cc290419Sopenharmony_ci    string &sNodeCfg = ctxPoint->localArgs[1];
372cc290419Sopenharmony_ci    int port = atoi(sNodeCfg.c_str());
373cc290419Sopenharmony_ci    ctxPoint->tcp.data = ctxPoint;
374cc290419Sopenharmony_ci    uv_tcp_init(loopTask, &ctxPoint->tcp);
375cc290419Sopenharmony_ci    struct sockaddr_in addr;
376cc290419Sopenharmony_ci    if (ctxPoint->masterSlave) {
377cc290419Sopenharmony_ci        uv_ip4_addr("127.0.0.1", port, &addr);  // loop interface
378cc290419Sopenharmony_ci        uv_tcp_bind(&ctxPoint->tcp, (const struct sockaddr *)&addr, 0);
379cc290419Sopenharmony_ci        if (uv_listen((uv_stream_t *)&ctxPoint->tcp, UV_LISTEN_LBACKOG, ListenCallback)) {
380cc290419Sopenharmony_ci            ctxPoint->lastError = "TCP Port listen failed at " + sNodeCfg;
381cc290419Sopenharmony_ci            return false;
382cc290419Sopenharmony_ci        }
383cc290419Sopenharmony_ci    } else {
384cc290419Sopenharmony_ci        uv_ip4_addr("127.0.0.1", port, &addr);  // loop interface
385cc290419Sopenharmony_ci        uv_connect_t *conn = new(std::nothrow) uv_connect_t();
386cc290419Sopenharmony_ci        if (conn == nullptr) {
387cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "SetupTCPPoint new conn failed");
388cc290419Sopenharmony_ci            return false;
389cc290419Sopenharmony_ci        }
390cc290419Sopenharmony_ci        conn->data = ctxPoint;
391cc290419Sopenharmony_ci        uv_tcp_connect(conn, (uv_tcp_t *)&ctxPoint->tcp, (const struct sockaddr *)&addr, ConnectTarget);
392cc290419Sopenharmony_ci    }
393cc290419Sopenharmony_ci    return true;
394cc290419Sopenharmony_ci}
395cc290419Sopenharmony_ci
396cc290419Sopenharmony_cibool HdcForwardBase::SetupDevicePoint(HCtxForward ctxPoint)
397cc290419Sopenharmony_ci{
398cc290419Sopenharmony_ci    uint8_t flag = 1;
399cc290419Sopenharmony_ci    string &sNodeCfg = ctxPoint->localArgs[1];
400cc290419Sopenharmony_ci    string resolvedPath = Base::CanonicalizeSpecPath(sNodeCfg);
401cc290419Sopenharmony_ci    if ((ctxPoint->fd = open(resolvedPath.c_str(), O_RDWR)) < 0) {
402cc290419Sopenharmony_ci        ctxPoint->lastError = "Open unix-dev failed";
403cc290419Sopenharmony_ci        flag = -1;
404cc290419Sopenharmony_ci    }
405cc290419Sopenharmony_ci    auto funcRead = [&](const void *a, uint8_t *b, const int c) -> bool {
406cc290419Sopenharmony_ci        HCtxForward ctx = (HCtxForward)a;
407cc290419Sopenharmony_ci        return SendToTask(ctx->id, CMD_FORWARD_DATA, b, c);
408cc290419Sopenharmony_ci    };
409cc290419Sopenharmony_ci    auto funcFinish = [&](const void *a, const bool b, const string c) -> bool {
410cc290419Sopenharmony_ci        HCtxForward ctx = (HCtxForward)a;
411cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "funcFinish id:%u ret:%d reason:%s", ctx->id, b, c.c_str());
412cc290419Sopenharmony_ci        FreeContext(ctx, 0, true);
413cc290419Sopenharmony_ci        return false;
414cc290419Sopenharmony_ci    };
415cc290419Sopenharmony_ci    ctxPoint->fdClass = new(std::nothrow) HdcFileDescriptor(loopTask, ctxPoint->fd, ctxPoint, funcRead,
416cc290419Sopenharmony_ci                                                            funcFinish, true);
417cc290419Sopenharmony_ci    if (ctxPoint->fdClass == nullptr) {
418cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SetupDevicePoint new ctxPoint->fdClass failed");
419cc290419Sopenharmony_ci        return false;
420cc290419Sopenharmony_ci    }
421cc290419Sopenharmony_ci    SetupPointContinue(ctxPoint, flag);
422cc290419Sopenharmony_ci    return true;
423cc290419Sopenharmony_ci}
424cc290419Sopenharmony_ci
425cc290419Sopenharmony_cibool HdcForwardBase::LocalAbstractConnect(uv_pipe_t *pipe, string &sNodeCfg)
426cc290419Sopenharmony_ci{
427cc290419Sopenharmony_ci    bool abstractRet = false;
428cc290419Sopenharmony_ci#ifndef _WIN32
429cc290419Sopenharmony_ci    int s = 0;
430cc290419Sopenharmony_ci    do {
431cc290419Sopenharmony_ci        if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
432cc290419Sopenharmony_ci            break;
433cc290419Sopenharmony_ci        }
434cc290419Sopenharmony_ci        fcntl(s, F_SETFD, FD_CLOEXEC);
435cc290419Sopenharmony_ci        struct sockaddr_un addr;
436cc290419Sopenharmony_ci        Base::ZeroStruct(addr);
437cc290419Sopenharmony_ci        int addrLen = sNodeCfg.size() + offsetof(struct sockaddr_un, sun_path) + 1;
438cc290419Sopenharmony_ci        addr.sun_family = AF_LOCAL;
439cc290419Sopenharmony_ci        addr.sun_path[0] = 0;
440cc290419Sopenharmony_ci
441cc290419Sopenharmony_ci        if (memcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 1, sNodeCfg.c_str(), sNodeCfg.size()) != EOK) {
442cc290419Sopenharmony_ci            break;
443cc290419Sopenharmony_ci        };
444cc290419Sopenharmony_ci        struct timeval timeout = { 3, 0 };
445cc290419Sopenharmony_ci        setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
446cc290419Sopenharmony_ci        if (connect(s, reinterpret_cast<struct sockaddr *>(&addr), addrLen) < 0) {
447cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "LocalAbstractConnect failed errno:%d", errno);
448cc290419Sopenharmony_ci            break;
449cc290419Sopenharmony_ci        }
450cc290419Sopenharmony_ci        if (uv_pipe_open(pipe, s)) {
451cc290419Sopenharmony_ci            break;
452cc290419Sopenharmony_ci        }
453cc290419Sopenharmony_ci        abstractRet = true;
454cc290419Sopenharmony_ci    } while (false);
455cc290419Sopenharmony_ci    if (!abstractRet) {
456cc290419Sopenharmony_ci        Base::CloseFd(s);
457cc290419Sopenharmony_ci    }
458cc290419Sopenharmony_ci#endif
459cc290419Sopenharmony_ci    return abstractRet;
460cc290419Sopenharmony_ci}
461cc290419Sopenharmony_ci
462cc290419Sopenharmony_cibool HdcForwardBase::SetupFilePoint(HCtxForward ctxPoint)
463cc290419Sopenharmony_ci{
464cc290419Sopenharmony_ci    string &sNodeCfg = ctxPoint->localArgs[1];
465cc290419Sopenharmony_ci    ctxPoint->pipe.data = ctxPoint;
466cc290419Sopenharmony_ci    uv_pipe_init(loopTask, &ctxPoint->pipe, 0);
467cc290419Sopenharmony_ci    if (ctxPoint->masterSlave) {
468cc290419Sopenharmony_ci        if (ctxPoint->type == FORWARD_RESERVED || ctxPoint->type == FORWARD_FILESYSTEM) {
469cc290419Sopenharmony_ci            unlink(sNodeCfg.c_str());
470cc290419Sopenharmony_ci        }
471cc290419Sopenharmony_ci        if (uv_pipe_bind(&ctxPoint->pipe, sNodeCfg.c_str())) {
472cc290419Sopenharmony_ci            ctxPoint->lastError = "Unix pipe bind failed";
473cc290419Sopenharmony_ci            return false;
474cc290419Sopenharmony_ci        }
475cc290419Sopenharmony_ci        if (uv_listen((uv_stream_t *)&ctxPoint->pipe, UV_LISTEN_LBACKOG, ListenCallback)) {
476cc290419Sopenharmony_ci            ctxPoint->lastError = "Unix pipe listen failed";
477cc290419Sopenharmony_ci            return false;
478cc290419Sopenharmony_ci        }
479cc290419Sopenharmony_ci    } else {
480cc290419Sopenharmony_ci        if (ctxPoint->type == FORWARD_ABSTRACT) {
481cc290419Sopenharmony_ci            bool abstractRet = LocalAbstractConnect(&ctxPoint->pipe, sNodeCfg);
482cc290419Sopenharmony_ci            SetupPointContinue(ctxPoint, abstractRet ? 0 : -1);
483cc290419Sopenharmony_ci            if (!abstractRet) {
484cc290419Sopenharmony_ci                ctxPoint->lastError = "LocalAbstractConnect failed";
485cc290419Sopenharmony_ci                return false;
486cc290419Sopenharmony_ci            }
487cc290419Sopenharmony_ci        } else {
488cc290419Sopenharmony_ci            uv_connect_t *connect = new(std::nothrow) uv_connect_t();
489cc290419Sopenharmony_ci            if (connect == nullptr) {
490cc290419Sopenharmony_ci                WRITE_LOG(LOG_FATAL, "SetupFilePoint new connect failed");
491cc290419Sopenharmony_ci                return false;
492cc290419Sopenharmony_ci            }
493cc290419Sopenharmony_ci            connect->data = ctxPoint;
494cc290419Sopenharmony_ci            uv_pipe_connect(connect, &ctxPoint->pipe, sNodeCfg.c_str(), ConnectTarget);
495cc290419Sopenharmony_ci        }
496cc290419Sopenharmony_ci    }
497cc290419Sopenharmony_ci    return true;
498cc290419Sopenharmony_ci}
499cc290419Sopenharmony_ci
500cc290419Sopenharmony_cibool HdcForwardBase::SetupPoint(HCtxForward ctxPoint)
501cc290419Sopenharmony_ci{
502cc290419Sopenharmony_ci    bool ret = true;
503cc290419Sopenharmony_ci    if (!DetechForwardType(ctxPoint)) {
504cc290419Sopenharmony_ci        return false;
505cc290419Sopenharmony_ci    }
506cc290419Sopenharmony_ci    switch (ctxPoint->type) {
507cc290419Sopenharmony_ci        case FORWARD_TCP:
508cc290419Sopenharmony_ci            if (!SetupTCPPoint(ctxPoint)) {
509cc290419Sopenharmony_ci                ret = false;
510cc290419Sopenharmony_ci            };
511cc290419Sopenharmony_ci            break;
512cc290419Sopenharmony_ci#ifndef _WIN32
513cc290419Sopenharmony_ci        case FORWARD_DEVICE:
514cc290419Sopenharmony_ci            if (!SetupDevicePoint(ctxPoint)) {
515cc290419Sopenharmony_ci                ret = false;
516cc290419Sopenharmony_ci            };
517cc290419Sopenharmony_ci            break;
518cc290419Sopenharmony_ci        case FORWARD_JDWP:
519cc290419Sopenharmony_ci            if (!SetupJdwpPoint(ctxPoint)) {
520cc290419Sopenharmony_ci                ret = false;
521cc290419Sopenharmony_ci            };
522cc290419Sopenharmony_ci            break;
523cc290419Sopenharmony_ci        case FORWARD_ABSTRACT:
524cc290419Sopenharmony_ci        case FORWARD_RESERVED:
525cc290419Sopenharmony_ci        case FORWARD_FILESYSTEM:
526cc290419Sopenharmony_ci            if (!SetupFilePoint(ctxPoint)) {
527cc290419Sopenharmony_ci                ret = false;
528cc290419Sopenharmony_ci            };
529cc290419Sopenharmony_ci            break;
530cc290419Sopenharmony_ci#else
531cc290419Sopenharmony_ci        case FORWARD_DEVICE:
532cc290419Sopenharmony_ci        case FORWARD_JDWP:
533cc290419Sopenharmony_ci        case FORWARD_ABSTRACT:
534cc290419Sopenharmony_ci        case FORWARD_RESERVED:
535cc290419Sopenharmony_ci        case FORWARD_FILESYSTEM:
536cc290419Sopenharmony_ci            ctxPoint->lastError = "Not supoort forward-type";
537cc290419Sopenharmony_ci            ret = false;
538cc290419Sopenharmony_ci            break;
539cc290419Sopenharmony_ci#endif
540cc290419Sopenharmony_ci        default:
541cc290419Sopenharmony_ci            ctxPoint->lastError = "Not supoort forward-type";
542cc290419Sopenharmony_ci            ret = false;
543cc290419Sopenharmony_ci            break;
544cc290419Sopenharmony_ci    }
545cc290419Sopenharmony_ci    return ret;
546cc290419Sopenharmony_ci}
547cc290419Sopenharmony_ci
548cc290419Sopenharmony_cibool HdcForwardBase::BeginForward(const string &command, string &sError)
549cc290419Sopenharmony_ci{
550cc290419Sopenharmony_ci    bool ret = false;
551cc290419Sopenharmony_ci    int argc = 0;
552cc290419Sopenharmony_ci    char bufString[BUF_SIZE_SMALL] = "";
553cc290419Sopenharmony_ci    HCtxForward ctxPoint = (HCtxForward)MallocContext(true);
554cc290419Sopenharmony_ci    if (!ctxPoint) {
555cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "MallocContext failed");
556cc290419Sopenharmony_ci        return false;
557cc290419Sopenharmony_ci    }
558cc290419Sopenharmony_ci    char **argv = Base::SplitCommandToArgs(command.c_str(), &argc);
559cc290419Sopenharmony_ci    if (argv == nullptr) {
560cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SplitCommandToArgs failed");
561cc290419Sopenharmony_ci        return false;
562cc290419Sopenharmony_ci    }
563cc290419Sopenharmony_ci    while (true) {
564cc290419Sopenharmony_ci        if (argc < CMD_ARG1_COUNT) {
565cc290419Sopenharmony_ci            break;
566cc290419Sopenharmony_ci        }
567cc290419Sopenharmony_ci        if (strlen(argv[0]) > BUF_SIZE_SMALL || strlen(argv[1]) > BUF_SIZE_SMALL) {
568cc290419Sopenharmony_ci            break;
569cc290419Sopenharmony_ci        }
570cc290419Sopenharmony_ci        if (!CheckNodeInfo(argv[0], ctxPoint->localArgs)) {
571cc290419Sopenharmony_ci            break;
572cc290419Sopenharmony_ci        }
573cc290419Sopenharmony_ci        if (!CheckNodeInfo(argv[1], ctxPoint->remoteArgs)) {
574cc290419Sopenharmony_ci            break;
575cc290419Sopenharmony_ci        }
576cc290419Sopenharmony_ci        ctxPoint->remoteParamenters = argv[1];
577cc290419Sopenharmony_ci        if (!SetupPoint(ctxPoint)) {
578cc290419Sopenharmony_ci            break;
579cc290419Sopenharmony_ci        }
580cc290419Sopenharmony_ci
581cc290419Sopenharmony_ci        ret = true;
582cc290419Sopenharmony_ci        break;
583cc290419Sopenharmony_ci    }
584cc290419Sopenharmony_ci    sError = ctxPoint->lastError;
585cc290419Sopenharmony_ci    if (ret) {
586cc290419Sopenharmony_ci        // First 8-byte parameter bit
587cc290419Sopenharmony_ci        int maxBufSize = sizeof(bufString) - forwardParameterBufSize;
588cc290419Sopenharmony_ci        if (snprintf_s(bufString + forwardParameterBufSize, maxBufSize, maxBufSize - 1, "%s", argv[1]) > 0) {
589cc290419Sopenharmony_ci            SendToTask(ctxPoint->id, CMD_FORWARD_CHECK, reinterpret_cast<uint8_t *>(bufString),
590cc290419Sopenharmony_ci                       forwardParameterBufSize + strlen(bufString + forwardParameterBufSize) + 1);
591cc290419Sopenharmony_ci            taskCommand = command;
592cc290419Sopenharmony_ci        }
593cc290419Sopenharmony_ci    }
594cc290419Sopenharmony_ci    delete[](reinterpret_cast<char *>(argv));
595cc290419Sopenharmony_ci    return ret;
596cc290419Sopenharmony_ci}
597cc290419Sopenharmony_ci
598cc290419Sopenharmony_ciinline bool HdcForwardBase::FilterCommand(uint8_t *bufCmdIn, uint32_t *idOut, uint8_t **pContentBuf)
599cc290419Sopenharmony_ci{
600cc290419Sopenharmony_ci    *pContentBuf = bufCmdIn + DWORD_SERIALIZE_SIZE;
601cc290419Sopenharmony_ci    *idOut = ntohl(*reinterpret_cast<uint32_t *>(bufCmdIn));
602cc290419Sopenharmony_ci    return true;
603cc290419Sopenharmony_ci}
604cc290419Sopenharmony_ci
605cc290419Sopenharmony_cibool HdcForwardBase::SlaveConnect(uint8_t *bufCmd, const int bufSize, bool bCheckPoint, string &sError)
606cc290419Sopenharmony_ci{
607cc290419Sopenharmony_ci    if (bufSize <= DWORD_SERIALIZE_SIZE + forwardParameterBufSize) {
608cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "Illegal payloadSize, shorter than forward header");
609cc290419Sopenharmony_ci        return false;
610cc290419Sopenharmony_ci    }
611cc290419Sopenharmony_ci    bool ret = false;
612cc290419Sopenharmony_ci    char *content = nullptr;
613cc290419Sopenharmony_ci    uint32_t idSlaveOld = 0;
614cc290419Sopenharmony_ci    HCtxForward ctxPoint = (HCtxForward)MallocContext(false);
615cc290419Sopenharmony_ci    if (!ctxPoint) {
616cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "MallocContext failed");
617cc290419Sopenharmony_ci        return false;
618cc290419Sopenharmony_ci    }
619cc290419Sopenharmony_ci    idSlaveOld = ctxPoint->id;
620cc290419Sopenharmony_ci    ctxPoint->checkPoint = bCheckPoint;
621cc290419Sopenharmony_ci    // refresh another id,8byte param
622cc290419Sopenharmony_ci    FilterCommand(bufCmd, &ctxPoint->id, reinterpret_cast<uint8_t **>(&content));
623cc290419Sopenharmony_ci    AdminContext(OP_UPDATE, idSlaveOld, ctxPoint);
624cc290419Sopenharmony_ci    content += forwardParameterBufSize;
625cc290419Sopenharmony_ci    if (!CheckNodeInfo(content, ctxPoint->localArgs)) {
626cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SlaveConnect CheckNodeInfo failed content:%s", content);
627cc290419Sopenharmony_ci        goto Finish;
628cc290419Sopenharmony_ci    }
629cc290419Sopenharmony_ci    if (!DetechForwardType(ctxPoint)) {
630cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SlaveConnect DetechForwardType failed content:%s", content);
631cc290419Sopenharmony_ci        goto Finish;
632cc290419Sopenharmony_ci    }
633cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "id:%u type:%d", ctxPoint->id, ctxPoint->type);
634cc290419Sopenharmony_ci    if (ctxPoint->type == FORWARD_ARK) {
635cc290419Sopenharmony_ci        if (ctxPoint->checkPoint) {
636cc290419Sopenharmony_ci            if (!SetupArkPoint(ctxPoint)) {
637cc290419Sopenharmony_ci                sError = ctxPoint->lastError;
638cc290419Sopenharmony_ci                WRITE_LOG(LOG_FATAL, "SlaveConnect SetupArkPoint failed content:%s", content);
639cc290419Sopenharmony_ci                goto Finish;
640cc290419Sopenharmony_ci            }
641cc290419Sopenharmony_ci        } else {
642cc290419Sopenharmony_ci            SetupPointContinue(ctxPoint, 0);
643cc290419Sopenharmony_ci        }
644cc290419Sopenharmony_ci        ret = true;
645cc290419Sopenharmony_ci    } else {
646cc290419Sopenharmony_ci        if (!ctxPoint->checkPoint) {
647cc290419Sopenharmony_ci            if (!SetupPoint(ctxPoint)) {
648cc290419Sopenharmony_ci                sError = ctxPoint->lastError;
649cc290419Sopenharmony_ci                WRITE_LOG(LOG_FATAL, "SlaveConnect SetupPoint failed content:%s", content);
650cc290419Sopenharmony_ci                goto Finish;
651cc290419Sopenharmony_ci            }
652cc290419Sopenharmony_ci        } else {
653cc290419Sopenharmony_ci            SetupPointContinue(ctxPoint, 0);
654cc290419Sopenharmony_ci        }
655cc290419Sopenharmony_ci        ret = true;
656cc290419Sopenharmony_ci    }
657cc290419Sopenharmony_ciFinish:
658cc290419Sopenharmony_ci    if (!ret) {
659cc290419Sopenharmony_ci        FreeContext(ctxPoint, 0, true);
660cc290419Sopenharmony_ci    }
661cc290419Sopenharmony_ci    return ret;
662cc290419Sopenharmony_ci}
663cc290419Sopenharmony_ci
664cc290419Sopenharmony_cibool HdcForwardBase::DoForwardBegin(HCtxForward ctx)
665cc290419Sopenharmony_ci{
666cc290419Sopenharmony_ci    switch (ctx->type) {
667cc290419Sopenharmony_ci        case FORWARD_TCP:
668cc290419Sopenharmony_ci        case FORWARD_JDWP:  // jdwp use tcp ->socketpair->jvm
669cc290419Sopenharmony_ci            uv_tcp_nodelay((uv_tcp_t *)&ctx->tcp, 1);
670cc290419Sopenharmony_ci            uv_read_start((uv_stream_t *)&ctx->tcp, AllocForwardBuf, ReadForwardBuf);
671cc290419Sopenharmony_ci            break;
672cc290419Sopenharmony_ci        case FORWARD_ARK:
673cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "DoForwardBegin ark socketpair id:%u fds[0]:%d", ctx->id, fds[0]);
674cc290419Sopenharmony_ci            uv_tcp_init(loopTask, &ctx->tcp);
675cc290419Sopenharmony_ci            uv_tcp_open(&ctx->tcp, fds[0]);
676cc290419Sopenharmony_ci            uv_tcp_nodelay((uv_tcp_t *)&ctx->tcp, 1);
677cc290419Sopenharmony_ci            uv_read_start((uv_stream_t *)&ctx->tcp, AllocForwardBuf, ReadForwardBuf);
678cc290419Sopenharmony_ci            break;
679cc290419Sopenharmony_ci        case FORWARD_ABSTRACT:
680cc290419Sopenharmony_ci        case FORWARD_RESERVED:
681cc290419Sopenharmony_ci        case FORWARD_FILESYSTEM:
682cc290419Sopenharmony_ci            uv_read_start((uv_stream_t *)&ctx->pipe, AllocForwardBuf, ReadForwardBuf);
683cc290419Sopenharmony_ci            break;
684cc290419Sopenharmony_ci        case FORWARD_DEVICE: {
685cc290419Sopenharmony_ci            ctx->fdClass->StartWorkOnThread();
686cc290419Sopenharmony_ci            break;
687cc290419Sopenharmony_ci        }
688cc290419Sopenharmony_ci        default:
689cc290419Sopenharmony_ci            break;
690cc290419Sopenharmony_ci    }
691cc290419Sopenharmony_ci    ctx->ready = true;
692cc290419Sopenharmony_ci    return true;
693cc290419Sopenharmony_ci}
694cc290419Sopenharmony_ci
695cc290419Sopenharmony_civoid *HdcForwardBase::AdminContext(const uint8_t op, const uint32_t id, HCtxForward hInput)
696cc290419Sopenharmony_ci{
697cc290419Sopenharmony_ci    ctxPointMutex.lock();
698cc290419Sopenharmony_ci    void *hRet = nullptr;
699cc290419Sopenharmony_ci    map<uint32_t, HCtxForward> &mapCtx = mapCtxPoint;
700cc290419Sopenharmony_ci    switch (op) {
701cc290419Sopenharmony_ci        case OP_ADD:
702cc290419Sopenharmony_ci            mapCtx[id] = hInput;
703cc290419Sopenharmony_ci            break;
704cc290419Sopenharmony_ci        case OP_REMOVE:
705cc290419Sopenharmony_ci            mapCtx.erase(id);
706cc290419Sopenharmony_ci            break;
707cc290419Sopenharmony_ci        case OP_QUERY:
708cc290419Sopenharmony_ci            if (mapCtx.count(id)) {
709cc290419Sopenharmony_ci                hRet = mapCtx[id];
710cc290419Sopenharmony_ci            }
711cc290419Sopenharmony_ci            break;
712cc290419Sopenharmony_ci        case OP_UPDATE:
713cc290419Sopenharmony_ci            mapCtx.erase(id);
714cc290419Sopenharmony_ci            mapCtx[hInput->id] = hInput;
715cc290419Sopenharmony_ci            break;
716cc290419Sopenharmony_ci        default:
717cc290419Sopenharmony_ci            break;
718cc290419Sopenharmony_ci    }
719cc290419Sopenharmony_ci    ctxPointMutex.unlock();
720cc290419Sopenharmony_ci    return hRet;
721cc290419Sopenharmony_ci}
722cc290419Sopenharmony_ci
723cc290419Sopenharmony_civoid HdcForwardBase::SendCallbackForwardBuf(uv_write_t *req, int status)
724cc290419Sopenharmony_ci{
725cc290419Sopenharmony_ci    ContextForwardIO *ctxIO = (ContextForwardIO *)req->data;
726cc290419Sopenharmony_ci    HCtxForward ctx = reinterpret_cast<HCtxForward>(ctxIO->ctxForward);
727cc290419Sopenharmony_ci    if (status < 0 && !ctx->finish) {
728cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "SendCallbackForwardBuf ctx->type:%d, status:%d finish", ctx->type, status);
729cc290419Sopenharmony_ci        ctx->thisClass->FreeContext(ctx, 0, true);
730cc290419Sopenharmony_ci    }
731cc290419Sopenharmony_ci    delete[] ctxIO->bufIO;
732cc290419Sopenharmony_ci    delete ctxIO;
733cc290419Sopenharmony_ci    delete req;
734cc290419Sopenharmony_ci}
735cc290419Sopenharmony_ci
736cc290419Sopenharmony_ciint HdcForwardBase::SendForwardBuf(HCtxForward ctx, uint8_t *bufPtr, const int size)
737cc290419Sopenharmony_ci{
738cc290419Sopenharmony_ci    int nRet = 0;
739cc290419Sopenharmony_ci    if (size > static_cast<int>(HDC_BUF_MAX_BYTES - 1)) {
740cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "SendForwardBuf size:%d > HDC_BUF_MAX_BYTES, ctxId:%u", size, ctx->id);
741cc290419Sopenharmony_ci        return -1;
742cc290419Sopenharmony_ci    }
743cc290419Sopenharmony_ci    if (size <= 0) {
744cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "SendForwardBuf failed size:%d, ctxId:%u", size, ctx->id);
745cc290419Sopenharmony_ci        return -1;
746cc290419Sopenharmony_ci    }
747cc290419Sopenharmony_ci    auto pDynBuf = new(std::nothrow) uint8_t[size];
748cc290419Sopenharmony_ci    if (!pDynBuf) {
749cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "SendForwardBuf new DynBuf failed size:%d, ctxId:%u", size, ctx->id);
750cc290419Sopenharmony_ci        return -1;
751cc290419Sopenharmony_ci    }
752cc290419Sopenharmony_ci    (void)memcpy_s(pDynBuf, size, bufPtr, size);
753cc290419Sopenharmony_ci    if (ctx->type == FORWARD_DEVICE) {
754cc290419Sopenharmony_ci        nRet = ctx->fdClass->WriteWithMem(pDynBuf, size);
755cc290419Sopenharmony_ci    } else {
756cc290419Sopenharmony_ci        auto ctxIO = new ContextForwardIO();
757cc290419Sopenharmony_ci        if (!ctxIO) {
758cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "SendForwardBuf new ContextForwardIO failed, ctxId:%u", ctx->id);
759cc290419Sopenharmony_ci            delete[] pDynBuf;
760cc290419Sopenharmony_ci            return -1;
761cc290419Sopenharmony_ci        }
762cc290419Sopenharmony_ci        ctxIO->ctxForward = ctx;
763cc290419Sopenharmony_ci        ctxIO->bufIO = pDynBuf;
764cc290419Sopenharmony_ci        if (ctx->type == FORWARD_TCP || ctx->type == FORWARD_JDWP || ctx->type == FORWARD_ARK) {
765cc290419Sopenharmony_ci            nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->tcp, pDynBuf, size, nullptr,
766cc290419Sopenharmony_ci                                        (void *)SendCallbackForwardBuf, (void *)ctxIO);
767cc290419Sopenharmony_ci        } else {
768cc290419Sopenharmony_ci            // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM,
769cc290419Sopenharmony_ci            nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, pDynBuf, size, nullptr,
770cc290419Sopenharmony_ci                                        (void *)SendCallbackForwardBuf, (void *)ctxIO);
771cc290419Sopenharmony_ci        }
772cc290419Sopenharmony_ci        if (nRet < 0) {
773cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "SendForwardBuf SendToStreamEx ret:%d, size:%d ctxId:%u type:%d",
774cc290419Sopenharmony_ci                nRet, size, ctx->id, ctx->type);
775cc290419Sopenharmony_ci        }
776cc290419Sopenharmony_ci    }
777cc290419Sopenharmony_ci    return nRet;
778cc290419Sopenharmony_ci}
779cc290419Sopenharmony_ci
780cc290419Sopenharmony_cibool HdcForwardBase::CommandForwardCheckResult(HCtxForward ctx, uint8_t *payload)
781cc290419Sopenharmony_ci{
782cc290419Sopenharmony_ci    bool ret = true;
783cc290419Sopenharmony_ci    bool bCheck = static_cast<bool>(payload);
784cc290419Sopenharmony_ci    LogMsg(bCheck ? MSG_OK : MSG_FAIL, "Forwardport result:%s", bCheck ? "OK" : "Failed");
785cc290419Sopenharmony_ci    if (bCheck) {
786cc290419Sopenharmony_ci        string mapInfo = taskInfo->serverOrDaemon ? "1|" : "0|";
787cc290419Sopenharmony_ci        mapInfo += taskCommand;
788cc290419Sopenharmony_ci        ctx->ready = true;
789cc290419Sopenharmony_ci        ServerCommand(CMD_FORWARD_SUCCESS, reinterpret_cast<uint8_t *>(const_cast<char *>(mapInfo.c_str())),
790cc290419Sopenharmony_ci                      mapInfo.size() + 1);
791cc290419Sopenharmony_ci    } else {
792cc290419Sopenharmony_ci        ret = false;
793cc290419Sopenharmony_ci        FreeContext(ctx, 0, false);
794cc290419Sopenharmony_ci    }
795cc290419Sopenharmony_ci    return ret;
796cc290419Sopenharmony_ci}
797cc290419Sopenharmony_ci
798cc290419Sopenharmony_cibool HdcForwardBase::ForwardCommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
799cc290419Sopenharmony_ci{
800cc290419Sopenharmony_ci    if (payloadSize <= DWORD_SERIALIZE_SIZE && command != CMD_FORWARD_FREE_CONTEXT
801cc290419Sopenharmony_ci        && command != CMD_FORWARD_ACTIVE_MASTER) {
802cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "Illegal payloadSize, shorter than forward command header");
803cc290419Sopenharmony_ci        return false;
804cc290419Sopenharmony_ci    }
805cc290419Sopenharmony_ci    bool ret = true;
806cc290419Sopenharmony_ci    uint8_t *pContent = nullptr;
807cc290419Sopenharmony_ci    int sizeContent = 0;
808cc290419Sopenharmony_ci    uint32_t id = 0;
809cc290419Sopenharmony_ci    HCtxForward ctx = nullptr;
810cc290419Sopenharmony_ci    FilterCommand(payload, &id, &pContent);
811cc290419Sopenharmony_ci    sizeContent = payloadSize - DWORD_SERIALIZE_SIZE;
812cc290419Sopenharmony_ci    if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) {
813cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "Query id:%u failed", id);
814cc290419Sopenharmony_ci        return true;
815cc290419Sopenharmony_ci    }
816cc290419Sopenharmony_ci    switch (command) {
817cc290419Sopenharmony_ci        case CMD_FORWARD_CHECK_RESULT: {
818cc290419Sopenharmony_ci            ret = CommandForwardCheckResult(ctx, pContent);
819cc290419Sopenharmony_ci            break;
820cc290419Sopenharmony_ci        }
821cc290419Sopenharmony_ci        case CMD_FORWARD_ACTIVE_MASTER: {
822cc290419Sopenharmony_ci            ret = DoForwardBegin(ctx);
823cc290419Sopenharmony_ci            break;
824cc290419Sopenharmony_ci        }
825cc290419Sopenharmony_ci        case CMD_FORWARD_DATA: {
826cc290419Sopenharmony_ci            if (ctx->finish) {
827cc290419Sopenharmony_ci                break;
828cc290419Sopenharmony_ci            }
829cc290419Sopenharmony_ci            if (SendForwardBuf(ctx, pContent, sizeContent) < 0) {
830cc290419Sopenharmony_ci                WRITE_LOG(LOG_WARN, "ForwardCommandDispatch SendForwardBuf rc < 0, ctxid:%u", ctx->id);
831cc290419Sopenharmony_ci                FreeContext(ctx, 0, true);
832cc290419Sopenharmony_ci            }
833cc290419Sopenharmony_ci            break;
834cc290419Sopenharmony_ci        }
835cc290419Sopenharmony_ci        case CMD_FORWARD_FREE_CONTEXT: {
836cc290419Sopenharmony_ci            FreeContext(ctx, 0, false);
837cc290419Sopenharmony_ci            break;
838cc290419Sopenharmony_ci        }
839cc290419Sopenharmony_ci        default:
840cc290419Sopenharmony_ci            ret = false;
841cc290419Sopenharmony_ci            break;
842cc290419Sopenharmony_ci    }
843cc290419Sopenharmony_ci    if (!ret) {
844cc290419Sopenharmony_ci        if (ctx) {
845cc290419Sopenharmony_ci            FreeContext(ctx, 0, true);
846cc290419Sopenharmony_ci        } else {
847cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "ctx==nullptr raw free");
848cc290419Sopenharmony_ci            TaskFinish();
849cc290419Sopenharmony_ci        }
850cc290419Sopenharmony_ci    }
851cc290419Sopenharmony_ci    return ret;
852cc290419Sopenharmony_ci}
853cc290419Sopenharmony_ci
854cc290419Sopenharmony_cibool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
855cc290419Sopenharmony_ci{
856cc290419Sopenharmony_ci    if (command != CMD_FORWARD_DATA) {
857cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "CommandDispatch command:%d payloadSize:%d", command, payloadSize);
858cc290419Sopenharmony_ci    }
859cc290419Sopenharmony_ci    bool ret = true;
860cc290419Sopenharmony_ci    string sError;
861cc290419Sopenharmony_ci    // prepare
862cc290419Sopenharmony_ci    if (command == CMD_FORWARD_INIT) {
863cc290419Sopenharmony_ci        string strCommand(reinterpret_cast<char *>(payload), payloadSize);
864cc290419Sopenharmony_ci        if (!BeginForward(strCommand, sError)) {
865cc290419Sopenharmony_ci            ret = false;
866cc290419Sopenharmony_ci            goto Finish;
867cc290419Sopenharmony_ci        }
868cc290419Sopenharmony_ci        return true;
869cc290419Sopenharmony_ci    } else if (command == CMD_FORWARD_CHECK) {
870cc290419Sopenharmony_ci        // Detect remote if it's reachable
871cc290419Sopenharmony_ci        if (!SlaveConnect(payload, payloadSize, true, sError)) {
872cc290419Sopenharmony_ci            ret = false;
873cc290419Sopenharmony_ci            goto Finish;
874cc290419Sopenharmony_ci        }
875cc290419Sopenharmony_ci        return true;
876cc290419Sopenharmony_ci    } else if (command == CMD_FORWARD_ACTIVE_SLAVE) {
877cc290419Sopenharmony_ci        // slave connect target port when activating
878cc290419Sopenharmony_ci        if (!SlaveConnect(payload, payloadSize, false, sError)) {
879cc290419Sopenharmony_ci            ret = false;
880cc290419Sopenharmony_ci            goto Finish;
881cc290419Sopenharmony_ci        }
882cc290419Sopenharmony_ci        return true;
883cc290419Sopenharmony_ci    }
884cc290419Sopenharmony_ci    if (!ForwardCommandDispatch(command, payload, payloadSize)) {
885cc290419Sopenharmony_ci        ret = false;
886cc290419Sopenharmony_ci        goto Finish;
887cc290419Sopenharmony_ci    }
888cc290419Sopenharmony_ciFinish:
889cc290419Sopenharmony_ci    if (!ret) {
890cc290419Sopenharmony_ci        if (!sError.size()) {
891cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, "Forward parament failed");
892cc290419Sopenharmony_ci        } else {
893cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, const_cast<char *>(sError.c_str()));
894cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, const_cast<char *>(sError.c_str()));
895cc290419Sopenharmony_ci        }
896cc290419Sopenharmony_ci    }
897cc290419Sopenharmony_ci    return ret;
898cc290419Sopenharmony_ci}
899cc290419Sopenharmony_ci}  // namespace Hdc
900