1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "libipc/ipc.h"
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <strings.h>
9
10#ifdef __MOS_KERNEL__
11#include "mos/io/io.h"
12
13#include <mos_stdlib.h>
14#define do_read(fd, buffer, size) io_read(fd, buffer, size)
15#define do_write(fd, buffer, size) io_write(fd, buffer, size)
16#define do_warn(fmt, ...) mos_warn(fmt, ##__VA_ARGS__)
17#else
18#include <unistd.h>
19#define do_read(fd, buffer, size) read(fd, buffer, size)
20#define do_write(fd, buffer, size) write(fd, buffer, size)
21#define do_warn(fmt, ...) fprintf(stderr, fmt __VA_OPT__(, ) __VA_ARGS__)
22#endif
23
24MOS_STATIC_ASSERT(sizeof(size_t) == sizeof(uint64_t), "size_t must be 64 bits");
25
26ipc_msg_t *ipc_msg_create(size_t size)
27{
28 ipc_msg_t *buffer = malloc(sizeof(ipc_msg_t) + size);
29 buffer->size = size;
30 return buffer;
31}
32
33void ipc_msg_destroy(ipc_msg_t *buffer)
34{
35 free(buffer);
36}
37
38ipc_msg_t *ipc_read_msg(ipcfd_t fd)
39{
40 size_t size = 0;
41 size_t read_size = do_read(fd, &size, sizeof(size));
42
43 if (read_size == 0)
44 {
45 // EOF
46 return NULL;
47 }
48
49 if (read_size != sizeof(size))
50 {
51 do_warn("failed to read size from ipc channel");
52 return NULL;
53 }
54
55 ipc_msg_t *buffer = ipc_msg_create(size);
56 read_size = do_read(fd, buffer->data, buffer->size);
57 if (read_size != size)
58 {
59 do_warn("failed to read data from ipc channel");
60 ipc_msg_destroy(buffer);
61 return NULL;
62 }
63
64 return buffer;
65}
66
67bool ipc_write_msg(ipcfd_t fd, ipc_msg_t *buffer)
68{
69 size_t written = do_write(fd, &buffer->size, sizeof(buffer->size));
70 if (written != sizeof(buffer->size))
71 {
72 do_warn("failed to write size to ipc channel");
73 return false;
74 }
75
76 written = do_write(fd, buffer->data, buffer->size);
77 if (written != buffer->size)
78 {
79 do_warn("failed to write data to ipc channel");
80 return false;
81 }
82
83 return true;
84}
85
86bool ipc_write_as_msg(ipcfd_t fd, const char *data, size_t size)
87{
88 size_t w = 0;
89 w = do_write(fd, &size, sizeof(size));
90 if (unlikely(w != sizeof(size)))
91 {
92 do_warn("failed to write size to ipc channel");
93 return false;
94 }
95 w = do_write(fd, data, size);
96 if (unlikely(w != size))
97 {
98 do_warn("failed to write data to ipc channel");
99 return false;
100 }
101
102 return true;
103}
104
105size_t ipc_read_as_msg(ipcfd_t fd, char *buffer, size_t buffer_size)
106{
107 size_t size = 0;
108 size_t data_size = 0;
109 size = do_read(fd, &data_size, sizeof(size_t));
110 if (unlikely(size != sizeof(size_t)))
111 {
112 do_warn("failed to read size from ipc channel");
113 return 0;
114 }
115
116 if (unlikely(data_size > buffer_size))
117 {
118 do_warn("buffer too small");
119 return 0;
120 }
121
122 size = do_read(fd, buffer, buffer_size);
123 if (unlikely(size != data_size))
124 {
125 do_warn("failed to read data from ipc channel");
126 return 0;
127 }
128 return data_size;
129}
130