169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci
1669570cc8Sopenharmony_ci#include "appspawn_client.h"
1769570cc8Sopenharmony_ci
1869570cc8Sopenharmony_ci#include <errno.h>
1969570cc8Sopenharmony_ci#include <fcntl.h>
2069570cc8Sopenharmony_ci#include <pthread.h>
2169570cc8Sopenharmony_ci#include <string.h>
2269570cc8Sopenharmony_ci#include <unistd.h>
2369570cc8Sopenharmony_ci
2469570cc8Sopenharmony_ci#include <linux/in.h>
2569570cc8Sopenharmony_ci#include <linux/socket.h>
2669570cc8Sopenharmony_ci#include <linux/tcp.h>
2769570cc8Sopenharmony_ci#include <sys/socket.h>
2869570cc8Sopenharmony_ci#include <sys/time.h>
2969570cc8Sopenharmony_ci#include <sys/types.h>
3069570cc8Sopenharmony_ci#include <sys/un.h>
3169570cc8Sopenharmony_ci
3269570cc8Sopenharmony_ci#include "appspawn_mount_permission.h"
3369570cc8Sopenharmony_ci#include "appspawn_hook.h"
3469570cc8Sopenharmony_ci#include "appspawn_utils.h"
3569570cc8Sopenharmony_ci#include "parameter.h"
3669570cc8Sopenharmony_ci#include "securec.h"
3769570cc8Sopenharmony_ci
3869570cc8Sopenharmony_cistatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
3969570cc8Sopenharmony_cistatic AppSpawnReqMsgMgr *g_clientInstance[CLIENT_MAX] = {NULL};
4069570cc8Sopenharmony_ci
4169570cc8Sopenharmony_cistatic uint32_t GetDefaultTimeout(uint32_t def)
4269570cc8Sopenharmony_ci{
4369570cc8Sopenharmony_ci    uint32_t value = def;
4469570cc8Sopenharmony_ci    char data[32] = {};  // 32 length
4569570cc8Sopenharmony_ci    int ret = GetParameter("persist.appspawn.reqMgr.timeout", "0", data, sizeof(data));
4669570cc8Sopenharmony_ci    if (ret > 0 && strcmp(data, "0") != 0) {
4769570cc8Sopenharmony_ci        errno = 0;
4869570cc8Sopenharmony_ci        value = (uint32_t)atoi(data);
4969570cc8Sopenharmony_ci        return (errno != 0) ? def : value;
5069570cc8Sopenharmony_ci    }
5169570cc8Sopenharmony_ci    return value;
5269570cc8Sopenharmony_ci}
5369570cc8Sopenharmony_ci
5469570cc8Sopenharmony_cistatic int InitClientInstance(AppSpawnClientType type)
5569570cc8Sopenharmony_ci{
5669570cc8Sopenharmony_ci    pthread_mutex_lock(&g_mutex);
5769570cc8Sopenharmony_ci    if (g_clientInstance[type] != NULL) {
5869570cc8Sopenharmony_ci        pthread_mutex_unlock(&g_mutex);
5969570cc8Sopenharmony_ci        return 0;
6069570cc8Sopenharmony_ci    }
6169570cc8Sopenharmony_ci    AppSpawnReqMsgMgr *clientInstance = malloc(sizeof(AppSpawnReqMsgMgr) + RECV_BLOCK_LEN);
6269570cc8Sopenharmony_ci    if (clientInstance == NULL) {
6369570cc8Sopenharmony_ci        pthread_mutex_unlock(&g_mutex);
6469570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR;
6569570cc8Sopenharmony_ci    }
6669570cc8Sopenharmony_ci    // init
6769570cc8Sopenharmony_ci    clientInstance->type = type;
6869570cc8Sopenharmony_ci    clientInstance->msgNextId = 1;
6969570cc8Sopenharmony_ci    clientInstance->timeout = GetDefaultTimeout(TIMEOUT_DEF);
7069570cc8Sopenharmony_ci    clientInstance->maxRetryCount = MAX_RETRY_SEND_COUNT;
7169570cc8Sopenharmony_ci    clientInstance->socketId = -1;
7269570cc8Sopenharmony_ci    pthread_mutex_init(&clientInstance->mutex, NULL);
7369570cc8Sopenharmony_ci    // init recvBlock
7469570cc8Sopenharmony_ci    OH_ListInit(&clientInstance->recvBlock.node);
7569570cc8Sopenharmony_ci    clientInstance->recvBlock.blockSize = RECV_BLOCK_LEN;
7669570cc8Sopenharmony_ci    clientInstance->recvBlock.currentIndex = 0;
7769570cc8Sopenharmony_ci    g_clientInstance[type] = clientInstance;
7869570cc8Sopenharmony_ci    pthread_mutex_unlock(&g_mutex);
7969570cc8Sopenharmony_ci    return 0;
8069570cc8Sopenharmony_ci}
8169570cc8Sopenharmony_ci
8269570cc8Sopenharmony_ciAPPSPAWN_STATIC void CloseClientSocket(int socketId)
8369570cc8Sopenharmony_ci{
8469570cc8Sopenharmony_ci    APPSPAWN_LOGV("Closed socket with fd %{public}d", socketId);
8569570cc8Sopenharmony_ci    if (socketId >= 0) {
8669570cc8Sopenharmony_ci        int flag = 0;
8769570cc8Sopenharmony_ci        setsockopt(socketId, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
8869570cc8Sopenharmony_ci        close(socketId);
8969570cc8Sopenharmony_ci    }
9069570cc8Sopenharmony_ci}
9169570cc8Sopenharmony_ci
9269570cc8Sopenharmony_ciAPPSPAWN_STATIC int CreateClientSocket(uint32_t type, uint32_t timeout)
9369570cc8Sopenharmony_ci{
9469570cc8Sopenharmony_ci    const char *socketName;
9569570cc8Sopenharmony_ci
9669570cc8Sopenharmony_ci    switch (type) {
9769570cc8Sopenharmony_ci        case CLIENT_FOR_APPSPAWN:
9869570cc8Sopenharmony_ci            socketName = APPSPAWN_SOCKET_NAME;
9969570cc8Sopenharmony_ci            break;
10069570cc8Sopenharmony_ci        case CLIENT_FOR_CJAPPSPAWN:
10169570cc8Sopenharmony_ci            socketName = CJAPPSPAWN_SOCKET_NAME;
10269570cc8Sopenharmony_ci            break;
10369570cc8Sopenharmony_ci        case CLIENT_FOR_NATIVESPAWN:
10469570cc8Sopenharmony_ci            socketName = NATIVESPAWN_SOCKET_NAME;
10569570cc8Sopenharmony_ci            break;
10669570cc8Sopenharmony_ci        default:
10769570cc8Sopenharmony_ci            socketName = NWEBSPAWN_SOCKET_NAME;
10869570cc8Sopenharmony_ci            break;
10969570cc8Sopenharmony_ci    }
11069570cc8Sopenharmony_ci
11169570cc8Sopenharmony_ci    int socketFd = socket(AF_UNIX, SOCK_STREAM, 0);  // SOCK_SEQPACKET
11269570cc8Sopenharmony_ci    APPSPAWN_CHECK(socketFd >= 0, return -1,
11369570cc8Sopenharmony_ci        "Socket socket fd: %{public}s error: %{public}d", socketName, errno);
11469570cc8Sopenharmony_ci    int ret = 0;
11569570cc8Sopenharmony_ci    do {
11669570cc8Sopenharmony_ci        int flag = 1;
11769570cc8Sopenharmony_ci        ret = setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
11869570cc8Sopenharmony_ci        flag = 1;
11969570cc8Sopenharmony_ci        ret = setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &flag, sizeof(flag));
12069570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, break, "Set opt SO_PASSCRED name: %{public}s error: %{public}d", socketName, errno);
12169570cc8Sopenharmony_ci
12269570cc8Sopenharmony_ci        struct timeval timeoutVal = {timeout, 0};
12369570cc8Sopenharmony_ci        ret = setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, &timeoutVal, sizeof(timeoutVal));
12469570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, break, "Set opt SO_SNDTIMEO name: %{public}s error: %{public}d", socketName, errno);
12569570cc8Sopenharmony_ci        ret = setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, &timeoutVal, sizeof(timeoutVal));
12669570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, break, "Set opt SO_RCVTIMEO name: %{public}s error: %{public}d", socketName, errno);
12769570cc8Sopenharmony_ci
12869570cc8Sopenharmony_ci        ret = APPSPAWN_SYSTEM_ERROR;
12969570cc8Sopenharmony_ci        struct sockaddr_un addr;
13069570cc8Sopenharmony_ci        socklen_t pathSize = sizeof(addr.sun_path);
13169570cc8Sopenharmony_ci        int pathLen = snprintf_s(addr.sun_path, pathSize, (pathSize - 1), "%s%s", APPSPAWN_SOCKET_DIR, socketName);
13269570cc8Sopenharmony_ci        APPSPAWN_CHECK(pathLen > 0, break, "Format path %{public}s error: %{public}d", socketName, errno);
13369570cc8Sopenharmony_ci        addr.sun_family = AF_LOCAL;
13469570cc8Sopenharmony_ci        socklen_t socketAddrLen = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + (socklen_t)pathLen + 1);
13569570cc8Sopenharmony_ci        ret = connect(socketFd, (struct sockaddr *)(&addr), socketAddrLen);
13669570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, break,
13769570cc8Sopenharmony_ci            "Failed to connect %{public}s error: %{public}d", addr.sun_path, errno);
13869570cc8Sopenharmony_ci        APPSPAWN_LOGI("Create socket success %{public}s socketFd: %{public}d", addr.sun_path, socketFd);
13969570cc8Sopenharmony_ci        return socketFd;
14069570cc8Sopenharmony_ci    } while (0);
14169570cc8Sopenharmony_ci    CloseClientSocket(socketFd);
14269570cc8Sopenharmony_ci    return -1;
14369570cc8Sopenharmony_ci}
14469570cc8Sopenharmony_ci
14569570cc8Sopenharmony_ciAPPSPAWN_STATIC int UpdateSocketTimeout(uint32_t timeout, int socketFd)
14669570cc8Sopenharmony_ci{
14769570cc8Sopenharmony_ci    struct timeval timeoutVal = {timeout, 0};
14869570cc8Sopenharmony_ci    int ret = setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, &timeoutVal, sizeof(timeoutVal));
14969570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return ret, "Set opt SO_SNDTIMEO error: %{public}d", errno);
15069570cc8Sopenharmony_ci    ret = setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, &timeoutVal, sizeof(timeoutVal));
15169570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return ret, "Set opt SO_RCVTIMEO error: %{public}d", errno);
15269570cc8Sopenharmony_ci    return ret;
15369570cc8Sopenharmony_ci}
15469570cc8Sopenharmony_ci
15569570cc8Sopenharmony_cistatic int ReadMessage(int socketFd, uint32_t sendMsgId, uint8_t *buf, int len, AppSpawnResult *result)
15669570cc8Sopenharmony_ci{
15769570cc8Sopenharmony_ci    ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len));
15869570cc8Sopenharmony_ci    APPSPAWN_CHECK(rLen >= 0, return APPSPAWN_TIMEOUT,
15969570cc8Sopenharmony_ci        "Read message from fd %{public}d rLen %{public}zd errno: %{public}d", socketFd, rLen, errno);
16069570cc8Sopenharmony_ci    if ((size_t)rLen >= sizeof(AppSpawnResponseMsg)) {
16169570cc8Sopenharmony_ci        AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)(buf);
16269570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_LOG(sendMsgId == msg->msgHdr.msgId,
16369570cc8Sopenharmony_ci            "Invalid msg recvd %{public}u %{public}u", sendMsgId, msg->msgHdr.msgId);
16469570cc8Sopenharmony_ci        return memcpy_s(result, sizeof(AppSpawnResult), &msg->result, sizeof(msg->result));
16569570cc8Sopenharmony_ci    }
16669570cc8Sopenharmony_ci    return APPSPAWN_TIMEOUT;
16769570cc8Sopenharmony_ci}
16869570cc8Sopenharmony_ci
16969570cc8Sopenharmony_cistatic int WriteMessage(int socketFd, const uint8_t *buf, ssize_t len, int *fds, int *fdCount)
17069570cc8Sopenharmony_ci{
17169570cc8Sopenharmony_ci    ssize_t written = 0;
17269570cc8Sopenharmony_ci    ssize_t remain = len;
17369570cc8Sopenharmony_ci    const uint8_t *offset = buf;
17469570cc8Sopenharmony_ci    struct iovec iov = {
17569570cc8Sopenharmony_ci        .iov_base = (void *) offset,
17669570cc8Sopenharmony_ci        .iov_len = len,
17769570cc8Sopenharmony_ci    };
17869570cc8Sopenharmony_ci    struct msghdr msg = {
17969570cc8Sopenharmony_ci        .msg_iov = &iov,
18069570cc8Sopenharmony_ci        .msg_iovlen = 1,
18169570cc8Sopenharmony_ci    };
18269570cc8Sopenharmony_ci    char *ctrlBuffer = NULL;
18369570cc8Sopenharmony_ci    if (fdCount != NULL && fds != NULL && *fdCount > 0) {
18469570cc8Sopenharmony_ci        msg.msg_controllen = CMSG_SPACE(*fdCount * sizeof(int));
18569570cc8Sopenharmony_ci        ctrlBuffer = (char *) malloc(msg.msg_controllen);
18669570cc8Sopenharmony_ci        APPSPAWN_CHECK(ctrlBuffer != NULL, return -1,
18769570cc8Sopenharmony_ci            "WriteMessage fail to alloc memory for msg_control %{public}d %{public}d", msg.msg_controllen, errno);
18869570cc8Sopenharmony_ci        msg.msg_control = ctrlBuffer;
18969570cc8Sopenharmony_ci        struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
19069570cc8Sopenharmony_ci        APPSPAWN_CHECK(cmsg != NULL, free(ctrlBuffer);
19169570cc8Sopenharmony_ci            return -1, "WriteMessage fail to get CMSG_FIRSTHDR %{public}d", errno);
19269570cc8Sopenharmony_ci        cmsg->cmsg_len = CMSG_LEN(*fdCount * sizeof(int));
19369570cc8Sopenharmony_ci        cmsg->cmsg_type = SCM_RIGHTS;
19469570cc8Sopenharmony_ci        cmsg->cmsg_level = SOL_SOCKET;
19569570cc8Sopenharmony_ci        int ret = memcpy_s(CMSG_DATA(cmsg), cmsg->cmsg_len, fds, *fdCount * sizeof(int));
19669570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, free(ctrlBuffer);
19769570cc8Sopenharmony_ci            return -1, "WriteMessage fail to memcpy_s fd %{public}d", errno);
19869570cc8Sopenharmony_ci        APPSPAWN_LOGV("build fd info count %{public}d", *fdCount);
19969570cc8Sopenharmony_ci    }
20069570cc8Sopenharmony_ci    for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) {
20169570cc8Sopenharmony_ci        errno = 0;
20269570cc8Sopenharmony_ci        wLen = sendmsg(socketFd, &msg, MSG_NOSIGNAL);
20369570cc8Sopenharmony_ci        APPSPAWN_LOGV("Write msg errno: %{public}d %{public}zd", errno, wLen);
20469570cc8Sopenharmony_ci        APPSPAWN_CHECK((wLen > 0) || (errno == EINTR), free(ctrlBuffer);
20569570cc8Sopenharmony_ci            return -errno,
20669570cc8Sopenharmony_ci            "Failed to write message to fd %{public}d, wLen %{public}zd errno: %{public}d", socketFd, wLen, errno);
20769570cc8Sopenharmony_ci    }
20869570cc8Sopenharmony_ci    free(ctrlBuffer);
20969570cc8Sopenharmony_ci    return written == len ? 0 : -EFAULT;
21069570cc8Sopenharmony_ci}
21169570cc8Sopenharmony_ci
21269570cc8Sopenharmony_cistatic int HandleMsgSend(AppSpawnReqMsgMgr *reqMgr, int socketId, AppSpawnReqMsgNode *reqNode)
21369570cc8Sopenharmony_ci{
21469570cc8Sopenharmony_ci    APPSPAWN_LOGV("HandleMsgSend reqId: %{public}u msgId: %{public}d", reqNode->reqId, reqNode->msg->msgId);
21569570cc8Sopenharmony_ci    ListNode *sendNode = reqNode->msgBlocks.next;
21669570cc8Sopenharmony_ci    uint32_t currentIndex = 0;
21769570cc8Sopenharmony_ci    bool sendFd = true;
21869570cc8Sopenharmony_ci    while (sendNode != NULL && sendNode != &reqNode->msgBlocks) {
21969570cc8Sopenharmony_ci        AppSpawnMsgBlock *sendBlock = (AppSpawnMsgBlock *)ListEntry(sendNode, AppSpawnMsgBlock, node);
22069570cc8Sopenharmony_ci        int ret = WriteMessage(socketId, sendBlock->buffer, sendBlock->currentIndex,
22169570cc8Sopenharmony_ci            sendFd ? reqNode->fds : NULL,
22269570cc8Sopenharmony_ci            sendFd ? &reqNode->fdCount : NULL);
22369570cc8Sopenharmony_ci        currentIndex += sendBlock->currentIndex;
22469570cc8Sopenharmony_ci        APPSPAWN_LOGV("Write msg ret: %{public}d msgId: %{public}u %{public}u %{public}u",
22569570cc8Sopenharmony_ci            ret, reqNode->msg->msgId, reqNode->msg->msgLen, currentIndex);
22669570cc8Sopenharmony_ci        if (ret == 0) {
22769570cc8Sopenharmony_ci            sendFd = false;
22869570cc8Sopenharmony_ci            sendNode = sendNode->next;
22969570cc8Sopenharmony_ci            continue;
23069570cc8Sopenharmony_ci        }
23169570cc8Sopenharmony_ci        APPSPAWN_LOGE("Send msg fail reqId: %{public}u msgId: %{public}d ret: %{public}d",
23269570cc8Sopenharmony_ci            reqNode->reqId, reqNode->msg->msgId, ret);
23369570cc8Sopenharmony_ci        return ret;
23469570cc8Sopenharmony_ci    }
23569570cc8Sopenharmony_ci    return 0;
23669570cc8Sopenharmony_ci}
23769570cc8Sopenharmony_ci
23869570cc8Sopenharmony_ciAPPSPAWN_STATIC void TryCreateSocket(AppSpawnReqMsgMgr *reqMgr)
23969570cc8Sopenharmony_ci{
24069570cc8Sopenharmony_ci    uint32_t retryCount = 1;
24169570cc8Sopenharmony_ci    while (retryCount <= reqMgr->maxRetryCount) {
24269570cc8Sopenharmony_ci        if (reqMgr->socketId < 0) {
24369570cc8Sopenharmony_ci            reqMgr->socketId = CreateClientSocket(reqMgr->type, reqMgr->timeout);
24469570cc8Sopenharmony_ci        }
24569570cc8Sopenharmony_ci        if (reqMgr->socketId < 0) {
24669570cc8Sopenharmony_ci            APPSPAWN_LOGV("Failed to create socket, try again");
24769570cc8Sopenharmony_ci            usleep(RETRY_TIME);
24869570cc8Sopenharmony_ci            retryCount++;
24969570cc8Sopenharmony_ci            continue;
25069570cc8Sopenharmony_ci        }
25169570cc8Sopenharmony_ci        break;
25269570cc8Sopenharmony_ci    }
25369570cc8Sopenharmony_ci}
25469570cc8Sopenharmony_ci
25569570cc8Sopenharmony_cistatic int ClientSendMsg(AppSpawnReqMsgMgr *reqMgr, AppSpawnReqMsgNode *reqNode, AppSpawnResult *result)
25669570cc8Sopenharmony_ci{
25769570cc8Sopenharmony_ci    uint32_t retryCount = 1;
25869570cc8Sopenharmony_ci    int isColdRun = reqNode->isAsan;
25969570cc8Sopenharmony_ci    while (retryCount <= reqMgr->maxRetryCount) {
26069570cc8Sopenharmony_ci        if (reqMgr->socketId < 0) { // try create socket
26169570cc8Sopenharmony_ci            TryCreateSocket(reqMgr);
26269570cc8Sopenharmony_ci            if (reqMgr->socketId < 0) {
26369570cc8Sopenharmony_ci                usleep(RETRY_TIME);
26469570cc8Sopenharmony_ci                retryCount++;
26569570cc8Sopenharmony_ci                continue;
26669570cc8Sopenharmony_ci            }
26769570cc8Sopenharmony_ci        }
26869570cc8Sopenharmony_ci        if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) {
26969570cc8Sopenharmony_ci            UpdateSocketTimeout(ASAN_TIMEOUT, reqMgr->socketId);
27069570cc8Sopenharmony_ci        }
27169570cc8Sopenharmony_ci
27269570cc8Sopenharmony_ci        if (reqNode->msg->msgId == 0) {
27369570cc8Sopenharmony_ci            reqNode->msg->msgId = reqMgr->msgNextId++;
27469570cc8Sopenharmony_ci        }
27569570cc8Sopenharmony_ci        int ret = HandleMsgSend(reqMgr, reqMgr->socketId, reqNode);
27669570cc8Sopenharmony_ci        if (ret == 0) {
27769570cc8Sopenharmony_ci            ret = ReadMessage(reqMgr->socketId, reqNode->msg->msgId,
27869570cc8Sopenharmony_ci                reqMgr->recvBlock.buffer, reqMgr->recvBlock.blockSize, result);
27969570cc8Sopenharmony_ci        }
28069570cc8Sopenharmony_ci        if (ret == 0) {
28169570cc8Sopenharmony_ci            if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) {
28269570cc8Sopenharmony_ci                UpdateSocketTimeout(reqMgr->timeout, reqMgr->socketId);
28369570cc8Sopenharmony_ci            }
28469570cc8Sopenharmony_ci            return 0;
28569570cc8Sopenharmony_ci        }
28669570cc8Sopenharmony_ci        // retry
28769570cc8Sopenharmony_ci        CloseClientSocket(reqMgr->socketId);
28869570cc8Sopenharmony_ci        reqMgr->socketId = -1;
28969570cc8Sopenharmony_ci        reqMgr->msgNextId = 1;
29069570cc8Sopenharmony_ci        reqNode->msg->msgId = 0;
29169570cc8Sopenharmony_ci        usleep(RETRY_TIME);
29269570cc8Sopenharmony_ci        retryCount++;
29369570cc8Sopenharmony_ci    }
29469570cc8Sopenharmony_ci    return APPSPAWN_TIMEOUT;
29569570cc8Sopenharmony_ci}
29669570cc8Sopenharmony_ci
29769570cc8Sopenharmony_ciint AppSpawnClientInit(const char *serviceName, AppSpawnClientHandle *handle)
29869570cc8Sopenharmony_ci{
29969570cc8Sopenharmony_ci    APPSPAWN_CHECK(serviceName != NULL, return APPSPAWN_ARG_INVALID, "Invalid service name");
30069570cc8Sopenharmony_ci    APPSPAWN_CHECK(handle != NULL, return APPSPAWN_ARG_INVALID, "Invalid handle for %{public}s", serviceName);
30169570cc8Sopenharmony_ci    APPSPAWN_LOGV("AppSpawnClientInit serviceName %{public}s", serviceName);
30269570cc8Sopenharmony_ci    AppSpawnClientType type = CLIENT_FOR_APPSPAWN;
30369570cc8Sopenharmony_ci    if (strcmp(serviceName, CJAPPSPAWN_SERVER_NAME) == 0) {
30469570cc8Sopenharmony_ci        type = CLIENT_FOR_CJAPPSPAWN;
30569570cc8Sopenharmony_ci    } else if (strcmp(serviceName, NWEBSPAWN_SERVER_NAME) == 0 || strstr(serviceName, NWEBSPAWN_SOCKET_NAME) != NULL) {
30669570cc8Sopenharmony_ci        type = CLIENT_FOR_NWEBSPAWN;
30769570cc8Sopenharmony_ci    } else if (strcmp(serviceName, NATIVESPAWN_SERVER_NAME) == 0 ||
30869570cc8Sopenharmony_ci        strstr(serviceName, NATIVESPAWN_SOCKET_NAME) != NULL) {
30969570cc8Sopenharmony_ci        type = CLIENT_FOR_NATIVESPAWN;
31069570cc8Sopenharmony_ci    }
31169570cc8Sopenharmony_ci    int ret = InitClientInstance(type);
31269570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to create reqMgr");
31369570cc8Sopenharmony_ci    *handle = (AppSpawnClientHandle)g_clientInstance[type];
31469570cc8Sopenharmony_ci    return 0;
31569570cc8Sopenharmony_ci}
31669570cc8Sopenharmony_ci
31769570cc8Sopenharmony_ciint AppSpawnClientDestroy(AppSpawnClientHandle handle)
31869570cc8Sopenharmony_ci{
31969570cc8Sopenharmony_ci    AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
32069570cc8Sopenharmony_ci    APPSPAWN_CHECK(reqMgr != NULL, return APPSPAWN_SYSTEM_ERROR, "Invalid reqMgr");
32169570cc8Sopenharmony_ci    pthread_mutex_lock(&g_mutex);
32269570cc8Sopenharmony_ci    if (reqMgr->type < sizeof(g_clientInstance) / sizeof(g_clientInstance[0])) {
32369570cc8Sopenharmony_ci        g_clientInstance[reqMgr->type] = NULL;
32469570cc8Sopenharmony_ci    }
32569570cc8Sopenharmony_ci    pthread_mutex_unlock(&g_mutex);
32669570cc8Sopenharmony_ci    pthread_mutex_destroy(&reqMgr->mutex);
32769570cc8Sopenharmony_ci    if (reqMgr->socketId >= 0) {
32869570cc8Sopenharmony_ci        CloseClientSocket(reqMgr->socketId);
32969570cc8Sopenharmony_ci        reqMgr->socketId = -1;
33069570cc8Sopenharmony_ci    }
33169570cc8Sopenharmony_ci    free(reqMgr);
33269570cc8Sopenharmony_ci    return 0;
33369570cc8Sopenharmony_ci}
33469570cc8Sopenharmony_ci
33569570cc8Sopenharmony_ciint AppSpawnClientSendMsg(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle, AppSpawnResult *result)
33669570cc8Sopenharmony_ci{
33769570cc8Sopenharmony_ci    APPSPAWN_CHECK(result != NULL, AppSpawnReqMsgFree(reqHandle);
33869570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid result");
33969570cc8Sopenharmony_ci    result->result = APPSPAWN_ARG_INVALID;
34069570cc8Sopenharmony_ci    result->pid = 0;
34169570cc8Sopenharmony_ci    AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
34269570cc8Sopenharmony_ci    APPSPAWN_CHECK(reqMgr != NULL, AppSpawnReqMsgFree(reqHandle);
34369570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid reqMgr");
34469570cc8Sopenharmony_ci    AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
34569570cc8Sopenharmony_ci    APPSPAWN_CHECK(reqNode != NULL && reqNode->msg != NULL, AppSpawnReqMsgFree(reqHandle);
34669570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid msgReq");
34769570cc8Sopenharmony_ci
34869570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnClientSendMsg reqId: %{public}u msgLen: %{public}u %{public}s",
34969570cc8Sopenharmony_ci        reqNode->reqId, reqNode->msg->msgLen, reqNode->msg->processName);
35069570cc8Sopenharmony_ci    pthread_mutex_lock(&reqMgr->mutex);
35169570cc8Sopenharmony_ci    int ret = ClientSendMsg(reqMgr, reqNode, result);
35269570cc8Sopenharmony_ci    if (ret != 0) {
35369570cc8Sopenharmony_ci        result->result = ret;
35469570cc8Sopenharmony_ci    }
35569570cc8Sopenharmony_ci    pthread_mutex_unlock(&reqMgr->mutex);
35669570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnClientSendMsg reqId: %{public}u end result: 0x%{public}x pid: %{public}d",
35769570cc8Sopenharmony_ci        reqNode->reqId, result->result, result->pid);
35869570cc8Sopenharmony_ci    AppSpawnReqMsgFree(reqHandle);
35969570cc8Sopenharmony_ci    return ret;
36069570cc8Sopenharmony_ci}
361