Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison src/gt_packet.c @ 0:d39e1d0d75b6
initial add
author | paulo@hit-nxdomain.opendns.com |
---|---|
date | Sat, 20 Feb 2010 21:18:28 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:53247e19bb40 |
---|---|
1 /* | |
2 * $Id: gt_packet.c,v 1.35 2004/04/17 06:05:53 hipnod Exp $ | |
3 * | |
4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net) | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify it | |
7 * under the terms of the GNU General Public License as published by the | |
8 * Free Software Foundation; either version 2, or (at your option) any | |
9 * later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 */ | |
16 | |
17 #include "gt_gnutella.h" | |
18 | |
19 #include "gt_packet.h" | |
20 | |
21 #include "gt_node.h" | |
22 #include "gt_netorg.h" | |
23 | |
24 #include "gt_utils.h" | |
25 | |
26 #include "gt_query_route.h" | |
27 #include "message/gt_message.h" /* gt_vendor_msg_get_{id,version} */ | |
28 | |
29 #include <stdarg.h> | |
30 | |
31 /*****************************************************************************/ | |
32 | |
33 GtPacket *gt_packet_new (uint8_t cmd, uint8_t ttl, gt_guid_t *guid) | |
34 { | |
35 GtPacket *packet; | |
36 unsigned char *data; | |
37 | |
38 if (!(packet = MALLOC (sizeof (GtPacket)))) | |
39 return NULL; | |
40 | |
41 if (!(data = MALLOC (GT_PACKET_INITIAL))) | |
42 { | |
43 free (packet); | |
44 return NULL; | |
45 } | |
46 | |
47 packet->data = data; | |
48 packet->len = GNUTELLA_HDR_LEN; | |
49 packet->data_len = GT_PACKET_INITIAL; | |
50 | |
51 /* | |
52 * Caller could provide GUID or request it be randomly initialized. | |
53 */ | |
54 if (guid) | |
55 gt_packet_set_guid (packet, guid); | |
56 else | |
57 gt_guid_init ((gt_guid_t *)packet->data); | |
58 | |
59 gt_packet_set_command (packet, cmd); | |
60 gt_packet_set_ttl (packet, ttl); | |
61 gt_packet_set_payload_len (packet, 0); | |
62 gt_packet_set_hops (packet, 0); | |
63 | |
64 /* set the offset to start at the end of the header */ | |
65 packet->offset = GNUTELLA_HDR_LEN; | |
66 | |
67 return packet; | |
68 } | |
69 | |
70 GtPacket *gt_packet_reply (GtPacket *src, uint8_t cmd) | |
71 { | |
72 GtPacket *packet; | |
73 uint8_t hops; | |
74 gt_guid_t *guid; | |
75 | |
76 hops = gt_packet_hops (src); | |
77 guid = gt_packet_guid (src); | |
78 | |
79 if (!(packet = gt_packet_new (cmd, hops + 1, guid))) | |
80 return NULL; | |
81 | |
82 return packet; | |
83 } | |
84 | |
85 GtPacket *gt_packet_vendor (const gt_vendor_msg_t *vmsg) | |
86 { | |
87 GtPacket *pkt; | |
88 | |
89 if (!(pkt = gt_packet_new (GT_MSG_VENDOR, 1, NULL))) | |
90 return NULL; | |
91 | |
92 gt_packet_put_ustr (pkt, vmsg->vendor_id, 4); | |
93 gt_packet_put_uint16 (pkt, vmsg->id); | |
94 gt_packet_put_uint16 (pkt, 1); /* vmsg version */ | |
95 | |
96 if (gt_packet_error (pkt)) | |
97 { | |
98 gt_packet_free (pkt); | |
99 return NULL; | |
100 } | |
101 | |
102 return pkt; | |
103 } | |
104 | |
105 void gt_packet_free (GtPacket *packet) | |
106 { | |
107 if (!packet) | |
108 return; | |
109 | |
110 free (packet->data); | |
111 free (packet); | |
112 } | |
113 | |
114 /*****************************************************************************/ | |
115 | |
116 gt_guid_t *gt_packet_guid (GtPacket *packet) | |
117 { | |
118 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
119 | |
120 return packet->data; | |
121 } | |
122 | |
123 uint32_t gt_packet_payload_len (GtPacket *packet) | |
124 { | |
125 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
126 | |
127 return get_payload_len (packet->data); | |
128 } | |
129 | |
130 uint32_t gt_packet_command (GtPacket *packet) | |
131 { | |
132 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
133 | |
134 return get_command (packet->data); | |
135 } | |
136 | |
137 uint8_t gt_packet_hops (GtPacket *packet) | |
138 { | |
139 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
140 | |
141 return get_hops (packet->data); | |
142 } | |
143 | |
144 uint8_t gt_packet_ttl (GtPacket *packet) | |
145 { | |
146 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
147 | |
148 return get_ttl (packet->data); | |
149 } | |
150 | |
151 /*****************************************************************************/ | |
152 | |
153 void gt_packet_set_guid (GtPacket *packet, gt_guid_t *guid) | |
154 { | |
155 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
156 | |
157 memcpy (packet->data, guid, 16); | |
158 } | |
159 | |
160 void gt_packet_set_command (GtPacket *packet, uint8_t cmd) | |
161 { | |
162 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
163 | |
164 get_command (packet->data) = cmd; | |
165 } | |
166 | |
167 void gt_packet_set_ttl (GtPacket *packet, uint8_t ttl) | |
168 { | |
169 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
170 | |
171 get_ttl (packet->data) = ttl; | |
172 } | |
173 | |
174 void gt_packet_set_hops (GtPacket *packet, uint8_t hops) | |
175 { | |
176 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
177 | |
178 get_hops (packet->data) = hops; | |
179 } | |
180 | |
181 void gt_packet_set_payload_len (GtPacket *packet, uint32_t len) | |
182 { | |
183 assert (packet->data_len >= GNUTELLA_HDR_LEN); | |
184 | |
185 len = htovl (len); | |
186 | |
187 memcpy (packet->data + 19, &len, 4); | |
188 } | |
189 | |
190 /*****************************************************************************/ | |
191 /* functions to read data from packets */ | |
192 | |
193 static uint8_t gt_get8 (unsigned char *src) | |
194 { | |
195 return *src; | |
196 } | |
197 | |
198 #define copy_bytes(src,sz,endian,swap,sizedvar_t,swap_net,swap_vax) \ | |
199 sizedvar_t r; \ | |
200 sizedvar_t v; \ | |
201 sizedvar_t n; \ | |
202 \ | |
203 memcpy (&r, src, sz); \ | |
204 \ | |
205 n = swap_net (r); \ | |
206 \ | |
207 assert_at_compile (BIG == 0x01); \ | |
208 if (endian & swap) \ | |
209 r = n; \ | |
210 \ | |
211 v = swap_vax (r); \ | |
212 \ | |
213 assert_at_compile (LITTLE == 0x00); \ | |
214 if (~endian & swap) \ | |
215 r = v; \ | |
216 \ | |
217 return r; | |
218 | |
219 static uint16_t gt_get16 (unsigned char *src, int endian, int swap) | |
220 { | |
221 copy_bytes (src, 2, endian, swap, uint16_t, ntohs, vtohs); | |
222 } | |
223 | |
224 static uint32_t gt_get32 (unsigned char *src, int endian, int swap) | |
225 { | |
226 copy_bytes (src, 4, endian, swap, uint32_t, ntohl, vtohl); | |
227 } | |
228 | |
229 /*****************************************************************************/ | |
230 | |
231 static BOOL gt_packet_resize (GtPacket *packet, size_t len) | |
232 { | |
233 size_t resize_len; | |
234 unsigned char *resized; | |
235 | |
236 if (!packet) | |
237 return FALSE; | |
238 | |
239 assert (len >= GNUTELLA_HDR_LEN); | |
240 assert (len < GT_PACKET_MAX); | |
241 | |
242 /* the buffer we have allocated is already large enough */ | |
243 if (packet->data_len >= len) | |
244 return TRUE; | |
245 | |
246 /* determine an appropriate resize length */ | |
247 for (resize_len = packet->data_len; resize_len < len; ) | |
248 { | |
249 if (resize_len == 0) | |
250 resize_len = GT_PACKET_INITIAL; | |
251 else | |
252 resize_len *= 2; | |
253 } | |
254 | |
255 if (!(resized = realloc (packet->data, resize_len))) | |
256 { | |
257 packet->error = TRUE; | |
258 return FALSE; | |
259 } | |
260 | |
261 memset (resized + packet->data_len, 0, resize_len - packet->data_len); | |
262 | |
263 /* modify the packet structure to reflect this resize */ | |
264 packet->data_len = resize_len; | |
265 packet->data = resized; | |
266 | |
267 return TRUE; | |
268 } | |
269 | |
270 int gt_packet_error (GtPacket *packet) | |
271 { | |
272 return packet->error; | |
273 } | |
274 | |
275 int gt_packet_seek (GtPacket *packet, int offset) | |
276 { | |
277 int old_offset; | |
278 | |
279 /* should we be setting packet->error here? */ | |
280 if (offset >= packet->len || offset < 0) | |
281 { | |
282 packet->error = TRUE; | |
283 return -1; | |
284 } | |
285 | |
286 old_offset = packet->offset; | |
287 packet->offset = offset; | |
288 | |
289 return old_offset; | |
290 } | |
291 | |
292 GtPacket *gt_packet_unserialize (unsigned char *data, size_t len) | |
293 { | |
294 GtPacket *packet; | |
295 | |
296 if (!(packet = gt_packet_new (0, 0, NULL))) | |
297 return NULL; | |
298 | |
299 if (len >= GT_PACKET_MAX) | |
300 { | |
301 gt_packet_free (packet); | |
302 return NULL; | |
303 } | |
304 | |
305 if (!gt_packet_resize (packet, len)) | |
306 { | |
307 GIFT_ERROR (("error resizing packet")); | |
308 gt_packet_free (packet); | |
309 return NULL; | |
310 } | |
311 | |
312 memcpy (packet->data, data, len); | |
313 | |
314 packet->len = len; | |
315 | |
316 /* Hmm, this should never happen, time to valgrind */ | |
317 if (gt_packet_payload_len (packet) != len - GNUTELLA_HDR_LEN) | |
318 { | |
319 GIFT_ERROR (("corrupt packet")); | |
320 gt_packet_free (packet); | |
321 return NULL; | |
322 } | |
323 | |
324 return packet; | |
325 } | |
326 | |
327 /*****************************************************************************/ | |
328 | |
329 uint8_t gt_packet_get_uint8 (GtPacket *packet) | |
330 { return gt_packet_get_uint (packet, 1, LITTLE, FALSE); } | |
331 | |
332 uint16_t gt_packet_get_uint16 (GtPacket *packet) | |
333 { return gt_packet_get_uint (packet, 2, LITTLE, TRUE); } | |
334 | |
335 uint32_t gt_packet_get_uint32 (GtPacket *packet) | |
336 { return gt_packet_get_uint (packet, 4, LITTLE, TRUE); } | |
337 | |
338 in_addr_t gt_packet_get_ip (GtPacket *packet) | |
339 { return gt_packet_get_uint (packet, 4, BIG, FALSE); } | |
340 | |
341 in_port_t gt_packet_get_port (GtPacket *packet) | |
342 { return gt_packet_get_uint (packet, 2, LITTLE, TRUE); } | |
343 | |
344 /*****************************************************************************/ | |
345 | |
346 uint32_t gt_packet_get_uint (GtPacket *packet, size_t size, | |
347 int endian, int swap) | |
348 { | |
349 uint32_t data32 = 0; | |
350 char *offs; | |
351 | |
352 assert (packet); | |
353 | |
354 /* check overrun */ | |
355 if (packet->offset + size > packet->len) | |
356 { | |
357 packet->error = TRUE; | |
358 return 0; | |
359 } | |
360 | |
361 offs = packet->data + packet->offset; | |
362 | |
363 switch (size) | |
364 { | |
365 case 1: | |
366 data32 = (uint32_t)gt_get8 (offs); | |
367 break; | |
368 case 2: | |
369 data32 = (uint32_t)gt_get16 (offs, endian, swap); | |
370 break; | |
371 case 4: | |
372 data32 = gt_get32 (offs, endian, swap); | |
373 break; | |
374 default: | |
375 printf ("%s: wtf are you doing?\n", __PRETTY_FUNCTION__); | |
376 return data32; | |
377 } | |
378 | |
379 packet->offset += size; | |
380 | |
381 return data32; | |
382 } | |
383 | |
384 /*****************************************************************************/ | |
385 | |
386 static int gt_packet_append (GtPacket *packet, const void *data, size_t size) | |
387 { | |
388 size_t required; | |
389 | |
390 if (!packet || !data || size == 0) | |
391 return FALSE; | |
392 | |
393 if (packet->data_len + size >= GT_PACKET_MAX) | |
394 { | |
395 packet->error = TRUE; | |
396 return FALSE; | |
397 } | |
398 | |
399 /* determine the total required space to append size bytes */ | |
400 required = packet->len + size; | |
401 | |
402 /* if we can't resize, gracefully fail...the caller should determine | |
403 * how bad this truly is */ | |
404 if (!gt_packet_resize (packet, required)) | |
405 return FALSE; | |
406 | |
407 /* append size bytes of data */ | |
408 memcpy (packet->data + packet->len, data, size); | |
409 | |
410 /* increment the length of this packet */ | |
411 packet->len += size; | |
412 | |
413 gt_packet_set_payload_len (packet, gt_packet_payload_len (packet) + size); | |
414 return TRUE; | |
415 } | |
416 | |
417 int gt_packet_put_uint (GtPacket *packet, void *data, size_t size, | |
418 int endian, int swap) | |
419 { | |
420 int ret; | |
421 uint16_t unet16; | |
422 uint32_t unet32; | |
423 | |
424 if (!data || size < 0 || size > sizeof (uint32_t)) | |
425 return FALSE; | |
426 | |
427 switch (size) | |
428 { | |
429 case 2: | |
430 unet16 = gt_get16 (data, endian, swap); | |
431 ret = gt_packet_append (packet, &unet16, size); | |
432 break; | |
433 case 4: | |
434 unet32 = gt_get32 (data, endian, swap); | |
435 ret = gt_packet_append (packet, &unet32, size); | |
436 break; | |
437 default: | |
438 ret = gt_packet_append (packet, data, size); | |
439 break; | |
440 } | |
441 | |
442 return ret; | |
443 } | |
444 | |
445 /*****************************************************************************/ | |
446 | |
447 int gt_packet_put_uint8 (GtPacket *packet, uint8_t byte) | |
448 { return gt_packet_put_uint (packet, &byte, 1, LITTLE, FALSE); } | |
449 | |
450 int gt_packet_put_uint16 (GtPacket *packet, uint16_t bytes) | |
451 { return gt_packet_put_uint (packet, &bytes, 2, LITTLE, TRUE); } | |
452 | |
453 int gt_packet_put_uint32 (GtPacket *packet, uint32_t bytes) | |
454 { return gt_packet_put_uint (packet, &bytes, 4, LITTLE, TRUE); } | |
455 | |
456 int gt_packet_put_ip (GtPacket *packet, in_addr_t ip) | |
457 { return gt_packet_put_uint (packet, &ip, 4, BIG, FALSE); } | |
458 | |
459 int gt_packet_put_port (GtPacket *packet, in_port_t port) | |
460 { return gt_packet_put_uint (packet, &port, 2, LITTLE, TRUE); } | |
461 | |
462 int gt_packet_put_ustr (GtPacket *packet, const unsigned char *str, size_t len) | |
463 { | |
464 assert (len > 0); | |
465 return gt_packet_append (packet, str, len); | |
466 } | |
467 | |
468 int gt_packet_put_str (GtPacket *packet, const char *str) | |
469 { | |
470 size_t len; | |
471 | |
472 if (!str) | |
473 return gt_packet_put_uint8 (packet, 0); | |
474 | |
475 len = strlen (str) + 1; | |
476 return gt_packet_put_ustr (packet, (const unsigned char *)str, len); | |
477 } | |
478 | |
479 /*****************************************************************************/ | |
480 | |
481 /* checks for the gt_packet_get_array sentinel given the size. the sentinel is | |
482 * defined as a full element filled with zeroes */ | |
483 static int array_sentinel (char *ptr, size_t size) | |
484 { | |
485 while (size--) | |
486 { | |
487 /* non-zero byte, this element couldnt be the sentinel */ | |
488 if (*ptr != 0) | |
489 return FALSE; | |
490 | |
491 ptr++; | |
492 } | |
493 | |
494 return TRUE; | |
495 } | |
496 | |
497 void *gt_packet_get_array (GtPacket *packet, size_t nmemb, size_t size, | |
498 int term, int endian, int swap) | |
499 { | |
500 char *start; | |
501 char *ptr; | |
502 char *end; | |
503 int n; | |
504 | |
505 assert (packet); | |
506 | |
507 /* we tried to read past the end of the packet */ | |
508 if (packet->offset >= packet->len) | |
509 { | |
510 packet->error = TRUE; | |
511 return NULL; | |
512 } | |
513 | |
514 start = packet->data + packet->offset; | |
515 end = packet->data + packet->len; | |
516 | |
517 /* TODO - optimize compares inside this loop */ | |
518 n = 0; | |
519 for (ptr = start; ptr + size < end; ptr += size, n++) | |
520 { | |
521 if (term && array_sentinel (ptr, size)) | |
522 break; | |
523 | |
524 if (nmemb > 0 && n >= nmemb) | |
525 break; | |
526 | |
527 if (swap) | |
528 { | |
529 switch (size) | |
530 { | |
531 case 2: | |
532 net_put16 (ptr, gt_get16 (ptr, endian, swap)); | |
533 break; | |
534 case 4: | |
535 net_put32 (ptr, gt_get32 (ptr, endian, swap)); | |
536 break; | |
537 default: | |
538 assert (0); | |
539 break; | |
540 } | |
541 } | |
542 } | |
543 | |
544 /* If the array was not null terminated, then terminate it now */ | |
545 if (term && !array_sentinel (ptr, size)) | |
546 { | |
547 uint32_t zero = 0; | |
548 size_t len; | |
549 | |
550 /* this is the length of the array we read */ | |
551 len = (ptr - start + size); | |
552 | |
553 /* we must have hit the end of the packet */ | |
554 assert (packet->offset + len == packet->len); | |
555 | |
556 if (!gt_packet_resize (packet, packet->len + size)) | |
557 { | |
558 packet->offset = packet->len; | |
559 return NULL; | |
560 } | |
561 | |
562 /* Hrm, this changes the payload, which we really dont want to do. */ | |
563 if (!gt_packet_append (packet, &zero, size)) | |
564 { | |
565 packet->offset = packet->len; | |
566 return NULL; | |
567 } | |
568 } | |
569 | |
570 /* invalid data...no sentinel found */ | |
571 if (ptr + size > end) | |
572 { | |
573 packet->offset = packet->len; | |
574 return NULL; | |
575 } | |
576 | |
577 /* ptr is at the sentinel right now, move one element out to calculate the | |
578 * next packet start */ | |
579 if (term) | |
580 ptr += size; | |
581 | |
582 /* this includes the sentinel now */ | |
583 packet->offset += (ptr - start); | |
584 | |
585 return start; | |
586 } | |
587 | |
588 char *gt_packet_get_str (GtPacket *packet) | |
589 { | |
590 return gt_packet_get_array (packet, 0, 1, TRUE, FALSE, FALSE); | |
591 } | |
592 | |
593 unsigned char *gt_packet_get_ustr (GtPacket *packet, size_t len) | |
594 { | |
595 return gt_packet_get_array (packet, len, 1, FALSE, FALSE, FALSE); | |
596 } | |
597 | |
598 /******************************************************************************/ | |
599 | |
600 static char *packet_command_str (unsigned char cmd) | |
601 { | |
602 static char buf[16]; | |
603 | |
604 switch (cmd) | |
605 { | |
606 case GT_MSG_PING: return "PING"; | |
607 case GT_MSG_PING_REPLY: return "PONG"; | |
608 case GT_MSG_BYE: return "BYE"; | |
609 case GT_MSG_QUERY_ROUTE: return "QROUTE"; | |
610 case GT_MSG_VENDOR: return "VMSG"; | |
611 case GT_MSG_VENDOR_STD: return "VMSG-S"; | |
612 case GT_MSG_PUSH: return "PUSH"; | |
613 case GT_MSG_QUERY: return "QUERY"; | |
614 case GT_MSG_QUERY_REPLY: return "HITS"; | |
615 | |
616 default: | |
617 snprintf (buf, sizeof (buf), "[<%02hx>]", cmd); | |
618 return buf; | |
619 } | |
620 } | |
621 | |
622 static void packet_log (char *data, int len, int sent, char *user_agent, | |
623 in_addr_t ip) | |
624 { | |
625 uint8_t cmd; | |
626 char user_buf[32]; | |
627 char *file; | |
628 static FILE *ascii_log; | |
629 | |
630 if (!ascii_log) | |
631 { | |
632 file = PACKET_ASCII_LOG; | |
633 | |
634 if (!(ascii_log = fopen (file, "w"))) | |
635 return; | |
636 } | |
637 | |
638 cmd = get_command (data); | |
639 | |
640 user_buf[0] = 0; | |
641 | |
642 /* copy the first few chars of user_agent to make it line up */ | |
643 if (user_agent) | |
644 { | |
645 strncpy (user_buf, user_agent, 21); | |
646 user_buf[21] = 0; | |
647 } | |
648 | |
649 fprintf (ascii_log, "%2s %-6s sz: %-5hu peer: %-22s [%s]\n", | |
650 (sent ? "<=" : "=>"), | |
651 packet_command_str (cmd), len, | |
652 (user_buf[0] ? user_buf : "(None)"), | |
653 (ip == 0 ? "None" : net_ip_str (ip))); | |
654 | |
655 fprint_hex (ascii_log, data, len); | |
656 } | |
657 | |
658 void gt_packet_log (GtPacket *packet, TCPC *src, int sent) | |
659 { | |
660 char *user_agent; | |
661 in_addr_t ip; | |
662 | |
663 if (!PACKET_DEBUG) | |
664 return; | |
665 | |
666 user_agent = NULL; | |
667 ip = 0; | |
668 | |
669 /* append the user-agent string to the packet log */ | |
670 if (src) | |
671 { | |
672 ip = src->host; | |
673 user_agent = dataset_lookupstr (GT_NODE(src)->hdr, "user-agent"); | |
674 } | |
675 | |
676 packet_log (packet->data, packet->len, sent, user_agent, ip); | |
677 } | |
678 | |
679 /******************************************************************************/ | |
680 | |
681 int gt_packet_send (TCPC *c, GtPacket *packet) | |
682 { | |
683 if (!c || c->fd < 0) | |
684 return -1; | |
685 | |
686 if (!gt_node_send (GT_NODE(c), packet)) | |
687 return -1; | |
688 | |
689 return 0; | |
690 } | |
691 | |
692 /******************************************************************************/ | |
693 | |
694 static int send_packetva (TCPC *c, uint8_t cmd, | |
695 gt_guid_t *guid, uint8_t ttl, | |
696 uint8_t hops, char *fmt, va_list args) | |
697 { | |
698 GtPacket *pkt; | |
699 char *p; | |
700 int short_fmt = FALSE; | |
701 int field_width = 0; | |
702 int ret; | |
703 | |
704 if (!(pkt = gt_packet_new (cmd, ttl, guid))) | |
705 return -1; | |
706 | |
707 for (p = fmt; *p; p++) | |
708 { | |
709 switch (*p) | |
710 { | |
711 case '%': | |
712 short_fmt = FALSE; | |
713 break; | |
714 case 'h': | |
715 short_fmt = TRUE; | |
716 break; | |
717 case 'l': | |
718 break; | |
719 case 'c': | |
720 { | |
721 uint8_t bits8 = (uint8_t) va_arg (args, int); | |
722 gt_packet_put_uint8 (pkt, bits8); | |
723 } | |
724 break; | |
725 case 'u': | |
726 if (short_fmt) | |
727 { | |
728 uint16_t bits16 = (uint16_t) va_arg (args, int); | |
729 gt_packet_put_uint16 (pkt, bits16); | |
730 } | |
731 else | |
732 { | |
733 uint32_t bits32 = (uint32_t) va_arg (args, int); | |
734 gt_packet_put_uint32 (pkt, bits32); | |
735 } | |
736 break; | |
737 case 's': | |
738 { | |
739 char *str = va_arg (args, char *); | |
740 gt_packet_put_str (pkt, str); | |
741 } | |
742 break; | |
743 case '0': case '1': case '2': case '3': case '4': case '5': | |
744 case '6': case '7': case '8': case '9': | |
745 field_width = field_width * 10 + (*p - '0'); | |
746 break; | |
747 case '*': | |
748 field_width = va_arg (args, int); | |
749 break; | |
750 case 'p': | |
751 { | |
752 unsigned char *ustr = va_arg (args, unsigned char *); | |
753 | |
754 gt_packet_put_ustr (pkt, ustr, field_width); | |
755 field_width = 0; | |
756 } | |
757 break; | |
758 default: | |
759 abort (); | |
760 break; | |
761 } | |
762 } | |
763 | |
764 if (gt_packet_error (pkt)) | |
765 { | |
766 gt_packet_free (pkt); | |
767 return -1; | |
768 } | |
769 | |
770 ret = gt_packet_send (c, pkt); | |
771 gt_packet_free (pkt); | |
772 | |
773 return ret; | |
774 } | |
775 | |
776 int gt_packet_send_fmt (TCPC *c, uint8_t cmd, | |
777 gt_guid_t *guid, uint8_t ttl, | |
778 uint8_t hops, char *fmt, ...) | |
779 { | |
780 va_list args; | |
781 int ret; | |
782 | |
783 va_start (args, fmt); | |
784 ret = send_packetva (c, cmd, guid, ttl, hops, fmt, args); | |
785 va_end (args); | |
786 | |
787 return ret; | |
788 } | |
789 | |
790 int gt_packet_reply_fmt (TCPC *c, GtPacket *packet, | |
791 uint8_t cmd, char *fmt, ...) | |
792 { | |
793 va_list args; | |
794 int ret; | |
795 size_t hops; | |
796 gt_guid_t *guid; | |
797 | |
798 guid = gt_packet_guid (packet); | |
799 hops = gt_packet_hops (packet); | |
800 | |
801 va_start (args, fmt); | |
802 ret = send_packetva (c, cmd, guid, hops + 1, 0, fmt, args); | |
803 va_end (args); | |
804 | |
805 return ret; | |
806 } | |
807 | |
808 /******************************************************************************/ | |
809 | |
810 int gt_packet_forward (GtPacket *packet, TCPC *c) | |
811 { | |
812 return -1; | |
813 } |