control_fd_service.c 5.5 KB
Newer Older
M
Mupceet 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <fcntl.h>
#include <unistd.h>

#include "beget_ext.h"
#include "control_fd.h"
#include "init_utils.h"
#include "securec.h"

static CmdService g_cmdService;

CallbackControlFdProcess g_controlFdFunc = NULL;

M
Mupceet 已提交
27
static void OnClose(const TaskHandle task)
M
Mupceet 已提交
28
{
M
Mupceet 已提交
29 30 31 32
    CmdTask *agent = (CmdTask *)LE_GetUserData(task);
    BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");
    OH_ListRemove(&agent->item);
    OH_ListInit(&agent->item);
M
Mupceet 已提交
33 34 35 36 37 38 39
}

static void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen)
{
    if (buffer == NULL) {
        return;
    }
M
Mupceet 已提交
40 41 42
    CmdTask *agent = (CmdTask *)LE_GetUserData(task);
    BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");

M
Mupceet 已提交
43 44
    // parse msg to exec
    CmdMessage *msg = (CmdMessage *)buffer;
C
codex  
chengjinsong 已提交
45
    if ((msg->type >= ACTION_MAX) || (msg->cmd[0] == '\0') || (msg->ptyName[0] == '\0')) {
M
Mupceet 已提交
46
        BEGET_LOGE("[control_fd] Received msg is invaild");
M
Mupceet 已提交
47 48 49
        return;
    }

M
Mupceet 已提交
50 51 52 53 54 55 56 57 58
    agent->pid = fork();
    if (agent->pid == 0) {
        OpenConsole();
        char *realPath = GetRealPath(msg->ptyName);
        BEGET_ERROR_CHECK(realPath != NULL, return, "Failed get realpath, err=%d", errno);
        char *strl = strstr(realPath, "/dev/pts");
        BEGET_ERROR_CHECK(strl != NULL, return, "pty slave path %s is invaild", realPath);
        int fd = open(realPath, O_RDWR);
        free(realPath);
M
Mupceet 已提交
59
        BEGET_ERROR_CHECK(fd >= 0, return, "Failed open %s, err=%d", msg->ptyName, errno);
M
Mupceet 已提交
60 61 62 63
        (void)dup2(fd, STDIN_FILENO);
        (void)dup2(fd, STDOUT_FILENO);
        (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2
        (void)close(fd);
C
codex  
chengjinsong 已提交
64 65 66
        if (g_controlFdFunc != NULL) {
            g_controlFdFunc(msg->type, msg->cmd, NULL);
        }
M
Mupceet 已提交
67
        exit(0);
M
Mupceet 已提交
68
    } else if (agent->pid < 0) {
M
Mupceet 已提交
69 70 71 72 73 74 75 76
        BEGET_LOGE("[control_fd] Failed fork service");
    }
    return;
}

static int SendMessage(LoopHandle loop, TaskHandle task, const char *message)
{
    if (message == NULL) {
77
        BEGET_LOGE("[control_fd] Invalid parameter");
M
Mupceet 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
        return -1;
    }
    BufferHandle handle = NULL;
    uint32_t bufferSize = strlen(message) + 1;
    handle = LE_CreateBuffer(loop, bufferSize);
    char *buff = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize);
    BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info");
    int ret = memcpy_s(buff, bufferSize, message, strlen(message) + 1);
    BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), task, handle);
        return -1, "[control_fd] Failed memcpy_s err=%d", errno);
    LE_STATUS status = LE_Send(loop, task, handle, strlen(message) + 1);
    BEGET_ERROR_CHECK(status == LE_SUCCESS, return -1, "[control_fd] Failed le send msg");
    return 0;
}

L
laiguizhong 已提交
93
static int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server)
M
Mupceet 已提交
94 95 96 97
{
    TaskHandle client = NULL;
    LE_StreamInfo info = {};
    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
M
Mupceet 已提交
98 99
    info.baseInfo.close = OnClose;
    info.baseInfo.userDataSize = sizeof(CmdTask);
L
laiguizhong 已提交
100
    info.disConnectComplete = NULL;
101
    info.sendMessageComplete = NULL;
M
Mupceet 已提交
102 103 104
    info.recvMessage = CmdOnRecvMessage;
    int ret = LE_AcceptStreamClient(LE_GetDefaultLoop(), server, &client, &info);
    BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed accept stream")
M
Mupceet 已提交
105
    CmdTask *agent = (CmdTask *)LE_GetUserData(client);
M
Mupceet 已提交
106 107
    BEGET_ERROR_CHECK(agent != NULL, return -1, "[control_fd] Invalid agent");
    agent->task = client;
M
Mupceet 已提交
108
    OH_ListInit(&agent->item);
M
Mupceet 已提交
109 110
    ret = SendMessage(LE_GetDefaultLoop(), agent->task, "connect success.");
    BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed send msg");
M
Mupceet 已提交
111
    OH_ListAddTail(&g_cmdService.head, &agent->item);
M
Mupceet 已提交
112 113 114 115 116 117
    return 0;
}

void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func)
{
    if ((socketPath == NULL) || (func == NULL)) {
118
        BEGET_LOGE("[control_fd] Invalid parameter");
M
Mupceet 已提交
119 120
        return;
    }
M
Mupceet 已提交
121
    OH_ListInit(&g_cmdService.head);
M
Mupceet 已提交
122 123 124 125 126
    LE_StreamServerInfo info = {};
    info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE;
    info.server = (char *)socketPath;
    info.socketId = -1;
    info.baseInfo.close = NULL;
L
laiguizhong 已提交
127
    info.disConnectComplete = NULL;
L
laiguizhong 已提交
128
    info.incommingConnect = CmdOnIncommingConnect;
M
Mupceet 已提交
129 130 131 132 133
    info.sendMessageComplete = NULL;
    info.recvMessage = NULL;
    g_controlFdFunc = func;
    (void)LE_CreateStreamServer(LE_GetDefaultLoop(), &g_cmdService.serverTask, &info);
}
M
Mupceet 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

static int ClientTraversalProc(ListNode *node, void *data)
{
    CmdTask *info = ListEntry(node, CmdTask, item);
    int pid = *(int *)data;
    return pid - info->pid;
}

void CmdServiceProcessDelClient(pid_t pid)
{
    ListNode *node = OH_ListFind(&g_cmdService.head, (void *)&pid, ClientTraversalProc);
    if (node != NULL) {
        CmdTask *agent = ListEntry(node, CmdTask, item);
        OH_ListRemove(&agent->item);
        OH_ListInit(&agent->item);
        LE_CloseTask(LE_GetDefaultLoop(), agent->task);
    }
}