GCC Code Coverage Report


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