1/*
2 * Copyright (c) 2024 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 "app_spawn_test_helper.h"
17
18#include <cstdint>
19#include <cstdio>
20#include <cstdlib>
21#include <fcntl.h>
22#include <pthread.h>
23#include <csignal>
24#include <string>
25#include <sys/eventfd.h>
26#include <sys/wait.h>
27#include <unistd.h>
28#include <inttypes.h>
29
30#include "appspawn.h"
31#include "appspawn_client.h"
32#include "appspawn_modulemgr.h"
33#include "appspawn_msg.h"
34#include "appspawn_server.h"
35#include "appspawn_service.h"
36#include "appspawn_manager.h"
37#include "appspawn_utils.h"
38#include "loop_event.h"
39#include "parameters.h"
40#include "securec.h"
41
42#include "app_spawn_stub.h"
43
44namespace OHOS {
45typedef struct {
46    int32_t bundleIndex;
47    char bundleName[APP_LEN_BUNDLE_NAME];  // process name
48} AppBundleInfo;
49
50typedef struct {
51    uint32_t hapFlags;
52    char apl[APP_APL_MAX_LEN];
53} AppDomainInfo;
54
55const uint32_t AppSpawnTestServer::defaultProtectTime = 60000; // 60000 60s
56
57uint32_t AppSpawnTestServer::serverId = 0;
58static int TestChildLoopRun(AppSpawnContent *content, AppSpawnClient *client)
59{
60    APPSPAWN_LOGV("ChildLoopRun ...");
61    sleep(1);
62    return 0;
63}
64
65AppSpawnTestServer::~AppSpawnTestServer()
66{
67    if (localServer_) {
68        delete localServer_;
69        localServer_ = nullptr;
70    }
71}
72
73void AppSpawnTestServer::CloseCheckHandler(void)
74{
75    APPSPAWN_LOGV("CloseCheckHandler");
76#ifdef USER_TIMER_TO_CHECK
77    if (timer_ != nullptr) {
78        LE_StopTimer(LE_GetDefaultLoop(), timer_);
79        timer_ = nullptr;
80    }
81#else
82    if (idle_) {
83        LE_DelIdle(idle_);
84        idle_ = nullptr;
85    }
86#endif
87}
88
89void AppSpawnTestServer::StartCheckHandler(void)
90{
91#ifdef USER_TIMER_TO_CHECK
92    int ret = LE_CreateTimer(LE_GetDefaultLoop(), &timer_, ProcessIdle, this);
93    if (ret == 0) {
94        ret = LE_StartTimer(LE_GetDefaultLoop(), timer_, 100, 10000000);  // 100 10000000 repeat
95    }
96#else
97    LE_AddIdle(LE_GetDefaultLoop(), &idle_, ProcessIdle, this, 10000000);  // 10000000 repeat
98#endif
99}
100
101void AppSpawnTestServer::ServiceThread()
102{
103    CmdArgs *args = nullptr;
104    pid_t pid = getpid();
105    APPSPAWN_LOGV("AppSpawnTestServer::ServiceThread %{public}s", serviceCmd_.c_str());
106
107    running_ = true;
108    // 测试server时,使用appspawn的server
109    if (testServer_) {
110        content_ = AppSpawnTestHelper::StartSpawnServer(serviceCmd_, args);
111        if (content_ == nullptr) {
112            return;
113        }
114        if (pid == getpid()) {  // 主进程进行处理
115            APPSPAWN_LOGV("Service start timer %{public}s ", serviceCmd_.c_str());
116            StartCheckHandler();
117            AppSpawnMgr *content = reinterpret_cast<AppSpawnMgr *>(content_);
118            APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, return);
119            AppSpawnedProcess *info = GetSpawnedProcessByName(NWEBSPAWN_SERVER_NAME);
120            if (info != nullptr) {
121                APPSPAWN_LOGV("Save nwebspawn pid: %{public}d %{public}d", info->pid, serverId_);
122                appPid_.store(info->pid);
123            }
124            // register
125            RegChildLooper(&content->content, TestChildLoopRun);
126        }
127        content_->runAppSpawn(content_, args->argc, args->argv);
128        if (pid != getpid()) {  // 子进程退出
129            exit(0);
130        } else {
131            content_ = nullptr;
132        }
133    } else {
134        StartCheckHandler();
135        localServer_ = new LocalTestServer();
136        localServer_->Run(APPSPAWN_SOCKET_NAME, recvMsgProcess_);
137    }
138    APPSPAWN_LOGV("AppSpawnTestServer::ServiceThread finish %{public}s ", serviceCmd_.c_str());
139    if (args) {
140        free(args);
141    }
142    return;
143}
144
145void AppSpawnTestServer::Start(void)
146{
147    Start(nullptr);
148}
149
150static void *ServiceHelperThread(void *arg)
151{
152    AppSpawnTestServer *server = reinterpret_cast<AppSpawnTestServer *>(arg);
153    APPSPAWN_LOGV("AppSpawnTestServer::thread ");
154    server->ServiceThread();
155    return nullptr;
156}
157
158void AppSpawnTestServer::Start(RecvMsgProcess process, uint32_t time)
159{
160    APPSPAWN_LOGV("AppSpawnTestServer::Start serverId %{public}u", AppSpawnTestServer::serverId);
161    protectTime_ = time;
162    uint32_t retry = 0;
163    if (threadId_ != 0) {
164        return;
165    }
166    clock_gettime(CLOCK_MONOTONIC, &startTime_);
167    recvMsgProcess_ = process;
168    errno = 0;
169    int ret = 0;
170    do {
171        threadId_ = 0;
172        ret = pthread_create(&threadId_, nullptr, ServiceHelperThread, static_cast<void *>(this));
173        if (ret == 0) {
174            break;
175        }
176        APPSPAWN_LOGE("AppSpawnTestServer::Start create thread fail %{public}d %{public}d", ret, errno);
177        usleep(20000); // 20000 20ms
178        retry++;
179    } while (ret == EAGAIN && retry < 10); // 10 max retry
180
181    // wait server thread run
182    retry = 0;
183    while (!running_ && (retry < 10)) { // 10 max retry
184        usleep(20000); // 20000 20ms
185        retry++;
186    }
187    APPSPAWN_LOGV("AppSpawnTestServer::Start retry %{public}u", retry);
188}
189
190void AppSpawnTestServer::Stop()
191{
192    APPSPAWN_LOGV("AppSpawnTestServer::Stop serverId %{public}u", AppSpawnTestServer::serverId);
193    if (threadId_ != 0) {
194        stop_ = true;
195        pthread_join(threadId_, nullptr);
196        threadId_ = 0;
197        APPSPAWN_LOGV("Stop");
198    }
199}
200
201void AppSpawnTestServer::KillNWebSpawnServer()
202{
203    APPSPAWN_LOGV("Kill nwebspawn %{public}d", serverId_);
204    if (appPid_ > 0) {
205        kill(appPid_, SIGKILL);
206    }
207}
208
209void AppSpawnTestServer::StopSpawnService(void)
210{
211    APPSPAWN_LOGV("StopSpawnService ");
212    if (serverStoped) {
213        CloseCheckHandler();
214    }
215    serverStoped = true;
216    if (testServer_) {
217        struct signalfd_siginfo siginfo = {};
218        siginfo.ssi_signo = SIGTERM;
219        siginfo.ssi_uid = 0;
220        ProcessSignal(&siginfo);
221    } else {
222        localServer_->Stop();
223    }
224}
225
226#ifdef USER_TIMER_TO_CHECK
227void AppSpawnTestServer::ProcessIdle(const TimerHandle taskHandle, void *context)
228#else
229void AppSpawnTestServer::ProcessIdle(const IdleHandle taskHandle, void *context)
230#endif
231{
232    APPSPAWN_LOGV("AppSpawnTestServer::ProcessIdle");
233    AppSpawnTestServer *server = reinterpret_cast<AppSpawnTestServer *>(const_cast<void *>(context));
234    if (server->stop_) {
235        server->StopSpawnService();
236        return;
237    }
238
239    struct timespec end;
240    clock_gettime(CLOCK_MONOTONIC, &end);
241    uint64_t diff = DiffTime(&server->startTime_, &end);
242    if (diff >= (server->protectTime_ * 1000)) {  // 1000 ms -> us
243        APPSPAWN_LOGV("AppSpawnTestServer:: timeout %{public}u %{public}" PRIu64 "", server->protectTime_, diff);
244        server->StopSpawnService();
245        return;
246    }
247}
248
249static int HandleRecvMessage(const TaskHandle taskHandle, uint8_t * buffer, int bufferSize, int flags)
250{
251    int socketFd = LE_GetSocketFd(taskHandle);
252    struct iovec iov = {
253        .iov_base = buffer,
254        .iov_len = bufferSize,
255    };
256    char ctrlBuffer[CMSG_SPACE(APP_MAX_FD_COUNT * sizeof(int))];
257    struct msghdr msg = {
258        .msg_iov = &iov,
259        .msg_iovlen = 1,
260        .msg_control = ctrlBuffer,
261        .msg_controllen = sizeof(ctrlBuffer),
262    };
263
264    AppSpawnConnection *connection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
265    errno = 0;
266    int recvLen = recvmsg(socketFd, &msg, flags);
267    APPSPAWN_CHECK_ONLY_LOG(errno == 0, "recvmsg with errno %d", errno);
268    struct cmsghdr *cmsg = nullptr;
269    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
270        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
271            int fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
272            int* fd = reinterpret_cast<int*>(CMSG_DATA(cmsg));
273            APPSPAWN_CHECK(fdCount <= APP_MAX_FD_COUNT,
274                return -1, "failed to recv fd %d %d", connection->receiverCtx.fdCount, fdCount);
275            APPSPAWN_CHECK(memcpy_s(connection->receiverCtx.fds, fdCount * sizeof(int), fd,
276                fdCount * sizeof(int)) == 0, return -1, "memcpy_s fd failed");
277            connection->receiverCtx.fdCount = fdCount;
278        }
279    }
280
281    return recvLen;
282}
283
284int LocalTestServer::OnConnection(const LoopHandle loopHandle, const TaskHandle server)
285{
286    static uint32_t connectionId = 0;
287    TaskHandle stream;
288    LE_StreamInfo info = {};
289    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
290    info.baseInfo.close = OnClose;
291    info.baseInfo.userDataSize = sizeof(TestConnection);
292    info.disConnectComplete = nullptr;
293    info.sendMessageComplete = SendMessageComplete;
294    info.recvMessage = OnReceiveRequest;
295    info.handleRecvMsg = HandleRecvMessage;
296
297    ServerInfo *serverInfo = (ServerInfo *)LE_GetUserData(server);
298    APPSPAWN_CHECK(serverInfo != nullptr, return -1, "Failed to alloc stream");
299
300    LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
301    APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream");
302    TestConnection *connection = (TestConnection *)LE_GetUserData(stream);
303    APPSPAWN_CHECK(connection != nullptr, return -1, "Failed to alloc stream");
304    connection->connectionId = ++connectionId;
305    connection->stream = stream;
306    connection->msgRecvLen = 0;
307    (void)memset_s(&connection->msg, sizeof(connection->msg), 0, sizeof(connection->msg));
308    connection->buffer = nullptr;
309    connection->recvMsgProcess = serverInfo->recvMsgProcess;
310    APPSPAWN_LOGI("OnConnection connection.id %{public}d fd %{public}d ",
311        connection->connectionId, LE_GetSocketFd(stream));
312    return 0;
313}
314
315void LocalTestServer::SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
316{
317    return;
318}
319
320void LocalTestServer::OnClose(const TaskHandle taskHandle)
321{
322    TestConnection *connection = (TestConnection *)LE_GetUserData(taskHandle);
323    APPSPAWN_CHECK(connection != nullptr, return, "Invalid connection");
324    APPSPAWN_LOGI("OnClose connection.id %{public}d socket %{public}d",
325        connection->connectionId, LE_GetSocketFd(taskHandle));
326
327    AppSpawnConnection *spawnConnection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
328    if (spawnConnection != nullptr) {
329        int fdCount = spawnConnection->receiverCtx.fdCount;
330        for (int i = 0; i < fdCount; i++) {
331            APPSPAWN_LOGI("OnClose close fd %d", spawnConnection->receiverCtx.fds[i]);
332            if (spawnConnection->receiverCtx.fds[i] >= 0) {
333                close(spawnConnection->receiverCtx.fds[i]);
334            }
335        }
336    }
337}
338
339void LocalTestServer::OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
340{
341    TestConnection *connection = (TestConnection *)LE_GetUserData(taskHandle);
342    APPSPAWN_CHECK(connection != nullptr, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
343        return, "Failed to get client form socket");
344
345    if (connection->recvMsgProcess) {
346        connection->recvMsgProcess(connection, buffer, buffLen);
347    }
348}
349
350int LocalTestServer::Run(const char *socketName, RecvMsgProcess recvMsg)
351{
352    char path[128] = {0};  // 128 max path
353    int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", APPSPAWN_SOCKET_DIR, socketName);
354    APPSPAWN_CHECK(ret >= 0, return -1, "Failed to snprintf_s %{public}d", ret);
355    LE_StreamServerInfo info = {};
356    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
357    info.baseInfo.userDataSize = sizeof(ServerInfo);
358    info.socketId = -1;
359    info.server = path;
360    info.baseInfo.close = nullptr;
361    info.incommingConnect = OnConnection;
362
363    MakeDirRec(path, 0711, 0);  // 0711 default mask
364    ret = LE_CreateStreamServer(LE_GetDefaultLoop(), &serverHandle_, &info);
365    APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s errno: %{public}d", path, errno);
366    APPSPAWN_LOGI("LocalTestServer path %{public}s fd %{public}d", path, LE_GetSocketFd(serverHandle_));
367
368    ServerInfo *serverInfo = (ServerInfo *)LE_GetUserData(serverHandle_);
369    APPSPAWN_CHECK(serverInfo != nullptr, return -1, "Failed to alloc stream");
370    serverInfo->local = this;
371    serverInfo->recvMsgProcess = recvMsg;
372    LE_RunLoop(LE_GetDefaultLoop());
373    LE_CloseStreamTask(LE_GetDefaultLoop(), serverHandle_);
374    LE_StopLoop(LE_GetDefaultLoop());
375    LE_CloseLoop(LE_GetDefaultLoop());
376    APPSPAWN_LOGI("LocalTestServer exit");
377    return 0;
378}
379
380void LocalTestServer::Stop()
381{
382    APPSPAWN_LOGI("Stop LocalTestServer ");
383    LE_StopLoop(LE_GetDefaultLoop());
384}
385
386int TestConnection::SendResponse(const AppSpawnMsg *msg, int result, pid_t pid)
387{
388    APPSPAWN_LOGV("SendResponse result: %{public}d pid: %{public}d", result, pid);
389    uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
390    BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
391    AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, nullptr, &bufferSize);
392    int ret = memcpy_s(buffer, bufferSize, msg, sizeof(AppSpawnMsg));
393    APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
394    buffer->result.result = result;
395    buffer->result.pid = pid;
396    return LE_Send(LE_GetDefaultLoop(), stream, handle, bufferSize);
397}
398
399uint32_t AppSpawnTestHelper::GenRandom(void)
400{
401    uint32_t random = 0;
402    int fd = open("/dev/random", O_RDONLY);
403    if (fd >= 0) {
404        read(fd, &random, sizeof(random));
405        close(fd);
406    }
407    return random;
408}
409
410CmdArgs *AppSpawnTestHelper::ToCmdList(const char *cmd)
411{
412    const uint32_t maxArgc = 20;
413    const uint32_t length = sizeof(CmdArgs) + maxArgc * sizeof(char *) + strlen(cmd) + APP_LEN_PROC_NAME + 1 + 2;
414    char *buffer = static_cast<char *>(malloc(length));
415    CmdArgs *args = reinterpret_cast<CmdArgs *>(buffer);
416    APPSPAWN_CHECK(buffer != nullptr, return nullptr, "Failed to alloc args");
417    (void)memset_s(args, length, 0, length);
418    char *start = buffer + sizeof(CmdArgs) + maxArgc * sizeof(char *);
419    char *end = buffer + length;
420    uint32_t index = 0;
421    char *curr = const_cast<char *>(cmd);
422    while (isspace(*curr)) {
423        curr++;
424    }
425
426    while (index < (maxArgc - 1) && *curr != '\0') {
427        if (args->argv[index] == nullptr) {
428            args->argv[index] = start;
429        }
430        *start = *curr;
431        if (isspace(*curr)) {
432            *start = '\0';
433            // 为SetProcessName 预留空间
434            start = (index == 0) ? start + APP_LEN_PROC_NAME : start + 1;
435            while (isspace(*curr) && *curr != '\0') {
436                curr++;
437            }
438            if (*curr != '\0') {
439                index++;
440            }
441        } else {
442            start++;
443            curr++;
444        }
445    }
446
447    index++;
448    args->argv[index] = end - 2;  // 2 last
449    args->argv[index][0] = '#';
450    args->argv[index][1] = '\0';
451    args->argc = index + 1;
452    return args;
453}
454
455int AppSpawnTestHelper::AddDacInfo(AppSpawnReqMsgHandle &reqHandle)
456{
457    AppDacInfo dacInfo = {};
458    dacInfo.uid = defaultTestUid_;
459    dacInfo.gid = defaultTestGid_;
460    dacInfo.gidCount = 2;  // 2 count
461    dacInfo.gidTable[0] = defaultTestGidGroup_;
462    dacInfo.gidTable[1] = defaultTestGidGroup_ + 1;
463    APPSPAWN_CHECK_ONLY_EXPER(strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), "test-app-name") == 0,
464        return APPSPAWN_ARG_INVALID);
465    return AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo);
466}
467
468int AppSpawnTestHelper::AddFdInfo(AppSpawnReqMsgHandle &reqHandle)
469{
470    if (fdArg < 0) {
471        fdArg = open("/dev/random", O_RDONLY);
472    }
473    APPSPAWN_LOGE("Add fd info %d", fdArg);
474    APPSPAWN_CHECK(fdArg >= 0, return -1, "open fd failed ");
475    return AppSpawnReqMsgAddFd(reqHandle, "fdname", fdArg);
476}
477
478AppSpawnReqMsgHandle AppSpawnTestHelper::CreateMsg(AppSpawnClientHandle handle, uint32_t msgType, int base)
479{
480    AppSpawnReqMsgHandle reqHandle = 0;
481    int ret = AppSpawnReqMsgCreate(static_cast<AppSpawnMsgType>(msgType), processName_.c_str(), &reqHandle);
482    APPSPAWN_CHECK(ret == 0, return INVALID_REQ_HANDLE, "Failed to create req %{public}s", processName_.c_str());
483    APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS, return reqHandle);
484    do {
485        ret = AddFdInfo(reqHandle);
486        APPSPAWN_CHECK(ret == 0, break, "Failed to add fd %{public}s", processName_.c_str());
487        ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 100, processName_.c_str());  // 100 test index
488        APPSPAWN_CHECK(ret == 0, break, "Failed to add bundle info req %{public}s", processName_.c_str());
489        ret = AddDacInfo(reqHandle);
490        APPSPAWN_CHECK(ret == 0, break, "Failed to add dac %{public}s", processName_.c_str());
491        ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678);  // 12345678
492        APPSPAWN_CHECK(ret == 0, break, "Failed to add access token %{public}s", processName_.c_str());
493
494        if (defaultMsgFlags_ != 0) {
495            (void)AppSpawnReqMsgSetFlags(reqHandle, TLV_MSG_FLAGS, defaultMsgFlags_);
496        }
497        if (base) {
498            return reqHandle;
499        }
500        const char *testData = "ssssssssssssss sssssssss ssssssss";
501        ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1",
502            reinterpret_cast<uint8_t *>(const_cast<char *>(testData)), strlen(testData));
503        APPSPAWN_CHECK(ret == 0, break, "Failed to ext tlv %{public}s", processName_.c_str());
504        size_t count = permissions_.size();
505        for (size_t i = 0; i < count; i++) {
506            ret = AppSpawnReqMsgAddPermission(reqHandle, permissions_[i]);
507            APPSPAWN_CHECK(ret == 0, break, "Failed to permission %{public}s", permissions_[i]);
508        }
509
510        ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle, 1, 0);
511        APPSPAWN_CHECK(ret == 0, break, "Failed to internet info %{public}s", processName_.c_str());
512
513        ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, "ohos.permission.FILE_ACCESS_MANAGER");
514        APPSPAWN_CHECK(ret == 0, break, "Failed to ownerid %{public}s", processName_.c_str());
515        const char *renderCmd = "/system/bin/sh ls -l ";
516        ret = AppSpawnReqMsgAddExtInfo(reqHandle, MSG_EXT_NAME_RENDER_CMD,
517            reinterpret_cast<const uint8_t *>(renderCmd), strlen(renderCmd));
518        APPSPAWN_CHECK(ret == 0, break, "Failed to render cmd %{public}s", processName_.c_str());
519        ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, defaultApl_.c_str());
520        APPSPAWN_CHECK(ret == 0, break, "Failed to domain info %{public}s", processName_.c_str());
521        return reqHandle;
522    } while (0);
523    AppSpawnReqMsgFree(reqHandle);
524    return INVALID_REQ_HANDLE;
525}
526
527AppSpawnMsgNode *AppSpawnTestHelper::CreateAppSpawnMsg(AppSpawnMsg *msg)
528{
529    AppSpawnMsgNode *msgNode = static_cast<AppSpawnMsgNode *>(calloc(1, sizeof(AppSpawnMsgNode)));
530    APPSPAWN_CHECK(msgNode != nullptr, return nullptr, "Failed to create receiver");
531    int ret = memcpy_s(&msgNode->msgHeader, sizeof(msgNode->msgHeader), msg, sizeof(msgNode->msgHeader));
532    APPSPAWN_CHECK(ret == 0, free(msgNode);
533        return nullptr, "Failed to memcpy msg");
534    msgNode->buffer = static_cast<uint8_t *>(malloc(msg->msgLen));
535    APPSPAWN_CHECK(msgNode->buffer != nullptr, free(msgNode);
536        return nullptr, "Failed to memcpy msg");
537    uint32_t totalCount = msg->tlvCount + TLV_MAX;
538    msgNode->tlvOffset = static_cast<uint32_t *>(malloc(totalCount * sizeof(uint32_t)));
539    APPSPAWN_CHECK(msgNode->tlvOffset != nullptr, free(msgNode);
540        return nullptr, "Failed to alloc memory for recv message");
541    for (uint32_t i = 0; i < totalCount; i++) {
542        msgNode->tlvOffset[i] = INVALID_OFFSET;
543    }
544    return msgNode;
545}
546
547AppSpawningCtx *AppSpawnTestHelper::GetAppProperty(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle)
548{
549    AppSpawnReqMsgNode *reqNode = static_cast<AppSpawnReqMsgNode *>(reqHandle);
550    APPSPAWN_CHECK(reqNode != nullptr && reqNode->msg != nullptr, AppSpawnReqMsgFree(reqHandle);
551        return nullptr, "Invalid reqNode");
552
553    AppSpawnMsgNode *msgNode = CreateAppSpawnMsg(reqNode->msg);
554    APPSPAWN_CHECK(msgNode != nullptr, return nullptr, "Failed to alloc for msg");
555
556    uint32_t bufferSize = reqNode->msg->msgLen;
557    uint32_t currIndex = 0;
558    uint32_t bufferStart = sizeof(AppSpawnMsg);
559    ListNode *node = reqNode->msgBlocks.next;
560    while (node != &reqNode->msgBlocks) {
561        AppSpawnMsgBlock *block = ListEntry(node, AppSpawnMsgBlock, node);
562        int ret = memcpy_s(msgNode->buffer + currIndex, bufferSize - currIndex,
563            block->buffer + bufferStart, block->currentIndex - bufferStart);
564        if (ret != 0) {
565            AppSpawnReqMsgFree(reqHandle);
566            DeleteAppSpawnMsg(msgNode);
567            return nullptr;
568        }
569        currIndex += block->currentIndex - bufferStart;
570        bufferStart = 0;
571        node = node->next;
572    }
573    APPSPAWN_LOGV("GetAppProperty header magic 0x%{public}x type %{public}u id %{public}u len %{public}u %{public}s",
574        msgNode->msgHeader.magic, msgNode->msgHeader.msgType,
575        msgNode->msgHeader.msgId, msgNode->msgHeader.msgLen, msgNode->msgHeader.processName);
576
577    // delete reqHandle
578    AppSpawnReqMsgFree(reqHandle);
579    int ret = DecodeAppSpawnMsg(msgNode);
580    APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(msgNode);
581        return nullptr, "Decode msg fail");
582    AppSpawningCtx *property = CreateAppSpawningCtx();
583    APPSPAWN_CHECK_ONLY_EXPER(property != nullptr, DeleteAppSpawnMsg(msgNode);
584        return nullptr);
585    property->message = msgNode;
586    SetDefaultTestData();
587    return property;
588}
589
590void AppSpawnTestHelper::SetDefaultTestData()
591{
592    processName_ = std::string("com.example.myapplication");
593    defaultTestUid_ = 20010029;       // 20010029 test
594    defaultTestGid_ = 20010029;       // 20010029 test
595    defaultTestGidGroup_ = 20010029;  // 20010029 test
596    defaultTestBundleIndex_ = 100;    // 100 test
597    defaultApl_ = std::string("system_core");
598    defaultMsgFlags_ = 0;
599}
600
601int AppSpawnTestHelper::CreateSocket(int type)
602{
603    const uint32_t maxCount = 10;
604    uint32_t count = 0;
605    int socketId = -1;
606    while ((socketId < 0) && (count < maxCount)) {
607        usleep(20000);                        // 20000 20ms
608        socketId = CreateClientSocket(type, 2);  // 2s
609        if (socketId > 0) {
610            return socketId;
611        }
612        count++;
613    }
614    return socketId;
615}
616
617int AppSpawnTestHelper::CreateSendMsg(std::vector<uint8_t> &buffer, uint32_t msgType, uint32_t &msgLen,
618    const std::vector<AddTlvFunction> &addTlvFuncs)
619{
620    if (buffer.size() < sizeof(AppSpawnMsg)) {
621        return -1;
622    }
623    AppSpawnMsg *msg = reinterpret_cast<AppSpawnMsg *>(buffer.data());
624    msg->magic = APPSPAWN_MSG_MAGIC;
625    msg->msgType = msgType;
626    msg->msgLen = sizeof(AppSpawnMsg);
627    msg->msgId = 1;
628    msg->tlvCount = 0;
629    APPSPAWN_CHECK_ONLY_EXPER(strcpy_s(msg->processName, sizeof(msg->processName), processName_.c_str()) == 0,
630        return -1);
631    // add tlv
632    uint32_t currLen = sizeof(AppSpawnMsg);
633    for (auto addTlvFunc : addTlvFuncs) {
634        uint32_t realLen = 0;
635        uint32_t tlvCount = 0;
636        int ret = addTlvFunc(buffer.data() + currLen, buffer.size() - currLen, realLen, tlvCount);
637        APPSPAWN_CHECK(ret == 0 && (currLen + realLen) < buffer.size(),
638            return -1, "Failed add tlv to msg %{public}s", processName_.c_str());
639        msg->msgLen += realLen;
640        currLen += realLen;
641        msg->tlvCount += tlvCount;
642    }
643    msgLen = msg->msgLen;
644    APPSPAWN_LOGV("CreateSendMsg msgLen %{public}d", msgLen);
645    return 0;
646}
647
648static int inline AddOneTlv(uint8_t *buffer, uint32_t bufferLen, const AppSpawnTlv &tlv, const uint8_t *data)
649{
650    if (tlv.tlvLen > bufferLen) {
651        return -1;
652    }
653    int ret = memcpy_s(buffer, bufferLen, &tlv, sizeof(tlv));
654    APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
655    ret = memcpy_s(buffer + sizeof(tlv), bufferLen - sizeof(tlv), data, tlv.tlvLen - sizeof(tlv));
656    APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
657    return 0;
658}
659
660#define ADD_TLV(type, value, currLen, tlvCount)  \
661do {    \
662    AppSpawnTlv d_tlv = {}; \
663    d_tlv.tlvType = (type);    \
664    d_tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(value);   \
665    ret = AddOneTlv(buffer + (currLen), bufferLen - (currLen), d_tlv, (uint8_t *)&(value));   \
666    APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", d_tlv.tlvType);  \
667    (currLen) += d_tlv.tlvLen;    \
668    (tlvCount)++;   \
669} while (0)
670
671int AppSpawnTestHelper::AddBaseTlv(uint8_t *buffer, uint32_t bufferLen, uint32_t &realLen, uint32_t &tlvCount)
672{
673    // add app flage
674    uint32_t currLen = 0;
675    uint32_t flags[2] = {1, 0b1010};
676    AppSpawnTlv tlv = {};
677    tlv.tlvType = TLV_MSG_FLAGS;
678    tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(flags);
679    int ret = AddOneTlv(buffer + currLen, bufferLen - currLen, tlv, (uint8_t *)flags);
680    APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", tlv.tlvType);
681    currLen += tlv.tlvLen;
682    tlvCount++;
683
684    tlv.tlvType = TLV_PERMISSION;
685    tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(flags);
686    ret = AddOneTlv(buffer + currLen, bufferLen - currLen, tlv, (uint8_t *)flags);
687    APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", tlv.tlvType);
688    currLen += tlv.tlvLen;
689    tlvCount++;
690
691    AppDomainInfo domainInfo = {0, "normal"};
692    ADD_TLV(TLV_DOMAIN_INFO, domainInfo, currLen, tlvCount);
693
694    AppSpawnMsgAccessToken token = {12345678};  // 12345678
695    ADD_TLV(TLV_ACCESS_TOKEN_INFO, token, currLen, tlvCount);
696
697    AppSpawnMsgInternetInfo internetInfo = {0, 1};
698    ADD_TLV(TLV_INTERNET_INFO, internetInfo, currLen, tlvCount);
699
700    // add bundle info
701    AppBundleInfo info = {};
702    APPSPAWN_CHECK_ONLY_EXPER(strcpy_s(info.bundleName, sizeof(info.bundleName), "test-bundleName") == 0,
703        return -1);
704    info.bundleIndex = 100;  // 100 test index
705    ADD_TLV(TLV_BUNDLE_INFO, info, currLen, tlvCount);
706
707    // add dac
708    AppDacInfo  dacInfo = {};
709    dacInfo.uid = 20010029; // 20010029 test uid
710    dacInfo.gid = 20010029; // 20010029 test gid
711    dacInfo.gidCount = 2; // 2 count
712    dacInfo.gidTable[0] = 20010029; // 20010029 test gid
713    dacInfo.gidTable[1] = 20010030; // 20010030 test gid
714    ADD_TLV(TLV_DAC_INFO, dacInfo, currLen, tlvCount);
715    realLen = currLen;
716    return 0;
717}
718
719AppSpawnContent *AppSpawnTestHelper::StartSpawnServer(std::string &cmd, CmdArgs *&args)
720{
721    args = AppSpawnTestHelper::ToCmdList(cmd.c_str());
722    APPSPAWN_CHECK(args != nullptr, return nullptr, "Failed to alloc args");
723
724    AppSpawnStartArg startRrg = {};
725    startRrg.mode = MODE_FOR_APP_SPAWN;
726    startRrg.socketName = APPSPAWN_SOCKET_NAME;
727    startRrg.serviceName = APPSPAWN_SERVER_NAME;
728    startRrg.moduleType = MODULE_APPSPAWN;
729    startRrg.initArg = 1;
730    if (args->argc <= MODE_VALUE_INDEX) {  // appspawn start
731        startRrg.mode = MODE_FOR_APP_SPAWN;
732    } else if (strcmp(args->argv[MODE_VALUE_INDEX], "app_cold") == 0) {  // cold start
733        APPSPAWN_CHECK(args->argc >= ARG_NULL, free(args);
734            return nullptr, "Invalid arg for cold start %{public}d", args->argc);
735        startRrg.mode = MODE_FOR_APP_COLD_RUN;
736        startRrg.initArg = 0;
737    } else if (strcmp(args->argv[MODE_VALUE_INDEX], "nweb_cold") == 0) {  // cold start
738        APPSPAWN_CHECK(args->argc >= ARG_NULL, free(args);
739            return nullptr, "Invalid arg for cold start %{public}d", args->argc);
740        startRrg.mode = MODE_FOR_NWEB_COLD_RUN;
741        startRrg.serviceName = NWEBSPAWN_SERVER_NAME;
742        startRrg.initArg = 0;
743    } else if (strcmp(args->argv[MODE_VALUE_INDEX], NWEBSPAWN_SERVER_NAME) == 0) {  // nweb spawn start
744        startRrg.mode = MODE_FOR_NWEB_SPAWN;
745        startRrg.moduleType = MODULE_NWEBSPAWN;
746        startRrg.socketName = NWEBSPAWN_SOCKET_NAME;
747        startRrg.serviceName = NWEBSPAWN_SERVER_NAME;
748    }
749    APPSPAWN_LOGV("Start service %{public}s", startRrg.serviceName);
750    AppSpawnContent *content = StartSpawnService(&startRrg, APP_LEN_PROC_NAME, args->argc, args->argv);
751    if (content == nullptr) {
752        free(args);
753    }
754    return content;
755}
756}  // namespace OHOS
757
758MODULE_CONSTRUCTOR(void)
759{
760    MakeDirRec(APPSPAWN_MSG_DIR "appspawn", 0771, 1);
761    MakeDirRec(APPSPAWN_MSG_DIR "nwebspawn", 0771, 1);
762}
763