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#ifndef APPSPAWN_MANAGER_H
17#define APPSPAWN_MANAGER_H
18
19#include <limits.h>
20#include <stdbool.h>
21#include <unistd.h>
22
23#include "appspawn.h"
24#include "appspawn_hook.h"
25#include "appspawn_msg.h"
26#include "appspawn_server.h"
27#include "appspawn_utils.h"
28#include "list.h"
29#include "loop_event.h"
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#define MODE_ID_INDEX 1
36#define MODE_VALUE_INDEX 2
37#define FD_ID_INDEX 3
38#define FD_VALUE_INDEX 4
39#define FLAGS_VALUE_INDEX 5
40#define SHM_SIZE_INDEX 6
41#define PARAM_ID_INDEX 7
42#define PARAM_VALUE_INDEX 8
43#define CLIENT_ID_INDEX 9
44#define ARG_NULL 10
45
46#define MAX_DIED_PROCESS_COUNT 5
47
48#define INVALID_OFFSET 0xffffffff
49
50#define APP_STATE_IDLE 1
51#define APP_STATE_SPAWNING 2
52#define APPSPAWN_MAX_TIME 3000000
53
54#define APPSPAWN_INLINE __attribute__((always_inline)) inline
55
56typedef struct AppSpawnContent AppSpawnContent;
57typedef struct AppSpawnClient AppSpawnClient;
58typedef struct TagAppSpawnConnection AppSpawnConnection;
59
60typedef struct TagAppSpawnMsgNode {
61    AppSpawnConnection *connection;
62    AppSpawnMsg msgHeader;
63    uint32_t tlvCount;
64    uint32_t *tlvOffset;  // 记录属性的在msg中的偏移,不完全拷贝试消息完整
65    uint8_t *buffer;
66} AppSpawnMsgNode;
67
68typedef struct {
69    int32_t fd[2];  // 2 fd count
70    WatcherHandle watcherHandle;
71    WatcherHandle pidFdWatcherHandle;
72    TimerHandle timer;
73    char *childMsg;
74    uint32_t msgSize;
75    char *coldRunPath;
76} AppSpawnForkCtx;
77
78typedef struct TagAppSpawningCtx {
79    AppSpawnClient client;
80    struct ListNode node;
81    AppSpawnForkCtx forkCtx;
82    AppSpawnMsgNode *message;
83    bool isPrefork;
84    pid_t pid;
85    int state;
86    struct timespec spawnStart;
87} AppSpawningCtx;
88
89typedef struct TagAppSpawnedProcess {
90    struct ListNode node;
91    uid_t uid;
92    pid_t pid;
93    uint32_t max;
94    int exitStatus;
95    struct timespec spawnStart;
96    struct timespec spawnEnd;
97#ifdef DEBUG_BEGETCTL_BOOT
98    AppSpawnMsgNode *message;
99#endif
100    bool isDebuggable;
101    char name[0];
102} AppSpawnedProcess;
103
104typedef struct SpawnTime {
105    int minAppspawnTime;
106    int maxAppspawnTime;
107} SpawnTime;
108
109typedef struct TagAppSpawnMgr {
110    AppSpawnContent content;
111    TaskHandle server;
112    SignalHandle sigHandler;
113    pid_t servicePid;
114    struct ListNode appQueue;  // save app pid and name
115    uint32_t diedAppCount;
116    uint32_t flags;
117    struct ListNode diedQueue;      // save app pid and name
118    struct ListNode appSpawnQueue;  // save app pid and name
119    struct timespec perLoadStart;
120    struct timespec perLoadEnd;
121    struct ListNode extData;
122    struct SpawnTime spawnTime;
123} AppSpawnMgr;
124
125/**
126 * @brief App Spawn Mgr object op
127 *
128 */
129AppSpawnMgr *CreateAppSpawnMgr(int mode);
130AppSpawnMgr *GetAppSpawnMgr(void);
131void DeleteAppSpawnMgr(AppSpawnMgr *mgr);
132AppSpawnContent *GetAppSpawnContent(void);
133
134/**
135 * @brief 孵化成功后进程或者app实例的操作
136 *
137 */
138typedef void (*AppTraversal)(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data);
139void TraversalSpawnedProcess(AppTraversal traversal, void *data);
140AppSpawnedProcess *AddSpawnedProcess(pid_t pid, const char *processName, bool isDebuggable);
141AppSpawnedProcess *GetSpawnedProcess(pid_t pid);
142AppSpawnedProcess *GetSpawnedProcessByName(const char *name);
143void TerminateSpawnedProcess(AppSpawnedProcess *node);
144
145/**
146 * @brief 孵化过程中的ctx对象的操作
147 *
148 */
149typedef void (*ProcessTraversal)(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data);
150void AppSpawningCtxTraversal(ProcessTraversal traversal, void *data);
151AppSpawningCtx *GetAppSpawningCtxByPid(pid_t pid);
152AppSpawningCtx *CreateAppSpawningCtx();
153void DeleteAppSpawningCtx(AppSpawningCtx *property);
154int KillAndWaitStatus(pid_t pid, int sig, int *exitStatus);
155
156/**
157 * @brief 消息解析、处理
158 *
159 */
160void ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message);
161int ProcessTerminationStatusMsg(const AppSpawnMsgNode *message, AppSpawnResult *result);
162
163AppSpawnMsgNode *CreateAppSpawnMsg(void);
164void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode);
165int CheckAppSpawnMsg(const AppSpawnMsgNode *message);
166int DecodeAppSpawnMsg(AppSpawnMsgNode *message);
167int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen,
168    AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder);
169AppSpawnMsgNode *RebuildAppSpawnMsgNode(AppSpawnMsgNode *message, AppSpawnedProcess *appInfo);
170
171/**
172 * @brief 消息内容操作接口
173 *
174 */
175void DumpAppSpawnMsg(const AppSpawnMsgNode *message);
176void *GetAppSpawnMsgInfo(const AppSpawnMsgNode *message, int type);
177void *GetAppSpawnMsgExtInfo(const AppSpawnMsgNode *message, const char *name, uint32_t *len);
178int CheckAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
179int SetAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
180
181APPSPAWN_INLINE int IsSpawnServer(const AppSpawnMgr *content)
182{
183    return (content != NULL) && (content->servicePid == getpid());
184}
185
186APPSPAWN_INLINE int IsNWebSpawnMode(const AppSpawnMgr *content)
187{
188    return (content != NULL) &&
189        (content->content.mode == MODE_FOR_NWEB_SPAWN || content->content.mode == MODE_FOR_NWEB_COLD_RUN);
190}
191
192APPSPAWN_INLINE int IsColdRunMode(const AppSpawnMgr *content)
193{
194    return (content != NULL) &&
195        (content->content.mode == MODE_FOR_APP_COLD_RUN || content->content.mode == MODE_FOR_NWEB_COLD_RUN);
196}
197
198APPSPAWN_INLINE int IsDeveloperModeOn(const AppSpawningCtx *property)
199{
200    return (property != NULL && ((property->client.flags & APP_DEVELOPER_MODE) == APP_DEVELOPER_MODE));
201}
202
203APPSPAWN_INLINE int IsJitFortModeOn(const AppSpawningCtx *property)
204{
205    return (property != NULL && ((property->client.flags & APP_JITFORT_MODE) == APP_JITFORT_MODE));
206}
207
208APPSPAWN_INLINE int GetAppSpawnMsgType(const AppSpawningCtx *appProperty)
209{
210    return (appProperty != NULL && appProperty->message != NULL) ?
211        appProperty->message->msgHeader.msgType : MAX_TYPE_INVALID;
212}
213
214APPSPAWN_INLINE const char *GetProcessName(const AppSpawningCtx *property)
215{
216    if (property == NULL || property->message == NULL) {
217        return NULL;
218    }
219    return property->message->msgHeader.processName;
220}
221
222APPSPAWN_INLINE const char *GetBundleName(const AppSpawningCtx *property)
223{
224    if (property == NULL || property->message == NULL) {
225        return NULL;
226    }
227    AppSpawnMsgBundleInfo *info = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(property->message, TLV_BUNDLE_INFO);
228    if (info != NULL) {
229        return info->bundleName;
230    }
231    return NULL;
232}
233
234APPSPAWN_INLINE void *GetAppProperty(const AppSpawningCtx *property, uint32_t type)
235{
236    APPSPAWN_CHECK(property != NULL && property->message != NULL,
237        return NULL, "Invalid property for type %{public}u", type);
238    return GetAppSpawnMsgInfo(property->message, type);
239}
240
241APPSPAWN_INLINE void *GetAppPropertyExt(const AppSpawningCtx *property, const char *name, uint32_t *len)
242{
243    APPSPAWN_CHECK(name != NULL, return NULL, "Invalid name ");
244    APPSPAWN_CHECK(property != NULL && property->message != NULL,
245        return NULL, "Invalid property for name %{public}s", name);
246    return GetAppSpawnMsgExtInfo(property->message, name, len);
247}
248
249APPSPAWN_INLINE int CheckAppMsgFlagsSet(const AppSpawningCtx *property, uint32_t index)
250{
251    APPSPAWN_CHECK(property != NULL && property->message != NULL,
252        return 0, "Invalid property for name %{public}u", TLV_MSG_FLAGS);
253    return CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, index);
254}
255
256APPSPAWN_INLINE int CheckAppPermissionFlagSet(const AppSpawningCtx *property, uint32_t index)
257{
258    APPSPAWN_CHECK(property != NULL && property->message != NULL,
259        return 0, "Invalid property for name %{public}u", TLV_PERMISSION);
260    return CheckAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
261}
262
263APPSPAWN_INLINE int SetAppPermissionFlags(const AppSpawningCtx *property, uint32_t index)
264{
265    APPSPAWN_CHECK(property != NULL && property->message != NULL,
266        return -1, "Invalid property for name %{public}u", TLV_PERMISSION);
267    return SetAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
268}
269
270APPSPAWN_INLINE int IsIsolatedNativeSpawnMode(const AppSpawnMgr *content, const AppSpawningCtx *property)
271{
272    return (content != NULL) && (content->content.mode == MODE_FOR_NATIVE_SPAWN) &&
273        CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE);
274}
275
276#ifdef __cplusplus
277}
278#endif
279#endif  // APPSPAWN_MANAGER_H
280