source: mainline/uspace/srv/test/ipc-test/main.c@ ca48672

Last change on this file since ca48672 was ca48672, checked in by Jiri Svoboda <jiri@…>, 7 days ago

loc_service_register() needs to take a port ID argument.

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ipc-test
30 * @{
31 */
32/**
33 * @file
34 * @brief IPC test service
35 *
36 * If run as an initial task, this can be used to test sharing areas
37 * backed by the ELF backend.
38 */
39
40#include <as.h>
41#include <async.h>
42#include <errno.h>
43#include <str_error.h>
44#include <io/log.h>
45#include <ipc/ipc_test.h>
46#include <ipc/services.h>
47#include <loc.h>
48#include <mem.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <task.h>
52
53#define NAME "ipc-test"
54
55static service_id_t svc_id;
56
57enum {
58 max_rw_buf_size = 16384,
59};
60
61/** Object in read-only memory area that will be shared.
62 *
63 * If the server is run as an initial task, the area should be backed
64 * by ELF backend.
65 */
66static const char *ro_data = "Hello, world!";
67
68/** Object in read-write memory area that will be shared.
69 *
70 * If the server is run as an initial task, the area should be backed
71 * by ELF backend.
72 */
73static char rw_data[] = "Hello, world!";
74
75/** Buffer for reading/writing via read/write messages.
76 *
77 * It is allocated / size is set by IPC_TEST_SET_RW_BUF_SIZE
78 */
79static void *rw_buf;
80/** Read/write buffer size */
81size_t rw_buf_size;
82
83static void ipc_test_get_ro_area_size_srv(ipc_call_t *icall)
84{
85 errno_t rc;
86 as_area_info_t info;
87
88 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_get_ro_area_size_srv");
89
90 rc = as_area_get_info((void *)ro_data, &info);
91 if (rc != EOK) {
92 async_answer_0(icall, EIO);
93 log_msg(LOG_DEFAULT, LVL_ERROR, "as_area_get_info failed");
94 return;
95 }
96
97 async_answer_1(icall, EOK, info.size);
98}
99
100static void ipc_test_get_rw_area_size_srv(ipc_call_t *icall)
101{
102 errno_t rc;
103 as_area_info_t info;
104
105 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_get_rw_area_size_srv");
106
107 rc = as_area_get_info(rw_data, &info);
108 if (rc != EOK) {
109 async_answer_0(icall, EIO);
110 log_msg(LOG_DEFAULT, LVL_ERROR, "as_area_get_info failed");
111 return;
112 }
113
114 async_answer_1(icall, EOK, info.size);
115}
116
117static void ipc_test_share_in_ro_srv(ipc_call_t *icall)
118{
119 ipc_call_t call;
120 errno_t rc;
121 size_t size;
122 as_area_info_t info;
123
124 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_share_in_ro_srv");
125 if (!async_share_in_receive(&call, &size)) {
126 async_answer_0(icall, EINVAL);
127 log_msg(LOG_DEFAULT, LVL_ERROR, "share_in_receive failed");
128 return;
129 }
130
131 rc = as_area_get_info((void *)ro_data, &info);
132 if (rc != EOK) {
133 async_answer_0(icall, EINVAL);
134 log_msg(LOG_DEFAULT, LVL_ERROR, "as_area_get_info failed");
135 return;
136 }
137
138 if (size != info.size) {
139 log_msg(LOG_DEFAULT, LVL_ERROR, "size(%zu) != %zu",
140 size, info.size);
141 async_answer_0(icall, EINVAL);
142 return;
143 }
144
145 rc = async_share_in_finalize(&call, (void *) info.start_addr,
146 AS_AREA_READ);
147 if (rc != EOK) {
148 log_msg(LOG_DEFAULT, LVL_ERROR,
149 " - async_share_in_finalize failed");
150 async_answer_0(icall, EINVAL);
151 return;
152 }
153
154 async_answer_0(icall, EOK);
155}
156
157static void ipc_test_share_in_rw_srv(ipc_call_t *icall)
158{
159 ipc_call_t call;
160 errno_t rc;
161 size_t size;
162 as_area_info_t info;
163
164 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_share_in_ro_srv");
165 if (!async_share_in_receive(&call, &size)) {
166 async_answer_0(icall, EINVAL);
167 log_msg(LOG_DEFAULT, LVL_ERROR, "share_in_receive failed");
168 return;
169 }
170
171 rc = as_area_get_info(rw_data, &info);
172 if (rc != EOK) {
173 async_answer_0(icall, EINVAL);
174 log_msg(LOG_DEFAULT, LVL_ERROR, "as_area_get_info failed");
175 return;
176 }
177
178 if (size != info.size) {
179 log_msg(LOG_DEFAULT, LVL_ERROR, " size(%zu) != %zu",
180 size, info.size);
181 async_answer_0(icall, EINVAL);
182 return;
183 }
184
185 rc = async_share_in_finalize(&call, (void *) info.start_addr,
186 AS_AREA_READ | AS_AREA_WRITE);
187 if (rc != EOK) {
188 log_msg(LOG_DEFAULT, LVL_ERROR,
189 "async_share_in_finalize failed");
190 async_answer_0(icall, EINVAL);
191 return;
192 }
193
194 async_answer_0(icall, EOK);
195}
196
197static void ipc_test_set_rw_buf_size_srv(ipc_call_t *icall)
198{
199 size_t size;
200 void *nbuf;
201
202 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_set_rw_buf_size_srv");
203
204 size = ipc_get_arg1(icall);
205
206 if (size == 0) {
207 async_answer_0(icall, ERANGE);
208 log_msg(LOG_DEFAULT, LVL_ERROR,
209 "Requested read/write buffer size is zero.");
210 return;
211 }
212
213 if (size > max_rw_buf_size) {
214 async_answer_0(icall, ERANGE);
215 log_msg(LOG_DEFAULT, LVL_ERROR, "Requested read/write buffer "
216 "size > %u", max_rw_buf_size);
217 return;
218 }
219
220 nbuf = realloc(rw_buf, size);
221 if (nbuf == NULL) {
222 async_answer_0(icall, ENOMEM);
223 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
224 return;
225 }
226
227 rw_buf = nbuf;
228 rw_buf_size = size;
229 async_answer_0(icall, EOK);
230}
231
232static void ipc_test_read_srv(ipc_call_t *icall)
233{
234 ipc_call_t call;
235 errno_t rc;
236 size_t size;
237
238 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_read_srv");
239
240 if (!async_data_read_receive(&call, &size)) {
241 async_answer_0(icall, EREFUSED);
242 log_msg(LOG_DEFAULT, LVL_ERROR, "data_read_receive failed");
243 return;
244 }
245
246 if (size > rw_buf_size) {
247 async_answer_0(&call, EINVAL);
248 async_answer_0(icall, EINVAL);
249 log_msg(LOG_DEFAULT, LVL_ERROR, "Invalid read size.");
250 return;
251 }
252
253 rc = async_data_read_finalize(&call, rw_buf, size);
254 if (rc != EOK) {
255 log_msg(LOG_DEFAULT, LVL_ERROR,
256 "data_read_finalize failed");
257 async_answer_0(icall, EINVAL);
258 return;
259 }
260
261 async_answer_0(icall, EOK);
262}
263
264static void ipc_test_write_srv(ipc_call_t *icall)
265{
266 ipc_call_t call;
267 errno_t rc;
268 size_t size;
269
270 log_msg(LOG_DEFAULT, LVL_DEBUG, "ipc_test_write_srv");
271
272 if (!async_data_write_receive(&call, &size)) {
273 async_answer_0(icall, EREFUSED);
274 log_msg(LOG_DEFAULT, LVL_ERROR, "data_write_receive failed");
275 return;
276 }
277
278 if (size > rw_buf_size) {
279 async_answer_0(&call, EINVAL);
280 async_answer_0(icall, EINVAL);
281 log_msg(LOG_DEFAULT, LVL_ERROR, "Invalid write size.");
282 return;
283 }
284
285 rc = async_data_write_finalize(&call, rw_buf, size);
286 if (rc != EOK) {
287 log_msg(LOG_DEFAULT, LVL_ERROR,
288 "data_write_finalize failed");
289 async_answer_0(icall, EINVAL);
290 return;
291 }
292
293 async_answer_0(icall, EOK);
294}
295
296static void ipc_test_connection(ipc_call_t *icall, void *arg)
297{
298 /* Accept connection */
299 async_accept_0(icall);
300
301 while (true) {
302 ipc_call_t call;
303 async_get_call(&call);
304
305 if (!ipc_get_imethod(&call)) {
306 async_answer_0(&call, EOK);
307 break;
308 }
309
310 switch (ipc_get_imethod(&call)) {
311 case IPC_TEST_PING:
312 async_answer_0(&call, EOK);
313 break;
314 case IPC_TEST_GET_RO_AREA_SIZE:
315 ipc_test_get_ro_area_size_srv(&call);
316 break;
317 case IPC_TEST_GET_RW_AREA_SIZE:
318 ipc_test_get_rw_area_size_srv(&call);
319 break;
320 case IPC_TEST_SHARE_IN_RO:
321 ipc_test_share_in_ro_srv(&call);
322 break;
323 case IPC_TEST_SHARE_IN_RW:
324 ipc_test_share_in_rw_srv(&call);
325 break;
326 case IPC_TEST_SET_RW_BUF_SIZE:
327 ipc_test_set_rw_buf_size_srv(&call);
328 break;
329 case IPC_TEST_READ:
330 ipc_test_read_srv(&call);
331 break;
332 case IPC_TEST_WRITE:
333 ipc_test_write_srv(&call);
334 break;
335 default:
336 async_answer_0(&call, ENOTSUP);
337 break;
338 }
339 }
340}
341
342int main(int argc, char *argv[])
343{
344 errno_t rc;
345 loc_srv_t *srv;
346
347 printf("%s: IPC test service\n", NAME);
348 async_set_fallback_port_handler(ipc_test_connection, NULL);
349
350 rc = log_init(NAME);
351 if (rc != EOK) {
352 printf(NAME ": Failed to initialize log.\n");
353 return rc;
354 }
355
356 rc = loc_server_register(NAME, &srv);
357 if (rc != EOK) {
358 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server. (%s)\n",
359 str_error(rc));
360 return rc;
361 }
362
363 rc = loc_service_register(srv, SERVICE_NAME_IPC_TEST, fallback_port_id,
364 &svc_id);
365 if (rc != EOK) {
366 loc_server_unregister(srv);
367 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service. (%s)\n",
368 str_error(rc));
369 return rc;
370 }
371
372 printf("%s: Accepting connections\n", NAME);
373 task_retval(0);
374 async_manager();
375
376 /* Not reached */
377 return 0;
378}
379
380/**
381 * @}
382 */
Note: See TracBrowser for help on using the repository browser.