Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_network_msg.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
26#include "nilorea/n_common.h"
27#include "nilorea/n_log.h"
28#include "nilorea/n_network.h"
30
36double double_swap(double value) {
37 double swaped = 0;
38 const unsigned char* src = (const unsigned char*)&value;
39 unsigned char* dst = (unsigned char*)&swaped;
40
41 /* swap bytes */
42 dst[0] = src[7];
43 dst[1] = src[6];
44 dst[2] = src[5];
45 dst[3] = src[4];
46 dst[4] = src[3];
47 dst[5] = src[2];
48 dst[6] = src[1];
49 dst[7] = src[0];
50
51 return swaped;
52} /* double_swap() */
53
59double htond(double value) {
60 /* if byte order is little like x86, PC, ... we swap to network notation */
61#if (BYTEORDER_ENDIAN == BYTEORDER_LITTLE_ENDIAN)
62 double ret = double_swap(value);
63#else
64 double ret = value;
65#endif
66 return ret;
67} /* htond() */
68
74double ntohd(double value) {
75 /* if byte order is little like x86, PC, ... we swap to network notation */
76#if (BYTEORDER_ENDIAN == BYTEORDER_LITTLE_ENDIAN)
77 double ret = double_swap(value);
78#else
79 double ret = value;
80#endif
81 return ret;
82} /* ntohd() */
83
89int create_msg(NETW_MSG** msg) {
90 if ((*msg)) {
91 n_log(LOG_ERR, "create_msg destination is valid and should be NULL !");
92 return FALSE;
93 }
94
95 Malloc((*msg), NETW_MSG, 1);
96 __n_assert(msg && (*msg), return FALSE);
97
98 (*msg)->tabstr = new_generic_list(MAX_LIST_ITEMS);
99 __n_assert((*msg)->tabstr, Free((*msg)); return FALSE);
100 (*msg)->tabint = new_generic_list(MAX_LIST_ITEMS);
101 __n_assert((*msg)->tabint, list_destroy(&(*msg)->tabstr); Free((*msg)); return FALSE);
102 (*msg)->tabflt = new_generic_list(MAX_LIST_ITEMS);
103 __n_assert((*msg)->tabflt, list_destroy(&(*msg)->tabstr); list_destroy(&(*msg)->tabint); Free((*msg)); return FALSE);
104
105 return TRUE;
106} /* create_msg( ... ) */
107
114 __n_assert(msg, return FALSE);
115 if ((*msg)) {
116 if ((*msg)->tabint) {
117 list_destroy(&(*msg)->tabint);
118 }
119 if ((*msg)->tabflt) {
120 list_destroy(&(*msg)->tabflt);
121 }
122 if ((*msg)->tabstr) {
123 list_destroy(&(*msg)->tabstr);
124 }
125 Free((*msg));
126 } else {
127 n_log(LOG_ERR, "(*msg) already NULL");
128 return FALSE;
129 }
130 return TRUE;
131} /* delete_msg */
132
138int empty_msg(NETW_MSG** msg) {
139 __n_assert(msg && (*msg), return FALSE);
140
141 list_empty((*msg)->tabint);
142 list_empty((*msg)->tabflt);
143 list_empty((*msg)->tabstr);
144
145 return TRUE;
146} /* empty_msg(...) */
147
155int add_nb_to_msg(NETW_MSG* msg, double value) {
156 double* new_val = NULL;
157
158 __n_assert(msg, return FALSE);
159
160 Malloc(new_val, double, 1);
161 __n_assert(new_val, return FALSE);
162
163 new_val[0] = value;
164
165 if (list_push(msg->tabflt, new_val, free) == FALSE) {
166 Free(new_val);
167 return FALSE;
168 }
169 return TRUE;
170} /* add_nb_to_msg( ... ) */
171
178int add_int_to_msg(NETW_MSG* msg, int value) {
179 int* new_val = NULL;
180
181 __n_assert(msg, return FALSE);
182
183 Malloc(new_val, int, 1);
184 __n_assert(new_val, return FALSE);
185
186 new_val[0] = value;
187
188 if (list_push(msg->tabint, new_val, free) == FALSE) {
189 Free(new_val);
190 return FALSE;
191 }
192 return TRUE;
193} /* add_int_to_msg( ... ) */
194
202 __n_assert(msg, return FALSE);
203 __n_assert(str, return FALSE);
204 __n_assert(str->data, return FALSE);
205 return list_push(msg->tabstr, str, free_nstr_ptr);
206} /* add_nstrptr_to_msg(...) */
207
215 __n_assert(msg, return FALSE);
216 __n_assert(str, return FALSE);
217 __n_assert(str->data, return FALSE);
218 N_STR* dup = nstrdup(str);
219 __n_assert(dup, return FALSE);
220 return list_push(msg->tabstr, dup, free_nstr_ptr);
221} /* add_nstrdup_to_msg(...) */
222
229int add_strdup_to_msg(NETW_MSG* msg, const char* str) {
230 __n_assert(msg, return FALSE);
231 __n_assert(str, return FALSE);
232
233 N_STR* dup = char_to_nstr(str);
234 __n_assert(dup, return FALSE);
235
236 return list_push(msg->tabstr, dup, free_nstr_ptr);
237} /* add_strdup_to_msg(...) */
238
245int get_nb_from_msg(NETW_MSG* msg, double* value) {
246 double* val = NULL;
247
248 __n_assert(msg, return FALSE);
249
250 val = list_shift(msg->tabflt, double);
251 if (val) {
252 (*value) = val[0];
253 Free(val);
254 return TRUE;
255 }
256 return FALSE;
257} /* get_nb_from_msg(...) */
258
265int get_int_from_msg(NETW_MSG* msg, int* value) {
266 int* val = NULL;
267
268 __n_assert(msg, return FALSE);
269
270 val = list_shift(msg->tabint, int);
271 if (val) {
272 (*value) = val[0];
273 Free(val);
274 return TRUE;
275 }
276 return FALSE;
277
278} /* get_int_from_msg(...) */
279
286int get_nstr_from_msg(NETW_MSG* msg, N_STR** value) {
287 N_STR* val = NULL;
288
289 __n_assert(msg, return FALSE);
290
291 val = list_shift(msg->tabstr, N_STR);
292 if (val) {
293 if ((*value)) {
294 n_log(LOG_ERR, "Previous pointer value %p overriden by pointer %p", (*value), val);
295 }
296 (*value) = val;
297 return TRUE;
298 }
299 return FALSE;
300} /* get_nstr_from_msg(...) */
301
308int get_str_from_msg(NETW_MSG* msg, char** value) {
309 N_STR* val = NULL;
310
311 __n_assert(msg, return FALSE);
312
313 val = list_shift(msg->tabstr, N_STR);
314 if (val) {
315 if ((*value)) {
316 n_log(LOG_ERR, "Previous pointer value %p overriden by pointer %p", (*value), val);
317 }
318
319 (*value) = val->data;
320 Free(val);
321 return TRUE;
322 }
323 return FALSE;
324} /* get_str_from_msg(...) */
325
332 size_t str_length = 0;
333 LIST_NODE* node = NULL;
334
335 N_STR *strptr = NULL,
336 *generated_str = NULL;
337
338 char* charptr = NULL;
339
340 __n_assert(msg, return NULL);
341
342 /* the first thing to do is to computer the resulting string size
343 the first 12 octets are for the number of ints , floats, strings in the message
344 */
345 str_length = 3 * sizeof(int32_t) + (msg->tabint->nb_items * sizeof(int32_t)) + (msg->tabflt->nb_items * sizeof(double));
346
347 /* let's count the eventual string blocks */
348 node = msg->tabstr->start;
349 while (node) {
350 strptr = (N_STR*)node->ptr;
351 str_length += sizeof(int32_t) + sizeof(int32_t) + strptr->written;
352 node = node->next;
353 }
354
355 /* preparing the new string */
356 Malloc(generated_str, N_STR, 1);
357 __n_assert(generated_str, return NULL);
358 Malloc(generated_str->data, char, str_length + 1);
359 __n_assert(generated_str->data, Free(generated_str); return NULL);
360
361 generated_str->length = str_length + 1;
362 generated_str->written = str_length;
363
364 /* copying header */
365 charptr = generated_str->data;
366
367 /* testing limits */
368 if (msg->tabint->nb_items >= UINT32_MAX) {
369 n_log(LOG_ERR, "too much items (>=UINT32_MAX) in int list of message %p", msg);
370 free_nstr(&generated_str);
371 return NULL;
372 }
373 if (msg->tabflt->nb_items >= UINT32_MAX) {
374 n_log(LOG_ERR, "too much items (>=UINT32_MAX) in float list of message %p", msg);
375 free_nstr(&generated_str);
376 return NULL;
377 }
378 if (msg->tabstr->nb_items >= UINT32_MAX) {
379 n_log(LOG_ERR, "too much items (>=UINT32_MAX) in string list of message %p", msg);
380 free_nstr(&generated_str);
381 return NULL;
382 }
383
384 /* byte order */
385 uint32_t nb_int_items = htonl((uint32_t)msg->tabint->nb_items);
386 uint32_t nb_float_items = htonl((uint32_t)msg->tabflt->nb_items);
387 uint32_t nb_str_items = htonl((uint32_t)msg->tabstr->nb_items);
388
389 /* number of ints inside the message */
390 memcpy(charptr, &nb_int_items, sizeof(uint32_t));
391 charptr += sizeof(uint32_t);
392 /* number of doubles inside the message */
393 memcpy(charptr, &nb_float_items, sizeof(uint32_t));
394 charptr += sizeof(uint32_t);
395 /* number of string inside the message */
396 memcpy(charptr, &nb_str_items, sizeof(uint32_t));
397 charptr += sizeof(uint32_t);
398
399 /* if there are numbers, copy all them ! */
400 node = msg->tabint->start;
401 while (node) {
402 uint32_t* nbptr = (uint32_t*)node->ptr;
403 uint32_t val = htonl(nbptr[0]);
404 memcpy(charptr, &val, sizeof(uint32_t));
405 charptr += sizeof(uint32_t);
406 node = node->next;
407 }
408
409 /* if there are numbers, copy all them ! */
410 node = msg->tabflt->start;
411 while (node) {
412 const double* nbptr = (const double*)node->ptr;
413 double val = htond(nbptr[0]);
414 memcpy(charptr, &val, sizeof(double));
415 charptr += sizeof(double);
416 node = node->next;
417 }
418
419 /* if there are strings, copy all them ! */
420 if (msg->tabstr->nb_items > 0) {
421 node = msg->tabstr->start;
422 while (node) {
423 strptr = (N_STR*)node->ptr;
424 if (strptr->length >= UINT32_MAX) {
425 n_log(LOG_ERR, "string too long (>=UINT32_MAX) in string list of message %p", msg);
426 free_nstr(&generated_str);
427 return NULL;
428 }
429 uint32_t var = htonl((uint32_t)strptr->length);
430 memcpy(charptr, &var, sizeof(uint32_t));
431 charptr += sizeof(uint32_t);
432
433 if (strptr->written >= UINT32_MAX) {
434 n_log(LOG_ERR, "string too long (>=UINT32_MAX) in string list of message %p", msg);
435 free_nstr(&generated_str);
436 return NULL;
437 }
438 var = htonl((uint32_t)strptr->written);
439 memcpy(charptr, &var, sizeof(uint32_t));
440 charptr += sizeof(uint32_t);
441
442 memcpy(charptr, strptr->data, strptr->written);
443 charptr += strptr->written;
444 node = node->next;
445 }
446 }
447
448 return generated_str;
449} /* make_str_from_msg(...) */
450
457 NETW_MSG* generated_msg = NULL;
458 N_STR* tmpstr = NULL;
459
460 char* charptr = NULL;
461
462 uint32_t it,
463 nb_int = 0,
464 nb_flt = 0,
465 nb_str = 0;
466 int32_t tmpnb = 0;
467
468 double tmpflt = 0;
469
470 __n_assert(str, return NULL);
471
472 charptr = str->data;
473
474 /* need at least 3 uint32_t for the header */
475 if (str->written < 3 * sizeof(uint32_t)) {
476 n_log(LOG_ERR, "message too short: %zu bytes, need at least %zu", str->written, 3 * sizeof(uint32_t));
477 return NULL;
478 }
479
480 create_msg(&generated_msg);
481
482 __n_assert(generated_msg, return NULL);
483
484 memcpy(&nb_int, charptr, sizeof(uint32_t));
485 charptr += sizeof(uint32_t);
486 nb_int = ntohl(nb_int);
487
488 memcpy(&nb_flt, charptr, sizeof(uint32_t));
489 charptr += sizeof(uint32_t);
490 nb_flt = ntohl(nb_flt);
491
492 memcpy(&nb_str, charptr, sizeof(uint32_t));
493 charptr += sizeof(uint32_t);
494 nb_str = ntohl(nb_str);
495
496 /* validate that the message is large enough for the claimed int and float counts.
497 * Use division-based checks to avoid size_t overflow on 32-bit platforms. */
498 size_t remaining = str->written - 3 * sizeof(uint32_t);
499
500 if (nb_int > remaining / sizeof(uint32_t)) {
501 n_log(LOG_ERR, "message claims %u ints but only %zu bytes remain", nb_int, remaining);
502 delete_msg(&generated_msg);
503 return NULL;
504 }
505 remaining -= (size_t)nb_int * sizeof(uint32_t);
506
507 if (nb_flt > remaining / sizeof(double)) {
508 n_log(LOG_ERR, "message claims %u floats but only %zu bytes remain", nb_flt, remaining);
509 delete_msg(&generated_msg);
510 return NULL;
511 }
512 remaining -= (size_t)nb_flt * sizeof(double);
513
514 if (nb_int > 0) {
515 for (it = 0; it < nb_int; it++) {
516 memcpy(&tmpnb, charptr, sizeof(uint32_t));
517 tmpnb = (int32_t)ntohl((uint32_t)tmpnb);
518 charptr += sizeof(uint32_t);
519 if (add_int_to_msg(generated_msg, tmpnb) == FALSE) {
520 n_log(LOG_ERR, "failed to add int %u/%u to message", it, nb_int);
521 delete_msg(&generated_msg);
522 return NULL;
523 }
524 }
525 }
526
527 if (nb_flt > 0) {
528 for (it = 0; it < nb_flt; it++) {
529 memcpy(&tmpflt, charptr, sizeof(double));
530 tmpflt = ntohd(tmpflt);
531 charptr += sizeof(double);
532 if (add_nb_to_msg(generated_msg, tmpflt) == FALSE) {
533 n_log(LOG_ERR, "failed to add float %u/%u to message", it, nb_flt);
534 delete_msg(&generated_msg);
535 return NULL;
536 }
537 }
538 }
539
540 if (nb_str > 0) {
541 /* sanity check: each string needs at least 2 uint32_t for headers */
542 if ((size_t)nb_str > remaining / (2 * sizeof(uint32_t))) {
543 n_log(LOG_ERR, "message claims %u strings but only %zu bytes remain (need at least %zu for headers)",
544 nb_str, remaining, (size_t)nb_str * 2 * sizeof(uint32_t));
545 delete_msg(&generated_msg);
546 return NULL;
547 }
548
549 for (it = 0; it < nb_str; it++) {
550 /* check space for length + written headers */
551 if (remaining < 2 * sizeof(uint32_t)) {
552 n_log(LOG_ERR, "string %u/%u: not enough data for string headers (%zu remaining)", it, nb_str, remaining);
553 delete_msg(&generated_msg);
554 return NULL;
555 }
556
557 Malloc(tmpstr, N_STR, 1);
558 __n_assert(tmpstr, { delete_msg(&generated_msg); return NULL; });
559
560 uint32_t var = 0;
561 memcpy(&var, charptr, sizeof(uint32_t));
562 charptr += sizeof(uint32_t);
563 tmpstr->length = ntohl(var);
564
565 memcpy(&var, charptr, sizeof(uint32_t));
566 charptr += sizeof(uint32_t);
567 tmpstr->written = ntohl(var);
568 remaining -= 2 * sizeof(uint32_t);
569
570 /* validate written < length (N_STR requires room for trailing '\0') */
571 if (tmpstr->length == 0 || tmpstr->written >= tmpstr->length) {
572 n_log(LOG_ERR, "string %u/%u: written (%zu) >= length (%zu), violates N_STR invariant", it, nb_str, tmpstr->written, tmpstr->length);
573 Free(tmpstr);
574 delete_msg(&generated_msg);
575 return NULL;
576 }
577
578 /* validate remaining buffer has enough for written bytes */
579 if (tmpstr->written > remaining) {
580 n_log(LOG_ERR, "string %u/%u: written size %zu exceeds remaining %zu bytes", it, nb_str, tmpstr->written, remaining);
581 Free(tmpstr);
582 delete_msg(&generated_msg);
583 return NULL;
584 }
585
586 /* sanity cap on allocation size to prevent DoS via huge allocation */
587 if (tmpstr->length > NETW_MSG_MAX_STRING_LENGTH) {
588 n_log(LOG_ERR, "string %u/%u: length %zu exceeds NETW_MSG_MAX_STRING_LENGTH (%zu)", it, nb_str, tmpstr->length, (size_t)NETW_MSG_MAX_STRING_LENGTH);
589 Free(tmpstr);
590 delete_msg(&generated_msg);
591 return NULL;
592 }
593
594 /* allocate based on written+1 (not untrusted length) to prevent memory-DoS
595 * where attacker sets length near cap but written tiny */
596 Malloc(tmpstr->data, char, tmpstr->written + 1);
597 __n_assert(tmpstr->data, { Free(tmpstr); delete_msg(&generated_msg); return NULL; });
598 tmpstr->length = tmpstr->written + 1;
599
600 memcpy(tmpstr->data, charptr, tmpstr->written);
601 tmpstr->data[tmpstr->written] = '\0';
602 charptr += tmpstr->written;
603 remaining -= tmpstr->written;
604
605 if (add_nstrptr_to_msg(generated_msg, tmpstr) == FALSE) {
606 Free(tmpstr->data);
607 Free(tmpstr);
608 delete_msg(&generated_msg);
609 return NULL;
610 }
611 }
612 }
613 return generated_msg;
614} /* make_msg_from_str(...) */
615
616#ifndef NO_NETMSG_API
617
626N_STR* netmsg_make_ping(int type, int id_from, int id_to, int time) {
627 NETW_MSG* msg = NULL;
628
629 N_STR* tmpstr = NULL;
630
631 create_msg(&msg);
632
633 __n_assert(msg, return NULL);
634
635 if (add_int_to_msg(msg, type) == FALSE) {
636 delete_msg(&msg);
637 return NULL;
638 }
639 if (add_int_to_msg(msg, id_from) == FALSE) {
640 delete_msg(&msg);
641 return NULL;
642 }
643 if (add_int_to_msg(msg, id_to) == FALSE) {
644 delete_msg(&msg);
645 return NULL;
646 }
647 if (add_int_to_msg(msg, time) == FALSE) {
648 delete_msg(&msg);
649 return NULL;
650 }
651
652 tmpstr = make_str_from_msg(msg);
653 delete_msg(&msg);
654
655 return tmpstr;
656} /* netmsg_make_ping() */
657
666N_STR* netmsg_make_ident(int type, int id, N_STR* name, N_STR* passwd) {
667 NETW_MSG* msg = NULL;
668 N_STR* tmpstr = NULL;
669
670 create_msg(&msg);
671 __n_assert(msg, return NULL);
672
673 if (add_int_to_msg(msg, type) == FALSE) {
674 delete_msg(&msg);
675 return NULL;
676 }
677 if (add_int_to_msg(msg, id) == FALSE) {
678 delete_msg(&msg);
679 return NULL;
680 }
681
682 if (add_nstrdup_to_msg(msg, name) == FALSE) {
683 delete_msg(&msg);
684 return NULL;
685 }
686 if (add_nstrdup_to_msg(msg, passwd) == FALSE) {
687 delete_msg(&msg);
688 return NULL;
689 }
690
691 tmpstr = make_str_from_msg(msg);
692 delete_msg(&msg);
693
694 return tmpstr;
695} /* netmsg_make_ident() */
696
709N_STR* netmsg_make_position_msg(int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp) {
710 NETW_MSG* msg = NULL;
711 N_STR* tmpstr = NULL;
712
713 create_msg(&msg);
714
715 __n_assert(msg, return NULL);
716
717 if (add_int_to_msg(msg, NETMSG_POSITION) == FALSE) {
718 delete_msg(&msg);
719 return NULL;
720 }
721 if (add_int_to_msg(msg, id) == FALSE) {
722 delete_msg(&msg);
723 return NULL;
724 }
725 if (add_nb_to_msg(msg, X) == FALSE) {
726 delete_msg(&msg);
727 return NULL;
728 }
729 if (add_nb_to_msg(msg, Y) == FALSE) {
730 delete_msg(&msg);
731 return NULL;
732 }
733 if (add_nb_to_msg(msg, vx) == FALSE) {
734 delete_msg(&msg);
735 return NULL;
736 }
737 if (add_nb_to_msg(msg, vy) == FALSE) {
738 delete_msg(&msg);
739 return NULL;
740 }
741 if (add_nb_to_msg(msg, acc_x) == FALSE) {
742 delete_msg(&msg);
743 return NULL;
744 }
745 if (add_nb_to_msg(msg, acc_y) == FALSE) {
746 delete_msg(&msg);
747 return NULL;
748 }
749 if (add_int_to_msg(msg, time_stamp) == FALSE) {
750 delete_msg(&msg);
751 return NULL;
752 }
753
754 tmpstr = make_str_from_msg(msg);
755 delete_msg(&msg);
756 return tmpstr;
757} /* netmsg_make_position_msg() */
758
769N_STR* netmsg_make_string_msg(int id_from, int id_to, N_STR* name, N_STR* chan, N_STR* txt, int color) {
770 NETW_MSG* msg = NULL;
771
772 N_STR* tmpstr = NULL;
773
774 create_msg(&msg);
775
776 __n_assert(msg, return NULL);
777
778 if (add_int_to_msg(msg, NETMSG_STRING) == FALSE) {
779 delete_msg(&msg);
780 return NULL;
781 }
782 if (add_int_to_msg(msg, id_from) == FALSE) {
783 delete_msg(&msg);
784 return NULL;
785 }
786 if (add_int_to_msg(msg, id_to) == FALSE) {
787 delete_msg(&msg);
788 return NULL;
789 }
790 if (add_int_to_msg(msg, color) == FALSE) {
791 delete_msg(&msg);
792 return NULL;
793 }
794
795 if (add_nstrdup_to_msg(msg, name) == FALSE) {
796 delete_msg(&msg);
797 return NULL;
798 }
799 if (add_nstrdup_to_msg(msg, chan) == FALSE) {
800 delete_msg(&msg);
801 return NULL;
802 }
803 if (add_nstrdup_to_msg(msg, txt) == FALSE) {
804 delete_msg(&msg);
805 return NULL;
806 }
807
808 tmpstr = make_str_from_msg(msg);
809 delete_msg(&msg);
810 __n_assert(tmpstr, return NULL);
811
812 return tmpstr;
813
814} /* netmsg_make_string_msg */
815
821 NETW_MSG* msg = NULL;
822 N_STR* tmpstr = NULL;
823
824 create_msg(&msg);
825 __n_assert(msg, return NULL);
826
827 if (add_int_to_msg(msg, NETMSG_QUIT) == FALSE) {
828 delete_msg(&msg);
829 return NULL;
830 }
831 tmpstr = make_str_from_msg(msg);
832 delete_msg(&msg);
833 __n_assert(tmpstr, return NULL);
834
835 return tmpstr;
836} /* netmsg_make_quit_msg() */
837
844 uint32_t nb_int = 0;
845 int32_t tmpnb = 0;
846 char* charptr = NULL;
847
848 __n_assert(msg, return -1);
849 __n_assert(msg->data, return -1);
850
851 /* need at least 3*uint32 header + 1*uint32 for the type int */
852 if (msg->written < 4 * sizeof(uint32_t)) return -1;
853
854 charptr = msg->data;
855
856 /* read nb_int from the header to verify the int section is present */
857 memcpy(&nb_int, charptr, sizeof(uint32_t));
858 nb_int = ntohl(nb_int);
859
860 if (nb_int < 1) {
861 n_log(LOG_ERR, "netw_msg_get_type: message has no int fields (nb_int=%u), cannot read type", nb_int);
862 return -1;
863 }
864
865 /* bypass nb_int, nb_flt, nb_str header fields to reach the first int (type) */
866 charptr += 3 * sizeof(uint32_t);
867 memcpy(&tmpnb, charptr, sizeof(uint32_t));
868 tmpnb = (int32_t)ntohl((uint32_t)tmpnb);
869
870 return tmpnb;
871} /* netw_msg_get_type(...) */
872
882int netw_get_ident(N_STR* msg, int* type, int* ident, N_STR** name, N_STR** passwd) {
883 NETW_MSG* netmsg = NULL;
884
885 __n_assert(msg, return FALSE);
886
887 netmsg = make_msg_from_str(msg);
888
889 __n_assert(netmsg, return FALSE);
890
891 if (get_int_from_msg(netmsg, type) != TRUE ||
892 get_int_from_msg(netmsg, ident) != TRUE) {
893 n_log(LOG_ERR, "failed to extract type/ident from ident message");
894 delete_msg(&netmsg);
895 return FALSE;
896 }
897
898 if ((*type) != NETMSG_IDENT_REQUEST && (*type) != NETMSG_IDENT_REPLY_OK && (*type) != NETMSG_IDENT_REPLY_NOK) {
899 n_log(LOG_ERR, "unknow (*type) %d", (*type));
900 delete_msg(&netmsg);
901 return FALSE;
902 }
903
904 if (get_nstr_from_msg(netmsg, name) != TRUE ||
905 get_nstr_from_msg(netmsg, passwd) != TRUE) {
906 n_log(LOG_ERR, "failed to extract name/passwd from ident message");
907 free_nstr(name);
908 free_nstr(passwd);
909 delete_msg(&netmsg);
910 return FALSE;
911 }
912
913 delete_msg(&netmsg);
914
915 return TRUE;
916} /* netw_get_ident( ... ) */
917
931int netw_get_position(N_STR* msg, int* id, double* X, double* Y, double* vx, double* vy, double* acc_x, double* acc_y, int* time_stamp) {
932 NETW_MSG* netmsg = NULL;
933
934 int type = 0;
935
936 __n_assert(msg, return FALSE);
937
938 netmsg = make_msg_from_str(msg);
939
940 __n_assert(netmsg, return FALSE);
941
942 if (get_int_from_msg(netmsg, &type) != TRUE) {
943 n_log(LOG_ERR, "failed to extract type from position message");
944 delete_msg(&netmsg);
945 return FALSE;
946 }
947
948 if (type != NETMSG_POSITION) {
949 delete_msg(&netmsg);
950 return FALSE;
951 }
952
953 if (get_int_from_msg(netmsg, id) != TRUE ||
954 get_nb_from_msg(netmsg, X) != TRUE ||
955 get_nb_from_msg(netmsg, Y) != TRUE ||
956 get_nb_from_msg(netmsg, vx) != TRUE ||
957 get_nb_from_msg(netmsg, vy) != TRUE ||
958 get_nb_from_msg(netmsg, acc_x) != TRUE ||
959 get_nb_from_msg(netmsg, acc_y) != TRUE ||
960 get_int_from_msg(netmsg, time_stamp) != TRUE) {
961 n_log(LOG_ERR, "failed to extract fields from position message");
962 delete_msg(&netmsg);
963 return FALSE;
964 }
965
966 delete_msg(&netmsg);
967
968 return TRUE;
969} /* netw_get_position( ... ) */
970
982int netw_get_string(N_STR* msg, int* id, N_STR** name, N_STR** chan, N_STR** txt, int* color) {
983 NETW_MSG* netmsg = NULL;
984
985 int type = 0;
986
987 __n_assert(msg, return FALSE);
988
989 netmsg = make_msg_from_str(msg);
990
991 __n_assert(netmsg, return FALSE);
992
993 if (get_int_from_msg(netmsg, &type) != TRUE) {
994 n_log(LOG_ERR, "failed to extract type from string message");
995 delete_msg(&netmsg);
996 return FALSE;
997 }
998
999 if (type != NETMSG_STRING) {
1000 delete_msg(&netmsg);
1001 return FALSE;
1002 }
1003
1004 int id_to = 0;
1005 if (get_int_from_msg(netmsg, id) != TRUE ||
1006 get_int_from_msg(netmsg, &id_to) != TRUE ||
1007 get_int_from_msg(netmsg, color) != TRUE) {
1008 n_log(LOG_ERR, "failed to extract int fields from string message");
1009 delete_msg(&netmsg);
1010 return FALSE;
1011 }
1012
1013 if (get_nstr_from_msg(netmsg, name) != TRUE ||
1014 get_nstr_from_msg(netmsg, chan) != TRUE ||
1015 get_nstr_from_msg(netmsg, txt) != TRUE) {
1016 n_log(LOG_ERR, "failed to extract string fields from string message");
1017 free_nstr(name);
1018 free_nstr(chan);
1019 free_nstr(txt);
1020 delete_msg(&netmsg);
1021 return FALSE;
1022 }
1023
1024 delete_msg(&netmsg);
1025
1026 return TRUE;
1027
1028} /* netw_get_string( ... ) */
1029
1039int netw_get_ping(N_STR* msg, int* type, int* from, int* to, int* time) {
1040 NETW_MSG* netmsg;
1041
1042 __n_assert(msg, return FALSE);
1043
1044 netmsg = make_msg_from_str(msg);
1045
1046 __n_assert(netmsg, return FALSE);
1047
1048 if (get_int_from_msg(netmsg, type) != TRUE) {
1049 n_log(LOG_ERR, "failed to extract type from ping message");
1050 delete_msg(&netmsg);
1051 return FALSE;
1052 }
1053
1054 if ((*type) != NETMSG_PING_REQUEST && (*type) != NETMSG_PING_REPLY) {
1055 delete_msg(&netmsg);
1056 return FALSE;
1057 }
1058
1059 if (get_int_from_msg(netmsg, from) != TRUE ||
1060 get_int_from_msg(netmsg, to) != TRUE ||
1061 get_int_from_msg(netmsg, time) != TRUE) {
1062 n_log(LOG_ERR, "failed to extract fields from ping message");
1063 delete_msg(&netmsg);
1064 return FALSE;
1065 }
1066
1067 delete_msg(&netmsg);
1068
1069 return TRUE;
1070} /* netw_get_ping( ... ) */
1071
1078 __n_assert(msg, return FALSE);
1079
1080 NETW_MSG* netmsg = NULL;
1081 netmsg = make_msg_from_str(msg);
1082 __n_assert(netmsg, return FALSE);
1083
1084 int type = -1;
1085 get_int_from_msg(netmsg, &type);
1086 if (type != NETMSG_QUIT) {
1087 delete_msg(&netmsg);
1088 return FALSE;
1089 }
1090 delete_msg(&netmsg);
1091 return TRUE;
1092} /* netw_get_quit( ... ) */
1093
1094#endif // NO_NETMSG_API
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
void * ptr
void pointer to store
Definition n_list.h:45
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:65
size_t nb_items
number of item currently in the list
Definition n_list.h:60
struct LIST_NODE * next
pointer to the next node
Definition n_list.h:51
#define list_shift(__LIST_, __TYPE_)
Shift macro helper for void pointer casting.
Definition n_list.h:95
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition n_list.c:500
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:227
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:547
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:36
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:74
Structure of a generic list node.
Definition n_list.h:43
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_ERR
error conditions
Definition n_log.h:75
size_t written
size of the written data inside the string
Definition n_str.h:66
char * data
the string
Definition n_str.h:62
size_t length
length of string (in case we wanna keep information after the 0 end of string value)
Definition n_str.h:64
void free_nstr_ptr(void *ptr)
Free a N_STR pointer structure.
Definition n_str.c:69
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:201
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
Definition n_str.c:708
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:254
A box including a string and his lenght.
Definition n_str.h:60
LIST * tabflt
array of casted double value
LIST * tabstr
array of N_STR
LIST * tabint
array of int
#define NETMSG_IDENT_REQUEST
Network Message is identification request: (int)type , (int)id , (N_STR *)name , (N_STR *)password.
double htond(double value)
If needed swap bytes for a double.
int get_str_from_msg(NETW_MSG *msg, char **value)
Get a string from a message string list.
int add_strdup_to_msg(NETW_MSG *msg, const char *str)
Add a copy of char *str to the string list in the message.
int netw_get_position(N_STR *msg, int *id, double *X, double *Y, double *vx, double *vy, double *acc_x, double *acc_y, int *time_stamp)
Retrieves position from netwmsg.
#define NETMSG_PING_REQUEST
Network Message is ping request: (int)type , (int)id_from , (int)id_to.
#define NETMSG_IDENT_REPLY_NOK
Network Message is identification reply NON OK: (int)type , (int)id , (N_STR *)name ,...
#define NETMSG_STRING
Network Message is string: (int)type , (int)id , (N_STR *)name , (N_STR *)chan , (N_STR *)text ,...
#define NETMSG_PING_REPLY
Network Message is ping reply: (int)type , (int)id_from , (int)id_to.
NETW_MSG * make_msg_from_str(N_STR *str)
Make a single message of the string.
int empty_msg(NETW_MSG **msg)
Empty a NETW_MSG *object.
double double_swap(double value)
Swap bytes endiannes for a double.
N_STR * make_str_from_msg(NETW_MSG *msg)
Make a single string of the message.
int netw_get_ping(N_STR *msg, int *type, int *from, int *to, int *time)
Retrieves a ping travel elapsed time.
int add_nstrptr_to_msg(NETW_MSG *msg, N_STR *str)
Add a string to the string list in the message.
int get_nb_from_msg(NETW_MSG *msg, double *value)
Get a number from a message number list.
#define NETMSG_QUIT
Network asking for exit.
int netw_get_quit(N_STR *msg)
get a formatted NETWMSG_QUIT message from the specified network
int create_msg(NETW_MSG **msg)
Create a NETW_MSG *object.
#define NETMSG_POSITION
Network Message position: (int)type , (int)id , (int)X , (int)Y , (int)x_shift , (int)y_shift ,...
N_STR * netmsg_make_position_msg(int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp)
make a network NETMSG_POSITION message with given parameters
int netw_msg_get_type(N_STR *msg)
Get the type of message without killing the first number. Use with netw_get_XXX.
int get_nstr_from_msg(NETW_MSG *msg, N_STR **value)
Get a string from a message string list.
N_STR * netmsg_make_ident(int type, int id, N_STR *name, N_STR *passwd)
Add a formatted NETWMSG_IDENT message to the specified network.
int add_nstrdup_to_msg(NETW_MSG *msg, N_STR *str)
Add a copy of str to the string list in the message.
int add_int_to_msg(NETW_MSG *msg, int value)
Add an int to the int list int the message.
double ntohd(double value)
If needed swap bytes for a double.
#define NETMSG_IDENT_REPLY_OK
Network Message is identification reply OK : (int)type , (int)id , (N_STR *)name ,...
int netw_get_string(N_STR *msg, int *id, N_STR **name, N_STR **chan, N_STR **txt, int *color)
Retrieves string from netwmsg.
#define NETW_MSG_MAX_STRING_LENGTH
Maximum allowed length for a single string inside a network message (default: 1 GB).
int delete_msg(NETW_MSG **msg)
Delete a NETW_MSG *object.
int add_nb_to_msg(NETW_MSG *msg, double value)
Add an float to the message.
N_STR * netmsg_make_quit_msg(void)
make a generic network NETMSG_QUIT message
N_STR * netmsg_make_ping(int type, int id_from, int id_to, int time)
Make a ping message to send to a network.
int netw_get_ident(N_STR *msg, int *type, int *ident, N_STR **name, N_STR **passwd)
Retrieves identification from netwmsg.
N_STR * netmsg_make_string_msg(int id_from, int id_to, N_STR *name, N_STR *chan, N_STR *txt, int color)
make a network NETMSG_STRING message with given parameters
int get_int_from_msg(NETW_MSG *msg, int *value)
Get an int from a message int list.
network message, array of char and int
Common headers and low-level functions & define.
Generic log system.
Network Engine.
Network messages , serialization tools.