serializer.c 7.6 KB
Newer Older
L
liubb_0516 已提交
1
/*
L
liubb_0516 已提交
2
 * Copyright (c) 2021 Huawei Device Co., Ltd.
L
liubb_0516 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15
 * 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.
 */

L
liubb_0516 已提交
16

L
liubb_0516 已提交
17
#include "serializer.h"
L
liubb_0516 已提交
18

L
liubb_0516 已提交
19 20
#include <stdlib.h>
#include <string.h>
L
liubb_0516 已提交
21
#ifdef __LINUX__
L
liubb_0516 已提交
22 23 24
#include "sys_binder.h"
#endif
#include "ipc_process_skeleton.h"
L
liubb_0516 已提交
25 26
#include "rpc_log.h"
#include "securec.h"
L
liubb_0516 已提交
27 28 29 30 31 32 33 34 35 36

#define MAX_IO_SIZE 8192UL
#define MAX_OBJ_NUM 32UL

#define ALIGN_SZ 4
#define IPC_IO_ALIGN(sz) (((sz) + ALIGN_SZ - 1) & (~(ALIGN_SZ - 1)))

#define IPC_IO_RETURN_IF_FAIL(value)                                             \
    do {                                                                         \
        if (!(value)) {                                                          \
L
liubb_0516 已提交
37
            printf("IPC_CHECK failed: %s:%d\n", __FUNCTION__, __LINE__);        \
L
liubb_0516 已提交
38 39 40 41 42 43 44 45
            if (io != NULL) {                                                    \
                io->flag |= IPC_IO_OVERFLOW;                                     \
            }                                                                    \
            return NULL;                                                         \
        }                                                                        \
    } while (0)


L
liubb_0516 已提交
46
void IpcIoInit(IpcIo *io, void *buffer, size_t bufferSize, size_t maxobjects)
L
liubb_0516 已提交
47
{
L
liubb_0516 已提交
48 49
    if ((io == NULL) || (buffer == NULL) || (bufferSize == 0) ||
        (bufferSize > MAX_IO_SIZE) || (maxobjects > MAX_OBJ_NUM)) {
L
liubb_0516 已提交
50 51 52 53 54 55 56 57 58 59 60
        return;
    }
    size_t objectsSize = maxobjects * sizeof(size_t);

    if (objectsSize > bufferSize) {
        io->flag = IPC_IO_OVERFLOW;
        io->bufferLeft = 0;
        io->offsetsLeft = 0;
        return;
    }

L
liubb_0516 已提交
61 62
    io->bufferCur = io->bufferBase = (char *)buffer + objectsSize;
    io->offsetsCur = io->offsetsBase = (size_t *)buffer;
L
liubb_0516 已提交
63 64 65 66 67
    io->bufferLeft = bufferSize - objectsSize;
    io->offsetsLeft = maxobjects;
    io->flag = IPC_IO_INITIALIZED;
}

L
liubb_0516 已提交
68
static bool IpcIoAvailable(IpcIo *io)
L
liubb_0516 已提交
69 70 71 72 73 74 75 76
{
    bool ret = false;
    if (io != NULL) {
        ret = (io->flag & IPC_IO_INITIALIZED) && !(io->flag & IPC_IO_OVERFLOW);
    }
    return ret;
}

L
liubb_0516 已提交
77
static void *IoPush(IpcIo *io, size_t size)
L
liubb_0516 已提交
78 79 80 81 82 83 84 85 86
{
    IPC_IO_RETURN_IF_FAIL(io != NULL);
    IPC_IO_RETURN_IF_FAIL(IpcIoAvailable(io));
    size = IPC_IO_ALIGN(size);
    if (size > io->bufferLeft) {
        io->flag |= IPC_IO_OVERFLOW;
        RPC_LOG_ERROR("IoPush IPC_IO_OVERFLOW.");
        return NULL;
    } else {
L
liubb_0516 已提交
87
        void *ptr = io->bufferCur;
L
liubb_0516 已提交
88 89 90 91 92 93
        io->bufferCur += size;
        io->bufferLeft -= size;
        return ptr;
    }
}

L
liubb_0516 已提交
94
static void *IoPop(IpcIo *io, size_t size)
L
liubb_0516 已提交
95 96 97 98 99 100 101 102 103 104
{
    IPC_IO_RETURN_IF_FAIL(io != NULL);
    IPC_IO_RETURN_IF_FAIL(IpcIoAvailable(io));
    size = IPC_IO_ALIGN(size);

    if (io->bufferLeft < size) {
        io->bufferLeft = 0;
        io->flag |= IPC_IO_OVERFLOW;
        return NULL;
    } else {
L
liubb_0516 已提交
105
        void *ptr = io->bufferCur;
L
liubb_0516 已提交
106 107 108 109 110 111
        io->bufferCur += size;
        io->bufferLeft -= size;
        return ptr;
    }
}

L
liubb_0516 已提交
112
#ifdef __LINUX__
L
liubb_0516 已提交
113
static struct flat_binder_object *IoPushBinderObj(IpcIo *io)
L
liubb_0516 已提交
114 115 116
{
    IPC_IO_RETURN_IF_FAIL(io != NULL);
    IPC_IO_RETURN_IF_FAIL(io->offsetsCur != NULL);
L
liubb_0516 已提交
117
    struct flat_binder_object *ptr = NULL;
L
liubb_0516 已提交
118 119 120 121 122 123 124 125 126 127 128 129
    ptr = IoPush(io, sizeof(struct flat_binder_object));
    if ((ptr != NULL) && io->offsetsLeft) {
        io->offsetsLeft--;
        *(io->offsetsCur) = (char*)ptr - (char*)io->bufferBase;
        io->offsetsCur++;
        return ptr;
    } else {
        io->flag |= IPC_IO_OVERFLOW;
        return NULL;
    }
}

L
liubb_0516 已提交
130
static bool IpcIoPushObject(IpcIo *io, uint32_t token, uint32_t cookie)
L
liubb_0516 已提交
131
{
L
liubb_0516 已提交
132
    struct flat_binder_object *ptr = IoPushBinderObj(io);
L
liubb_0516 已提交
133 134 135 136 137 138 139 140 141 142 143
    if (ptr == NULL) {
        RPC_LOG_ERROR("Io push object IPC_IO_OVERFLOW.");
        return false;
    }
    ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    ptr->type = BINDER_TYPE_BINDER;
    ptr->binder = (uintptr_t)cookie;
    ptr->cookie = cookie;
    return true;
}

L
liubb_0516 已提交
144
static bool IpcIoPushRef(IpcIo *io, uint32_t handle, uint32_t cookie)
L
liubb_0516 已提交
145
{
L
liubb_0516 已提交
146
    struct flat_binder_object *ptr = IoPushBinderObj(io);
L
liubb_0516 已提交
147 148 149 150 151 152 153 154 155 156 157
    if (ptr == NULL) {
        RPC_LOG_ERROR("Io push ref IPC_IO_OVERFLOW.");
        return false;
    }
    ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    ptr->type = BINDER_TYPE_HANDLE;
    ptr->handle = handle;
    ptr->cookie = cookie;
    return true;
}

L
liubb_0516 已提交
158
struct flat_binder_object *IpcIoPopRef(IpcIo *io)
L
liubb_0516 已提交
159 160 161 162 163 164 165
{
    IPC_IO_RETURN_IF_FAIL(io != NULL);
    IPC_IO_RETURN_IF_FAIL(io->offsetsCur != NULL);
    if (io->offsetsLeft == 0) {
        io->flag |= IPC_IO_OVERFLOW;
        return NULL;
    }
L
liubb_0516 已提交
166
    struct flat_binder_object *obj = (struct flat_binder_object *)IoPop(io, sizeof(struct flat_binder_object));
L
liubb_0516 已提交
167 168 169 170 171 172 173 174
    if (obj != NULL) {
        io->offsetsCur++;
        io->offsetsLeft--;
        return obj;
    }
    return NULL;
}

L
liubb_0516 已提交
175
bool WriteRemoteObject(IpcIo *io, const SvcIdentity *svc)
L
liubb_0516 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189
{
    if (io == NULL || svc == NULL) {
        RPC_LOG_ERROR("push io or svc is NULL ...");
        return false;
    }
    bool res;
    if (svc->handle <= 0) {
        res = IpcIoPushObject(io, svc->token, svc->cookie);
    } else {
        res = IpcIoPushRef(io, svc->handle, svc->cookie);
    }
    return res;
}

L
liubb_0516 已提交
190
bool ReadRemoteObject(IpcIo *io, SvcIdentity *svc)
L
liubb_0516 已提交
191 192 193 194
{
    if (io == NULL || svc == NULL) {
        return false;
    }
L
liubb_0516 已提交
195
    struct flat_binder_object *obj = IpcIoPopRef(io);
L
liubb_0516 已提交
196
    if (obj == NULL) {
L
liubb_0516 已提交
197
        RPC_LOG_ERROR("ReadRemoteObject failed: obj is null");
L
liubb_0516 已提交
198 199 200 201 202 203 204 205 206 207 208 209 210 211
        return false;
    }
    if (obj->type == BINDER_TYPE_BINDER) {
        svc->token = obj->binder;
        svc->handle = MIN_BINDER_HANDLE;
        svc->cookie = obj->cookie;
    } else {
        WaitForProxyInit(obj->handle);
        svc->handle = obj->handle;
        svc->cookie = obj->cookie;
    }
    return true;
}

L
liubb_0516 已提交
212
bool WriteFileDescriptor(IpcIo *io, uint32_t fd)
L
liubb_0516 已提交
213
{
L
liubb_0516 已提交
214
    if (io == NULL) {
L
liubb_0516 已提交
215 216 217
        RPC_LOG_ERROR("push fd io is NULL.");
        return false;
    }
L
liubb_0516 已提交
218
    struct flat_binder_object *ptr = IoPushBinderObj(io);
L
liubb_0516 已提交
219 220 221 222 223 224 225 226 227 228 229 230
    if (ptr == NULL) {
        RPC_LOG_ERROR("Io push fd IPC_IO_OVERFLOW.\n");
        return false;
    }
    ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    ptr->type = BINDER_TYPE_FD;
    ptr->binder = 0;
    ptr->cookie = 1;
    ptr->handle = fd;
    return true;
}

L
liubb_0516 已提交
231
int32_t ReadFileDescriptor(IpcIo *io)
L
liubb_0516 已提交
232 233 234 235
{
    if (io == NULL) {
        return -1;
    }
L
liubb_0516 已提交
236
    struct flat_binder_object *obj = IpcIoPopRef(io);
L
liubb_0516 已提交
237
    if (obj == NULL) {
L
liubb_0516 已提交
238
        RPC_LOG_ERROR("ReadFileDescriptor failed: obj is null");
L
liubb_0516 已提交
239 240
        return -1;
    }
L
liubb_0516 已提交
241
    if (obj->type == BINDER_TYPE_FD) {
L
liubb_0516 已提交
242 243
        return obj->handle;
    }
L
liubb_0516 已提交
244
    RPC_LOG_ERROR("ReadFileDescriptor failed: type:%d", obj->type);
L
liubb_0516 已提交
245 246 247
    return -1;
}
#else
L
liubb_0516 已提交
248
bool WriteRemoteObject(IpcIo *io, const SvcIdentity *svc)
L
liubb_0516 已提交
249 250 251 252 253 254
{
    (void)io;
    (void)svc;
    return false;
}

L
liubb_0516 已提交
255
bool WriteFileDescriptor(IpcIo *io, uint32_t fd)
L
liubb_0516 已提交
256 257 258 259 260 261
{
    (void)io;
    (void)fd;
    return false;
}

L
liubb_0516 已提交
262
bool ReadRemoteObject(IpcIo *io, SvcIdentity *svc)
L
liubb_0516 已提交
263 264 265 266 267 268
{
    (void)io;
    (void)svc;
    return false;
}

L
liubb_0516 已提交
269
int32_t ReadFileDescriptor(IpcIo *io)
L
liubb_0516 已提交
270 271 272 273 274
{
    (void)io;
    return -1;
}
#endif