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