GCC Code Coverage Report


Directory: src/gate/
File: src/gate/interfaces/socop_impl.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 0 470 0.0%
Functions: 0 29 0.0%
Branches: 0 215 0.0%

Line Branch Exec Source
1 #include "socop.h"
2
3 #include <stdlib.h>
4 #include <string.h>
5
6 ✗ int socop_client_init(socop_client_t* session,
7 socop_read_byte_t reader_func, void* reader_param,
8 socop_write_byte_t writer_func, void* writer_param)
9 {
10 ✗ session->driver.read_byte = reader_func;
11 ✗ session->driver.read_param = reader_param;
12 ✗ session->driver.write_byte = writer_func;
13 ✗ session->driver.write_param = writer_param;
14 ✗ return SOCOP_ERROR_NOTIMPL;
15 }
16
17 ✗ static void serialize_word(unsigned char target[2], socop_word_t src)
18 {
19 ✗ target[0] = (unsigned char)(src >> 8);
20 ✗ target[1] = (unsigned char)(src & 0xff);
21 ✗ }
22
23 ✗ static void deserialize_word(socop_word_t* target, unsigned char const* src)
24 {
25 ✗ *target = ((((socop_word_t)src[0]) << 8) | ((socop_word_t)(src[1] & 0xff)));
26 ✗ }
27
28
29 ✗ int socop_driver_send_msg(socop_driver_t* driver, socop_msg_base_t const* msg, void const* data)
30 {
31 unsigned char msg_buffer[SOCOP_MSG_BASE_LENGTH];
32 unsigned ndx;
33 ✗ unsigned datalen = msg->msg_length - SOCOP_MSG_BASE_LENGTH;
34 ✗ unsigned char const* ptr_data = (unsigned char const*)data;
35 unsigned more; /* true until no more bytes will follow */
36 int result;
37
38 /* serialize header */
39 ✗ serialize_word(&msg_buffer[0], msg->msg_type);
40 ✗ serialize_word(&msg_buffer[2], msg->msg_length);
41 ✗ serialize_word(&msg_buffer[4], msg->resource_id);
42 ✗ serialize_word(&msg_buffer[6], msg->resource_param);
43 ✗ serialize_word(&msg_buffer[8], msg->state);
44 ✗ serialize_word(&msg_buffer[10], msg->user_param);
45
46 /* send header */
47 ✗ more = 1;
48 ✗ for (ndx = 0; ndx != SOCOP_MSG_BASE_LENGTH; ++ndx)
49 {
50 ✗ if (ndx == SOCOP_MSG_BASE_LENGTH - 1)
51 {
52 ✗ more = (datalen == 0) ? 0 : 1;
53 }
54 ✗ result = driver->write_byte(msg_buffer[ndx], more, driver->write_param);
55 ✗ if (result != SOCOP_OK)
56 {
57 ✗ return SOCOP_ERROR_IO;
58 }
59 }
60
61 /* send content if available */
62 ✗ for (ndx = 0; ndx != datalen; ++ndx)
63 {
64 ✗ more = (ndx == datalen - 1) ? 0 : 1;
65 ✗ result = driver->write_byte(ptr_data[ndx], more, driver->write_param);
66 ✗ if (result != SOCOP_OK)
67 {
68 ✗ return SOCOP_ERROR_IO;
69 }
70 }
71
72 ✗ return SOCOP_OK;
73 }
74
75 ✗ static int receive_buffer(socop_driver_t* driver, unsigned char* target, unsigned length)
76 {
77 unsigned ndx;
78 unsigned more;
79 int result;
80
81 ✗ for (ndx = 0; ndx != length; ++ndx)
82 {
83 ✗ more = (ndx == length - 1) ? 0 : 1;
84 ✗ result = driver->read_byte(&target[ndx], more, driver->read_param);
85 ✗ if (result == SOCOP_ERROR_TIMEOUT)
86 {
87 ✗ continue;
88 }
89 ✗ if (result != SOCOP_OK)
90 {
91 ✗ return result;
92 }
93 }
94 ✗ return SOCOP_OK;
95 }
96
97 ✗ int socop_driver_receive_msg(socop_driver_t* driver, socop_msg_buffer_t* buffer)
98 {
99 unsigned char msg_buffer[SOCOP_MSG_BASE_LENGTH];
100 unsigned data_len;
101 int result;
102
103 ✗ result = receive_buffer(driver, msg_buffer, SOCOP_MSG_BASE_LENGTH);
104 ✗ if (result != SOCOP_OK)
105 {
106 ✗ return result;
107 }
108
109 ✗ deserialize_word(&buffer->base.msg_type, &msg_buffer[0]);
110 ✗ deserialize_word(&buffer->base.msg_length, &msg_buffer[2]);
111 ✗ deserialize_word(&buffer->base.resource_id, &msg_buffer[4]);
112 ✗ deserialize_word(&buffer->base.resource_param, &msg_buffer[6]);
113 ✗ deserialize_word(&buffer->base.state, &msg_buffer[8]);
114 ✗ deserialize_word(&buffer->base.user_param, &msg_buffer[10]);
115
116 ✗ if (buffer->base.msg_length < SOCOP_MSG_BASE_LENGTH)
117 {
118 ✗ return SOCOP_ERROR_INVALIDDATA;
119 }
120 ✗ if ((buffer->base.msg_type & SOCOP_MSG_MASK) != SOCOP_MSG_MASK)
121 {
122 ✗ return SOCOP_ERROR_INVALIDDATA;
123 }
124
125 ✗ if (buffer->base.msg_length == SOCOP_MSG_BASE_LENGTH)
126 {
127 ✗ return SOCOP_OK;
128 }
129 ✗ data_len = buffer->base.msg_length - SOCOP_MSG_BASE_LENGTH;
130 ✗ if (data_len > sizeof(buffer->content))
131 {
132 ✗ return SOCOP_ERROR_OUTOFBOUNDS;
133 }
134 ✗ return receive_buffer(driver, (unsigned char*)&buffer->content[0], data_len);
135 }
136
137
138
139 ✗ static void init_msg_base(socop_msg_base_t* msg, socop_word_t type, socop_word_t sock_id, socop_word_t sock_param,
140 socop_word_t state, socop_word_t user, socop_word_t content_length)
141 {
142 ✗ msg->msg_type = type;
143 ✗ msg->msg_length = SOCOP_MSG_BASE_LENGTH + content_length;
144 ✗ msg->resource_id = sock_id;
145 ✗ msg->resource_param = sock_param;
146 ✗ msg->state = state;
147 ✗ msg->user_param = user;
148 ✗ }
149
150 ✗ static int receive_message_type(socop_driver_t* session, socop_msg_buffer_t* ptr_msg, socop_word_t desired_type, socop_word_t desired_resource_id)
151 {
152 ✗ int result = socop_driver_receive_msg(session, ptr_msg);
153 ✗ if (result != SOCOP_OK)
154 {
155 ✗ return result;
156 }
157 ✗ if (ptr_msg->base.msg_type != desired_type)
158 {
159 ✗ return SOCOP_ERROR_WRONGMESSAGE;
160 }
161 ✗ if (ptr_msg->base.state != SOCOP_OK)
162 {
163 ✗ return ptr_msg->base.state;
164 }
165 ✗ if (desired_resource_id && (ptr_msg->base.resource_id != desired_resource_id))
166 {
167 ✗ return SOCOP_ERROR_RESOURCEERROR;
168 }
169 ✗ return SOCOP_OK;
170 }
171
172 ✗ static socop_word_t serialize_addr(unsigned char target[6], socop_addr_t const* ptr_addr)
173 {
174 ✗ target[0] = ptr_addr->ip[0];
175 ✗ target[1] = ptr_addr->ip[1];
176 ✗ target[2] = ptr_addr->ip[2];
177 ✗ target[3] = ptr_addr->ip[3];
178 ✗ serialize_word(&target[4], ptr_addr->port);
179 ✗ return 6;
180 }
181
182 ✗ static void deserialize_addr(socop_addr_t* target, unsigned char const src[6])
183 {
184 ✗ target->ip[0] = src[0];
185 ✗ target->ip[1] = src[1];
186 ✗ target->ip[2] = src[2];
187 ✗ target->ip[3] = src[3];
188 ✗ deserialize_word(&target->port, &src[4]);
189 ✗ }
190
191
192 ✗ int socop_client_reset(socop_client_t* session)
193 {
194 int result;
195 socop_msg_buffer_t msg;
196
197 ✗ init_msg_base(&msg.base, SOCOP_MSG_RESET_REQUEST, 0, 0, 0, 0, 0);
198 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
199 ✗ if (result != SOCOP_OK)
200 {
201 ✗ return result;
202 }
203 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_RESET_RESPONSE, 0);
204 ✗ if (result != SOCOP_OK)
205 {
206 ✗ return result;
207 }
208 ✗ return SOCOP_OK;
209 }
210
211 ✗ int socop_client_netstatus(socop_client_t* session, unsigned* ptr_status)
212 {
213 int result;
214 socop_msg_buffer_t msg;
215
216 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_STATUS_REQUEST, 0, 0, 0, 0, 0);
217 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
218 ✗ if (result != SOCOP_OK)
219 {
220 ✗ return result;
221 }
222 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_NET_STATUS_RESPONSE, 0);
223 ✗ if (result != SOCOP_OK)
224 {
225 ✗ return result;
226 }
227 ✗ if (ptr_status)
228 {
229 ✗ *ptr_status = msg.base.resource_param;
230 }
231 ✗ return SOCOP_OK;
232 }
233
234 ✗ int socop_client_netstart(socop_client_t* session, char const* parameters, unsigned parameters_length)
235 {
236 int result;
237 socop_msg_buffer_t msg;
238 ✗ if (parameters_length > SOCOP_MAX_CONTENT_LENGTH)
239 {
240 ✗ parameters_length = SOCOP_MAX_CONTENT_LENGTH;
241 }
242
243 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_START_REQUEST, 0, 0, 0, 0, (socop_word_t)parameters_length);
244 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, parameters);
245 ✗ if (result != SOCOP_OK)
246 {
247 ✗ return result;
248 }
249 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_NET_START_RESPONSE, 0);
250 ✗ if (result != SOCOP_OK)
251 {
252 ✗ return result;
253 }
254 ✗ return SOCOP_OK;
255 }
256
257 ✗ int socop_client_netstop(socop_client_t* session)
258 {
259 int result;
260 socop_msg_buffer_t msg;
261
262 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_STOP_REQUEST, 0, 0, 0, 0, 0);
263 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, NULL);
264 ✗ if (result != SOCOP_OK)
265 {
266 ✗ return result;
267 }
268 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_NET_STOP_RESPONSE, 0);
269 ✗ if (result != SOCOP_OK)
270 {
271 ✗ return result;
272 }
273 ✗ return SOCOP_OK;
274 }
275
276 ✗ int socop_client_connect(socop_client_t* session, socop_addr_t const* addr, socop_socket_t* ptr_sock)
277 {
278 int result;
279 socop_msg_buffer_t msg;
280 ✗ const socop_word_t content_len = serialize_addr((unsigned char*)&msg.content[0], addr);
281
282 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_CONNECT_REQUEST, 0, 0, 0, 0, content_len);
283 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
284 ✗ if (result != SOCOP_OK)
285 {
286 ✗ return result;
287 }
288 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_CONNECT_RESPONSE, 0);
289 ✗ if (result != SOCOP_OK)
290 {
291 ✗ return result;
292 }
293 ✗ if (msg.base.resource_id)
294 {
295 ✗ *ptr_sock = msg.base.resource_id;
296 ✗ return SOCOP_OK;
297 }
298 else
299 {
300 ✗ return SOCOP_ERROR_RESOURCEERROR;
301 }
302 }
303
304 ✗ int socop_client_bind(socop_client_t* session, socop_addr_t const* addr, socop_socket_t* ptr_sock)
305 {
306 int result;
307 socop_msg_buffer_t msg;
308 ✗ const socop_word_t content_len = serialize_addr((unsigned char*)&msg.content[0], addr);
309
310 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_BIND_REQUEST, 0, 0, 0, 0, content_len);
311 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
312 ✗ if (result != SOCOP_OK)
313 {
314 ✗ return result;
315 }
316 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_BIND_RESPONSE, 0);
317 ✗ if (result != SOCOP_OK)
318 {
319 ✗ return result;
320 }
321 ✗ if (msg.base.resource_id)
322 {
323 ✗ *ptr_sock = msg.base.resource_id;
324 ✗ return SOCOP_OK;
325 }
326 else
327 {
328 ✗ return SOCOP_ERROR_RESOURCEERROR;
329 }
330 }
331
332 ✗ int socop_client_listen(socop_client_t* session, socop_addr_t const* addr, socop_socket_t* ptr_sock)
333 {
334 int result;
335 socop_msg_buffer_t msg;
336 ✗ const socop_word_t content_len = serialize_addr((unsigned char*)&msg.content[0], addr);
337
338 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_LISTEN_REQUEST, 0, 0, 0, 0, content_len);
339 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
340 ✗ if (result != SOCOP_OK)
341 {
342 ✗ return result;
343 }
344 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_LISTEN_RESPONSE, 0);
345 ✗ if (result != SOCOP_OK)
346 {
347 ✗ return result;
348 }
349 ✗ if (msg.base.resource_id)
350 {
351 ✗ *ptr_sock = msg.base.resource_id;
352 ✗ return SOCOP_OK;
353 }
354 else
355 {
356 ✗ return SOCOP_ERROR_RESOURCEERROR;
357 }
358 }
359
360 ✗ int socop_client_accept(socop_client_t* session, socop_socket_t sock, socop_socket_t* ptr_sock)
361 {
362 int result;
363 socop_msg_buffer_t msg;
364
365 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_ACCEPT_REQUEST, sock, 0, 0, 0, 0);
366 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, NULL);
367 ✗ if (result != SOCOP_OK)
368 {
369 ✗ return result;
370 }
371 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_ACCEPT_RESPONSE, 0);
372 ✗ if (result != SOCOP_OK)
373 {
374 ✗ return result;
375 }
376 /* original server socket is returned as resource_param */
377 ✗ if (msg.base.resource_param == sock)
378 {
379 ✗ *ptr_sock = msg.base.resource_id;
380 ✗ return SOCOP_OK;
381 }
382 else
383 {
384 ✗ return SOCOP_ERROR_RESOURCEERROR;
385 }
386 }
387
388
389 ✗ int socop_client_close(socop_client_t* session, socop_socket_t sock)
390 {
391 int result;
392 socop_msg_buffer_t msg;
393
394 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_CLOSE_REQUEST, sock, 0, 0, 0, 0);
395 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, NULL);
396 ✗ if (result != SOCOP_OK)
397 {
398 ✗ return result;
399 }
400 ✗ return receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_CLOSE_RESPONSE, 0);
401 }
402
403 ✗ int socop_client_receive(socop_client_t* session, socop_socket_t sock,
404 void* buffer, unsigned bufferlen, unsigned* bufferused)
405 {
406 int result;
407 socop_msg_buffer_t msg;
408 unsigned received_content;
409
410 ✗ if (bufferlen > SOCOP_MAX_CONTENT_LENGTH)
411 {
412 ✗ bufferlen = SOCOP_MAX_CONTENT_LENGTH;
413 }
414
415 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_RECV_REQUEST, sock, (socop_word_t)bufferlen, 0, 0, 0);
416 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, NULL);
417 ✗ if (result != SOCOP_OK)
418 {
419 ✗ return result;
420 }
421 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_RECV_RESPONSE, sock);
422 ✗ if (result != SOCOP_OK)
423 {
424 ✗ return result;
425 }
426 ✗ received_content = msg.base.msg_length - SOCOP_MSG_BASE_LENGTH;
427 ✗ if (received_content)
428 {
429 ✗ memcpy(buffer, msg.content, received_content);
430 }
431 ✗ if (bufferused)
432 {
433 ✗ *bufferused = received_content;
434 }
435 ✗ return SOCOP_OK;
436 }
437
438 ✗ int socop_client_recv_from(socop_client_t* session, socop_socket_t sock,
439 void* buffer, unsigned bufferlen, unsigned* bufferused,
440 socop_addr_t* ptr_addr)
441 {
442 int result;
443 socop_msg_buffer_t msg;
444 unsigned address_length;
445 unsigned received_content;
446
447 ✗ if (bufferlen > (SOCOP_MAX_CONTENT_LENGTH - 8))
448 {
449 ✗ bufferlen = SOCOP_MAX_CONTENT_LENGTH - 8;
450 }
451
452 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_RECVFROM_REQUEST, sock, (socop_word_t)bufferlen, 0, 0, 0);
453 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, NULL);
454 ✗ if (result != SOCOP_OK)
455 {
456 ✗ return result;
457 }
458 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_RECVFROM_RESPONSE, sock);
459 ✗ if (result != SOCOP_OK)
460 {
461 ✗ return result;
462 }
463
464 ✗ address_length = msg.base.resource_param;
465 ✗ if (address_length > (unsigned)(msg.base.msg_length - SOCOP_MSG_BASE_LENGTH))
466 {
467 ✗ return SOCOP_ERROR_CORRUPTION;
468 }
469
470 ✗ if (ptr_addr)
471 {
472 ✗ deserialize_addr(ptr_addr, (unsigned char const*)&msg.content[0]);
473 }
474
475 ✗ received_content = msg.base.msg_length - address_length - SOCOP_MSG_BASE_LENGTH;
476 ✗ if (received_content)
477 {
478 ✗ memcpy(buffer, &msg.content[address_length], received_content);
479 }
480 ✗ if (bufferused)
481 {
482 ✗ *bufferused = received_content;
483 }
484 ✗ return SOCOP_OK;
485 }
486
487 ✗ int socop_client_send(socop_client_t* session, socop_socket_t sock,
488 void const* buffer, unsigned bufferlen, unsigned* bufferused)
489 {
490 int result;
491 socop_msg_buffer_t msg;
492
493 ✗ if (bufferlen > (SOCOP_MAX_CONTENT_LENGTH))
494 {
495 ✗ bufferlen = SOCOP_MAX_CONTENT_LENGTH;
496 }
497
498 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SEND_REQUEST, sock, 0, 0, 0, (socop_word_t)bufferlen);
499 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, buffer);
500 ✗ if (result != SOCOP_OK)
501 {
502 ✗ return result;
503 }
504 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_SEND_RESPONSE, sock);
505 ✗ if (result != SOCOP_OK)
506 {
507 ✗ return result;
508 }
509 ✗ if (bufferused)
510 {
511 ✗ *bufferused = msg.base.resource_param;
512 }
513 ✗ return SOCOP_OK;
514 }
515
516 ✗ int socop_client_sendto(socop_client_t* session, socop_socket_t sock,
517 void const* buffer, unsigned bufferlen, unsigned* bufferused,
518 socop_addr_t const* ptr_addr)
519 {
520 int result;
521 socop_msg_buffer_t msg;
522 ✗ const socop_word_t addr_length = serialize_addr((unsigned char*)&msg.content[0], ptr_addr);
523
524 ✗ if (bufferlen > (unsigned)(SOCOP_MAX_CONTENT_LENGTH - addr_length))
525 {
526 ✗ bufferlen = SOCOP_MAX_CONTENT_LENGTH - addr_length;
527 }
528 ✗ memcpy(&msg.content[addr_length], buffer, bufferlen);
529
530 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SENDTO_REQUEST, sock, addr_length, 0, 0, (socop_word_t)(bufferlen + addr_length));
531 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
532 ✗ if (result != SOCOP_OK)
533 {
534 ✗ return result;
535 }
536 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_SENDTO_RESPONSE, sock);
537 ✗ if (result != SOCOP_OK)
538 {
539 ✗ return result;
540 }
541 ✗ if (bufferused)
542 {
543 ✗ *bufferused = msg.base.resource_param;
544 }
545 ✗ return SOCOP_OK;
546 }
547
548 ✗ int socop_client_shutdown(socop_client_t* session, socop_socket_t sock, unsigned target)
549 {
550 int result;
551 socop_msg_buffer_t msg;
552
553 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SHUTDOWN_REQUEST, sock, (socop_word_t)target, 0, 0, 0);
554 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
555 ✗ if (result != SOCOP_OK)
556 {
557 ✗ return result;
558 }
559 ✗ return receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_SHUTDOWN_RESPONSE, sock);
560 }
561
562 ✗ int socop_client_select(socop_client_t* session, socop_socket_t sock, unsigned* flags, unsigned timeout_ms)
563 {
564 int result;
565 socop_msg_buffer_t msg;
566 ✗ const socop_word_t sel_flags = flags ? ((socop_word_t)*flags) : (SOCOP_MSG_FLAG_RECV | SOCOP_MSG_FLAG_SEND | SOCOP_MSG_FLAG_ERROR);
567 socop_word_t timeout;
568
569 ✗ if (timeout_ms > (unsigned int)0xffff)
570 {
571 ✗ timeout = 0xffff;
572 }
573 else
574 {
575 ✗ timeout = (socop_word_t)timeout_ms;
576 }
577
578 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SELECT_REQUEST, sock, sel_flags, timeout, 0, 0);
579 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, msg.content);
580 ✗ if (result != SOCOP_OK)
581 {
582 ✗ return result;
583 }
584 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_SELECT_RESPONSE, sock);
585 ✗ if (result != SOCOP_OK)
586 {
587 ✗ return result;
588 }
589 ✗ if (flags)
590 {
591 ✗ *flags = msg.base.resource_param;
592 }
593 ✗ return SOCOP_OK;
594 }
595
596 ✗ int socop_client_peer(socop_client_t* session, socop_socket_t sock, socop_addr_t* ptr_addr)
597 {
598 int result;
599 socop_msg_buffer_t msg;
600
601 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_PEER_REQUEST, sock, 0, 0, 0, 0);
602 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, 0);
603 ✗ if (result != SOCOP_OK)
604 {
605 ✗ return result;
606 }
607 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_PEER_RESPONSE, sock);
608 ✗ if (result != SOCOP_OK)
609 {
610 ✗ return result;
611 }
612 ✗ deserialize_addr(ptr_addr, (unsigned char const*)&msg.content[0]);
613 ✗ return SOCOP_OK;
614 }
615
616 ✗ int socop_client_ioctl(socop_client_t* session, socop_socket_t sock, unsigned option, void* data, unsigned datalen)
617 {
618 int result;
619 socop_msg_buffer_t msg;
620 unsigned content_length;
621
622 ✗ if (datalen > SOCOP_MAX_CONTENT_LENGTH)
623 {
624 ✗ datalen = SOCOP_MAX_CONTENT_LENGTH;
625 }
626 ✗ if ((datalen > 0) && !data)
627 {
628 ✗ return SOCOP_ERROR_INVALIDARG;
629 }
630
631 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_IOCTL_REQUEST, sock, (socop_word_t)option, 0, 0, (socop_word_t)datalen);
632 ✗ result = socop_driver_send_msg(&session->driver, &msg.base, data);
633 ✗ if (result != SOCOP_OK)
634 {
635 ✗ return result;
636 }
637 ✗ result = receive_message_type(&session->driver, &msg, SOCOP_MSG_SOCK_IOCTL_RESPONSE, sock);
638 ✗ if (result != SOCOP_OK)
639 {
640 ✗ return result;
641 }
642 ✗ content_length = msg.base.msg_length - SOCOP_MSG_BASE_LENGTH;
643 ✗ if (content_length > datalen)
644 {
645 ✗ content_length = datalen;
646 }
647 ✗ if (content_length > 0)
648 {
649 ✗ memcpy(data, msg.content, content_length);
650 }
651 ✗ return SOCOP_OK;
652 }
653
654
655
656
657 ✗ int socop_server_init(socop_server_t* server, void* server_param,
658 socop_read_byte_t reader_func, void* reader_param, socop_write_byte_t writer_func, void* writer_param)
659 {
660 ✗ memset(server, 0, sizeof(socop_server_t));
661 ✗ server->server_param = server_param;
662 ✗ server->driver.read_byte = reader_func;
663 ✗ server->driver.read_param = reader_param;
664 ✗ server->driver.write_byte = writer_func;
665 ✗ server->driver.write_param = writer_param;
666 ✗ return SOCOP_OK;
667 }
668
669
670
671 ✗ int socop_server_chat_once(socop_server_t* server)
672 {
673 int result;
674 ✗ socop_msg_buffer_t msg = { 0 };
675 ✗ unsigned content_length = 0;
676 ✗ socop_addr_t addr = { 0 };
677 ✗ socop_socket_t sock = 0;
678 ✗ unsigned flags = 0;
679
680 ✗ result = socop_driver_receive_msg(&server->driver, &msg);
681 ✗ if (SOCOP_OK != result)
682 {
683 ✗ return result;
684 }
685
686 ✗ content_length = msg.base.msg_length - SOCOP_MSG_BASE_LENGTH;
687
688 ✗ switch (msg.base.msg_type)
689 {
690 ✗ case SOCOP_MSG_RESET_REQUEST:
691 {
692 ✗ if (!server->on_reset)
693 {
694 ✗ result = SOCOP_ERROR_NOTIMPL;
695 }
696 else
697 {
698 ✗ result = server->on_reset(server, msg.content, content_length);
699 }
700 ✗ init_msg_base(&msg.base, SOCOP_MSG_RESET_RESPONSE, 0, 0, (socop_word_t)result, msg.base.user_param, 0);
701 ✗ result = SOCOP_OK;
702 ✗ break;
703 }
704
705 ✗ case SOCOP_MSG_NET_STATUS_REQUEST:
706 {
707 ✗ if (!server->on_netstatus)
708 {
709 ✗ result = SOCOP_ERROR_NOTIMPL;
710 }
711 else
712 {
713 ✗ result = server->on_netstatus(server, NULL, 0);
714 }
715 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_STATUS_RESPONSE, 0, 0, (socop_word_t)result, msg.base.user_param, 0);
716 ✗ result = SOCOP_OK;
717 ✗ break;
718 }
719
720 ✗ case SOCOP_MSG_NET_START_REQUEST:
721 {
722 ✗ if (!server->on_netstart)
723 {
724 ✗ result = SOCOP_ERROR_NOTIMPL;
725 }
726 else
727 {
728 ✗ result = server->on_netstart(server, msg.content, content_length);
729 }
730 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_STATUS_RESPONSE, 0, 0, (socop_word_t)result, msg.base.user_param, 0);
731 ✗ result = SOCOP_OK;
732 ✗ break;
733 }
734 ✗ case SOCOP_MSG_NET_STOP_REQUEST:
735 {
736 ✗ if (!server->on_netstop)
737 {
738 ✗ result = SOCOP_ERROR_NOTIMPL;
739 }
740 else
741 {
742 ✗ result = server->on_netstop(server, NULL, 0);
743 }
744 ✗ init_msg_base(&msg.base, SOCOP_MSG_NET_STATUS_RESPONSE, 0, 0, (socop_word_t)result, msg.base.user_param, 0);
745 ✗ result = SOCOP_OK;
746 ✗ break;
747 }
748
749 ✗ case SOCOP_MSG_SOCK_CONNECT_REQUEST:
750 {
751 ✗ if (!server->on_connect)
752 {
753 ✗ result = SOCOP_ERROR_NOTIMPL;
754 }
755 else
756 {
757 ✗ deserialize_addr(&addr, (unsigned char const*)&msg.content[0]);
758 ✗ result = server->on_connect(server, &addr, &sock);
759 }
760 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_CONNECT_RESPONSE, sock, 0, (socop_word_t)result, msg.base.user_param, 0);
761 ✗ result = SOCOP_OK;
762 ✗ break;
763 }
764
765 ✗ case SOCOP_MSG_SOCK_BIND_REQUEST:
766 {
767 ✗ if (!server->on_bind)
768 {
769 ✗ result = SOCOP_ERROR_NOTIMPL;
770 }
771 else
772 {
773 ✗ deserialize_addr(&addr, (unsigned char const*)&msg.content[0]);
774 ✗ result = server->on_bind(server, &addr, &sock);
775 }
776 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_BIND_RESPONSE, sock, 0, (socop_word_t)result, msg.base.user_param, 0);
777 ✗ result = SOCOP_OK;
778 ✗ break;
779 }
780
781 ✗ case SOCOP_MSG_SOCK_LISTEN_REQUEST:
782 {
783 ✗ if (!server->on_bind)
784 {
785 ✗ result = SOCOP_ERROR_NOTIMPL;
786 }
787 else
788 {
789 ✗ deserialize_addr(&addr, (unsigned char const*)&msg.content[0]);
790 ✗ result = server->on_listen(server, &addr, &sock);
791 }
792 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_LISTEN_RESPONSE, sock, 0, (socop_word_t)result, msg.base.user_param, 0);
793 ✗ result = SOCOP_OK;
794 ✗ break;
795 }
796
797 ✗ case SOCOP_MSG_SOCK_ACCEPT_REQUEST:
798 {
799 ✗ if (!server->on_accept)
800 {
801 ✗ result = SOCOP_ERROR_NOTIMPL;
802 }
803 else
804 {
805 ✗ result = server->on_accept(server, msg.base.resource_id, &sock);
806 }
807 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_ACCEPT_RESPONSE, sock, msg.base.resource_id, (socop_word_t)result, msg.base.user_param, 0);
808 ✗ result = SOCOP_OK;
809 ✗ break;
810 }
811
812 ✗ case SOCOP_MSG_SOCK_CLOSE_REQUEST:
813 {
814 ✗ if (!server->on_close)
815 {
816 ✗ result = SOCOP_ERROR_NOTIMPL;
817 }
818 else
819 {
820 ✗ result = server->on_close(server, msg.base.resource_id, 0);
821 }
822 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_CLOSE_RESPONSE, msg.base.resource_id, 0,
823 ✗ (socop_word_t)result, msg.base.user_param, 0);
824 ✗ result = SOCOP_OK;
825 ✗ break;
826 }
827
828 ✗ case SOCOP_MSG_SOCK_RECV_REQUEST:
829 {
830 ✗ if (!server->on_recv)
831 {
832 ✗ result = SOCOP_ERROR_NOTIMPL;
833 }
834 else
835 {
836 ✗ content_length = msg.base.resource_param;
837 ✗ if (content_length > SOCOP_MAX_CONTENT_LENGTH)
838 {
839 ✗ content_length = SOCOP_MAX_CONTENT_LENGTH;
840 }
841 ✗ result = server->on_recv(server, msg.base.resource_id, msg.content, content_length, &content_length);
842 ✗ if (SOCOP_OK != result)
843 {
844 ✗ content_length = 0;
845 }
846 }
847 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_RECV_RESPONSE, msg.base.resource_id, 0,
848 ✗ (socop_word_t)result, msg.base.user_param, (socop_word_t)content_length);
849 ✗ result = SOCOP_OK;
850 ✗ break;
851 }
852
853 ✗ case SOCOP_MSG_SOCK_RECVFROM_REQUEST:
854 {
855 ✗ if (!server->on_recvfrom)
856 {
857 ✗ result = SOCOP_ERROR_NOTIMPL;
858 }
859 else
860 {
861 ✗ content_length = msg.base.resource_param;
862 ✗ if (content_length > SOCOP_MAX_CONTENT_LENGTH)
863 {
864 ✗ content_length = SOCOP_MAX_CONTENT_LENGTH;
865 }
866 ✗ result = server->on_recvfrom(server, msg.base.resource_id, &msg.content[6], content_length, &content_length, &addr);
867 ✗ if (SOCOP_OK != result)
868 {
869 ✗ content_length = 0;
870 ✗ msg.base.resource_param = 0;
871 }
872 else
873 {
874 ✗ msg.base.resource_param = serialize_addr((unsigned char*)&msg.content[0], &addr);
875 }
876 }
877 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_RECVFROM_RESPONSE, msg.base.resource_id, msg.base.resource_param,
878 ✗ (socop_word_t)result, msg.base.user_param, (socop_word_t)content_length);
879 ✗ result = SOCOP_OK;
880 ✗ break;
881 }
882 ✗ case SOCOP_MSG_SOCK_SEND_REQUEST:
883 {
884 ✗ if (!server->on_send)
885 {
886 ✗ result = SOCOP_ERROR_NOTIMPL;
887 }
888 else
889 {
890 ✗ result = server->on_send(server, msg.base.resource_id, msg.content, content_length, &content_length);
891 ✗ if (SOCOP_OK != result)
892 {
893 ✗ content_length = 0;
894 }
895 }
896 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SEND_RESPONSE, msg.base.resource_id, (socop_word_t)content_length,
897 ✗ (socop_word_t)result, msg.base.user_param, 0);
898 ✗ result = SOCOP_OK;
899 ✗ break;
900 }
901
902 ✗ case SOCOP_MSG_SOCK_SENDTO_REQUEST:
903 {
904 ✗ if (!server->on_sendto)
905 {
906 ✗ result = SOCOP_ERROR_NOTIMPL;
907 }
908 else
909 {
910 ✗ deserialize_addr(&addr, (unsigned char const*)&msg.content[0]);
911 ✗ result = server->on_sendto(server, msg.base.resource_id, &msg.content[6], content_length - 6, &content_length, &addr);
912 ✗ if (SOCOP_OK != result)
913 {
914 ✗ content_length = 0;
915 }
916 }
917 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SENDTO_RESPONSE, msg.base.resource_id, (socop_word_t)content_length,
918 ✗ (socop_word_t)result, msg.base.user_param, 0);
919 ✗ result = SOCOP_OK;
920 ✗ break;
921 }
922
923 ✗ case SOCOP_MSG_SOCK_SHUTDOWN_REQUEST:
924 {
925 ✗ if (!server->on_shutdown)
926 {
927 ✗ result = SOCOP_ERROR_NOTIMPL;
928 }
929 else
930 {
931 ✗ result = server->on_shutdown(server, msg.base.resource_id, msg.base.resource_param);
932 }
933 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SHUTDOWN_RESPONSE, msg.base.resource_id, 0,
934 ✗ (socop_word_t)result, msg.base.user_param, 0);
935 ✗ result = SOCOP_OK;
936 ✗ break;
937 }
938
939 ✗ case SOCOP_MSG_SOCK_SELECT_REQUEST:
940 {
941 ✗ if (!server->on_select)
942 {
943 ✗ result = SOCOP_ERROR_NOTIMPL;
944 }
945 else
946 {
947 ✗ flags = msg.base.resource_param;
948 ✗ result = server->on_select(server, msg.base.resource_id, &flags);
949 }
950 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_SELECT_RESPONSE, msg.base.resource_id, (socop_word_t)flags,
951 ✗ (socop_word_t)result, msg.base.user_param, 0);
952 ✗ result = SOCOP_OK;
953 ✗ break;
954 }
955
956 ✗ case SOCOP_MSG_SOCK_PEER_REQUEST:
957 case SOCOP_MSG_SOCK_IOCTL_REQUEST:
958 {
959 ✗ result = SOCOP_ERROR_WRONGMESSAGE;
960 ✗ break;
961 }
962
963 ✗ default:
964 {
965 ✗ result = SOCOP_ERROR_WRONGMESSAGE;
966 ✗ break;
967 }
968 }
969
970 ✗ if (SOCOP_OK != result)
971 {
972 ✗ init_msg_base(&msg.base, SOCOP_MSG_SOCK_UNKNOWN, msg.base.resource_id, msg.base.resource_param,
973 ✗ (socop_word_t)result, msg.base.user_param, 0);
974 }
975
976 ✗ return socop_driver_send_msg(&server->driver, &msg.base, msg.content);
977 }
978
979