GCC Code Coverage Report


Directory: src/gate/
File: src/gate/interfaces/socop_impl.c
Date: 2026-06-15 21:53:51
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