Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gt_packet.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,813 @@ 1.4 +/* 1.5 + * $Id: gt_packet.c,v 1.35 2004/04/17 06:05:53 hipnod Exp $ 1.6 + * 1.7 + * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net) 1.8 + * 1.9 + * This program is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License as published by the 1.11 + * Free Software Foundation; either version 2, or (at your option) any 1.12 + * later version. 1.13 + * 1.14 + * This program is distributed in the hope that it will be useful, but 1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + * General Public License for more details. 1.18 + */ 1.19 + 1.20 +#include "gt_gnutella.h" 1.21 + 1.22 +#include "gt_packet.h" 1.23 + 1.24 +#include "gt_node.h" 1.25 +#include "gt_netorg.h" 1.26 + 1.27 +#include "gt_utils.h" 1.28 + 1.29 +#include "gt_query_route.h" 1.30 +#include "message/gt_message.h" /* gt_vendor_msg_get_{id,version} */ 1.31 + 1.32 +#include <stdarg.h> 1.33 + 1.34 +/*****************************************************************************/ 1.35 + 1.36 +GtPacket *gt_packet_new (uint8_t cmd, uint8_t ttl, gt_guid_t *guid) 1.37 +{ 1.38 + GtPacket *packet; 1.39 + unsigned char *data; 1.40 + 1.41 + if (!(packet = MALLOC (sizeof (GtPacket)))) 1.42 + return NULL; 1.43 + 1.44 + if (!(data = MALLOC (GT_PACKET_INITIAL))) 1.45 + { 1.46 + free (packet); 1.47 + return NULL; 1.48 + } 1.49 + 1.50 + packet->data = data; 1.51 + packet->len = GNUTELLA_HDR_LEN; 1.52 + packet->data_len = GT_PACKET_INITIAL; 1.53 + 1.54 + /* 1.55 + * Caller could provide GUID or request it be randomly initialized. 1.56 + */ 1.57 + if (guid) 1.58 + gt_packet_set_guid (packet, guid); 1.59 + else 1.60 + gt_guid_init ((gt_guid_t *)packet->data); 1.61 + 1.62 + gt_packet_set_command (packet, cmd); 1.63 + gt_packet_set_ttl (packet, ttl); 1.64 + gt_packet_set_payload_len (packet, 0); 1.65 + gt_packet_set_hops (packet, 0); 1.66 + 1.67 + /* set the offset to start at the end of the header */ 1.68 + packet->offset = GNUTELLA_HDR_LEN; 1.69 + 1.70 + return packet; 1.71 +} 1.72 + 1.73 +GtPacket *gt_packet_reply (GtPacket *src, uint8_t cmd) 1.74 +{ 1.75 + GtPacket *packet; 1.76 + uint8_t hops; 1.77 + gt_guid_t *guid; 1.78 + 1.79 + hops = gt_packet_hops (src); 1.80 + guid = gt_packet_guid (src); 1.81 + 1.82 + if (!(packet = gt_packet_new (cmd, hops + 1, guid))) 1.83 + return NULL; 1.84 + 1.85 + return packet; 1.86 +} 1.87 + 1.88 +GtPacket *gt_packet_vendor (const gt_vendor_msg_t *vmsg) 1.89 +{ 1.90 + GtPacket *pkt; 1.91 + 1.92 + if (!(pkt = gt_packet_new (GT_MSG_VENDOR, 1, NULL))) 1.93 + return NULL; 1.94 + 1.95 + gt_packet_put_ustr (pkt, vmsg->vendor_id, 4); 1.96 + gt_packet_put_uint16 (pkt, vmsg->id); 1.97 + gt_packet_put_uint16 (pkt, 1); /* vmsg version */ 1.98 + 1.99 + if (gt_packet_error (pkt)) 1.100 + { 1.101 + gt_packet_free (pkt); 1.102 + return NULL; 1.103 + } 1.104 + 1.105 + return pkt; 1.106 +} 1.107 + 1.108 +void gt_packet_free (GtPacket *packet) 1.109 +{ 1.110 + if (!packet) 1.111 + return; 1.112 + 1.113 + free (packet->data); 1.114 + free (packet); 1.115 +} 1.116 + 1.117 +/*****************************************************************************/ 1.118 + 1.119 +gt_guid_t *gt_packet_guid (GtPacket *packet) 1.120 +{ 1.121 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.122 + 1.123 + return packet->data; 1.124 +} 1.125 + 1.126 +uint32_t gt_packet_payload_len (GtPacket *packet) 1.127 +{ 1.128 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.129 + 1.130 + return get_payload_len (packet->data); 1.131 +} 1.132 + 1.133 +uint32_t gt_packet_command (GtPacket *packet) 1.134 +{ 1.135 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.136 + 1.137 + return get_command (packet->data); 1.138 +} 1.139 + 1.140 +uint8_t gt_packet_hops (GtPacket *packet) 1.141 +{ 1.142 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.143 + 1.144 + return get_hops (packet->data); 1.145 +} 1.146 + 1.147 +uint8_t gt_packet_ttl (GtPacket *packet) 1.148 +{ 1.149 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.150 + 1.151 + return get_ttl (packet->data); 1.152 +} 1.153 + 1.154 +/*****************************************************************************/ 1.155 + 1.156 +void gt_packet_set_guid (GtPacket *packet, gt_guid_t *guid) 1.157 +{ 1.158 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.159 + 1.160 + memcpy (packet->data, guid, 16); 1.161 +} 1.162 + 1.163 +void gt_packet_set_command (GtPacket *packet, uint8_t cmd) 1.164 +{ 1.165 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.166 + 1.167 + get_command (packet->data) = cmd; 1.168 +} 1.169 + 1.170 +void gt_packet_set_ttl (GtPacket *packet, uint8_t ttl) 1.171 +{ 1.172 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.173 + 1.174 + get_ttl (packet->data) = ttl; 1.175 +} 1.176 + 1.177 +void gt_packet_set_hops (GtPacket *packet, uint8_t hops) 1.178 +{ 1.179 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.180 + 1.181 + get_hops (packet->data) = hops; 1.182 +} 1.183 + 1.184 +void gt_packet_set_payload_len (GtPacket *packet, uint32_t len) 1.185 +{ 1.186 + assert (packet->data_len >= GNUTELLA_HDR_LEN); 1.187 + 1.188 + len = htovl (len); 1.189 + 1.190 + memcpy (packet->data + 19, &len, 4); 1.191 +} 1.192 + 1.193 +/*****************************************************************************/ 1.194 +/* functions to read data from packets */ 1.195 + 1.196 +static uint8_t gt_get8 (unsigned char *src) 1.197 +{ 1.198 + return *src; 1.199 +} 1.200 + 1.201 +#define copy_bytes(src,sz,endian,swap,sizedvar_t,swap_net,swap_vax) \ 1.202 + sizedvar_t r; \ 1.203 + sizedvar_t v; \ 1.204 + sizedvar_t n; \ 1.205 + \ 1.206 + memcpy (&r, src, sz); \ 1.207 + \ 1.208 + n = swap_net (r); \ 1.209 + \ 1.210 + assert_at_compile (BIG == 0x01); \ 1.211 + if (endian & swap) \ 1.212 + r = n; \ 1.213 + \ 1.214 + v = swap_vax (r); \ 1.215 + \ 1.216 + assert_at_compile (LITTLE == 0x00); \ 1.217 + if (~endian & swap) \ 1.218 + r = v; \ 1.219 + \ 1.220 + return r; 1.221 + 1.222 +static uint16_t gt_get16 (unsigned char *src, int endian, int swap) 1.223 +{ 1.224 + copy_bytes (src, 2, endian, swap, uint16_t, ntohs, vtohs); 1.225 +} 1.226 + 1.227 +static uint32_t gt_get32 (unsigned char *src, int endian, int swap) 1.228 +{ 1.229 + copy_bytes (src, 4, endian, swap, uint32_t, ntohl, vtohl); 1.230 +} 1.231 + 1.232 +/*****************************************************************************/ 1.233 + 1.234 +static BOOL gt_packet_resize (GtPacket *packet, size_t len) 1.235 +{ 1.236 + size_t resize_len; 1.237 + unsigned char *resized; 1.238 + 1.239 + if (!packet) 1.240 + return FALSE; 1.241 + 1.242 + assert (len >= GNUTELLA_HDR_LEN); 1.243 + assert (len < GT_PACKET_MAX); 1.244 + 1.245 + /* the buffer we have allocated is already large enough */ 1.246 + if (packet->data_len >= len) 1.247 + return TRUE; 1.248 + 1.249 + /* determine an appropriate resize length */ 1.250 + for (resize_len = packet->data_len; resize_len < len; ) 1.251 + { 1.252 + if (resize_len == 0) 1.253 + resize_len = GT_PACKET_INITIAL; 1.254 + else 1.255 + resize_len *= 2; 1.256 + } 1.257 + 1.258 + if (!(resized = realloc (packet->data, resize_len))) 1.259 + { 1.260 + packet->error = TRUE; 1.261 + return FALSE; 1.262 + } 1.263 + 1.264 + memset (resized + packet->data_len, 0, resize_len - packet->data_len); 1.265 + 1.266 + /* modify the packet structure to reflect this resize */ 1.267 + packet->data_len = resize_len; 1.268 + packet->data = resized; 1.269 + 1.270 + return TRUE; 1.271 +} 1.272 + 1.273 +int gt_packet_error (GtPacket *packet) 1.274 +{ 1.275 + return packet->error; 1.276 +} 1.277 + 1.278 +int gt_packet_seek (GtPacket *packet, int offset) 1.279 +{ 1.280 + int old_offset; 1.281 + 1.282 + /* should we be setting packet->error here? */ 1.283 + if (offset >= packet->len || offset < 0) 1.284 + { 1.285 + packet->error = TRUE; 1.286 + return -1; 1.287 + } 1.288 + 1.289 + old_offset = packet->offset; 1.290 + packet->offset = offset; 1.291 + 1.292 + return old_offset; 1.293 +} 1.294 + 1.295 +GtPacket *gt_packet_unserialize (unsigned char *data, size_t len) 1.296 +{ 1.297 + GtPacket *packet; 1.298 + 1.299 + if (!(packet = gt_packet_new (0, 0, NULL))) 1.300 + return NULL; 1.301 + 1.302 + if (len >= GT_PACKET_MAX) 1.303 + { 1.304 + gt_packet_free (packet); 1.305 + return NULL; 1.306 + } 1.307 + 1.308 + if (!gt_packet_resize (packet, len)) 1.309 + { 1.310 + GIFT_ERROR (("error resizing packet")); 1.311 + gt_packet_free (packet); 1.312 + return NULL; 1.313 + } 1.314 + 1.315 + memcpy (packet->data, data, len); 1.316 + 1.317 + packet->len = len; 1.318 + 1.319 + /* Hmm, this should never happen, time to valgrind */ 1.320 + if (gt_packet_payload_len (packet) != len - GNUTELLA_HDR_LEN) 1.321 + { 1.322 + GIFT_ERROR (("corrupt packet")); 1.323 + gt_packet_free (packet); 1.324 + return NULL; 1.325 + } 1.326 + 1.327 + return packet; 1.328 +} 1.329 + 1.330 +/*****************************************************************************/ 1.331 + 1.332 +uint8_t gt_packet_get_uint8 (GtPacket *packet) 1.333 +{ return gt_packet_get_uint (packet, 1, LITTLE, FALSE); } 1.334 + 1.335 +uint16_t gt_packet_get_uint16 (GtPacket *packet) 1.336 +{ return gt_packet_get_uint (packet, 2, LITTLE, TRUE); } 1.337 + 1.338 +uint32_t gt_packet_get_uint32 (GtPacket *packet) 1.339 +{ return gt_packet_get_uint (packet, 4, LITTLE, TRUE); } 1.340 + 1.341 +in_addr_t gt_packet_get_ip (GtPacket *packet) 1.342 +{ return gt_packet_get_uint (packet, 4, BIG, FALSE); } 1.343 + 1.344 +in_port_t gt_packet_get_port (GtPacket *packet) 1.345 +{ return gt_packet_get_uint (packet, 2, LITTLE, TRUE); } 1.346 + 1.347 +/*****************************************************************************/ 1.348 + 1.349 +uint32_t gt_packet_get_uint (GtPacket *packet, size_t size, 1.350 + int endian, int swap) 1.351 +{ 1.352 + uint32_t data32 = 0; 1.353 + char *offs; 1.354 + 1.355 + assert (packet); 1.356 + 1.357 + /* check overrun */ 1.358 + if (packet->offset + size > packet->len) 1.359 + { 1.360 + packet->error = TRUE; 1.361 + return 0; 1.362 + } 1.363 + 1.364 + offs = packet->data + packet->offset; 1.365 + 1.366 + switch (size) 1.367 + { 1.368 + case 1: 1.369 + data32 = (uint32_t)gt_get8 (offs); 1.370 + break; 1.371 + case 2: 1.372 + data32 = (uint32_t)gt_get16 (offs, endian, swap); 1.373 + break; 1.374 + case 4: 1.375 + data32 = gt_get32 (offs, endian, swap); 1.376 + break; 1.377 + default: 1.378 + printf ("%s: wtf are you doing?\n", __PRETTY_FUNCTION__); 1.379 + return data32; 1.380 + } 1.381 + 1.382 + packet->offset += size; 1.383 + 1.384 + return data32; 1.385 +} 1.386 + 1.387 +/*****************************************************************************/ 1.388 + 1.389 +static int gt_packet_append (GtPacket *packet, const void *data, size_t size) 1.390 +{ 1.391 + size_t required; 1.392 + 1.393 + if (!packet || !data || size == 0) 1.394 + return FALSE; 1.395 + 1.396 + if (packet->data_len + size >= GT_PACKET_MAX) 1.397 + { 1.398 + packet->error = TRUE; 1.399 + return FALSE; 1.400 + } 1.401 + 1.402 + /* determine the total required space to append size bytes */ 1.403 + required = packet->len + size; 1.404 + 1.405 + /* if we can't resize, gracefully fail...the caller should determine 1.406 + * how bad this truly is */ 1.407 + if (!gt_packet_resize (packet, required)) 1.408 + return FALSE; 1.409 + 1.410 + /* append size bytes of data */ 1.411 + memcpy (packet->data + packet->len, data, size); 1.412 + 1.413 + /* increment the length of this packet */ 1.414 + packet->len += size; 1.415 + 1.416 + gt_packet_set_payload_len (packet, gt_packet_payload_len (packet) + size); 1.417 + return TRUE; 1.418 +} 1.419 + 1.420 +int gt_packet_put_uint (GtPacket *packet, void *data, size_t size, 1.421 + int endian, int swap) 1.422 +{ 1.423 + int ret; 1.424 + uint16_t unet16; 1.425 + uint32_t unet32; 1.426 + 1.427 + if (!data || size < 0 || size > sizeof (uint32_t)) 1.428 + return FALSE; 1.429 + 1.430 + switch (size) 1.431 + { 1.432 + case 2: 1.433 + unet16 = gt_get16 (data, endian, swap); 1.434 + ret = gt_packet_append (packet, &unet16, size); 1.435 + break; 1.436 + case 4: 1.437 + unet32 = gt_get32 (data, endian, swap); 1.438 + ret = gt_packet_append (packet, &unet32, size); 1.439 + break; 1.440 + default: 1.441 + ret = gt_packet_append (packet, data, size); 1.442 + break; 1.443 + } 1.444 + 1.445 + return ret; 1.446 +} 1.447 + 1.448 +/*****************************************************************************/ 1.449 + 1.450 +int gt_packet_put_uint8 (GtPacket *packet, uint8_t byte) 1.451 +{ return gt_packet_put_uint (packet, &byte, 1, LITTLE, FALSE); } 1.452 + 1.453 +int gt_packet_put_uint16 (GtPacket *packet, uint16_t bytes) 1.454 +{ return gt_packet_put_uint (packet, &bytes, 2, LITTLE, TRUE); } 1.455 + 1.456 +int gt_packet_put_uint32 (GtPacket *packet, uint32_t bytes) 1.457 +{ return gt_packet_put_uint (packet, &bytes, 4, LITTLE, TRUE); } 1.458 + 1.459 +int gt_packet_put_ip (GtPacket *packet, in_addr_t ip) 1.460 +{ return gt_packet_put_uint (packet, &ip, 4, BIG, FALSE); } 1.461 + 1.462 +int gt_packet_put_port (GtPacket *packet, in_port_t port) 1.463 +{ return gt_packet_put_uint (packet, &port, 2, LITTLE, TRUE); } 1.464 + 1.465 +int gt_packet_put_ustr (GtPacket *packet, const unsigned char *str, size_t len) 1.466 +{ 1.467 + assert (len > 0); 1.468 + return gt_packet_append (packet, str, len); 1.469 +} 1.470 + 1.471 +int gt_packet_put_str (GtPacket *packet, const char *str) 1.472 +{ 1.473 + size_t len; 1.474 + 1.475 + if (!str) 1.476 + return gt_packet_put_uint8 (packet, 0); 1.477 + 1.478 + len = strlen (str) + 1; 1.479 + return gt_packet_put_ustr (packet, (const unsigned char *)str, len); 1.480 +} 1.481 + 1.482 +/*****************************************************************************/ 1.483 + 1.484 +/* checks for the gt_packet_get_array sentinel given the size. the sentinel is 1.485 + * defined as a full element filled with zeroes */ 1.486 +static int array_sentinel (char *ptr, size_t size) 1.487 +{ 1.488 + while (size--) 1.489 + { 1.490 + /* non-zero byte, this element couldnt be the sentinel */ 1.491 + if (*ptr != 0) 1.492 + return FALSE; 1.493 + 1.494 + ptr++; 1.495 + } 1.496 + 1.497 + return TRUE; 1.498 +} 1.499 + 1.500 +void *gt_packet_get_array (GtPacket *packet, size_t nmemb, size_t size, 1.501 + int term, int endian, int swap) 1.502 +{ 1.503 + char *start; 1.504 + char *ptr; 1.505 + char *end; 1.506 + int n; 1.507 + 1.508 + assert (packet); 1.509 + 1.510 + /* we tried to read past the end of the packet */ 1.511 + if (packet->offset >= packet->len) 1.512 + { 1.513 + packet->error = TRUE; 1.514 + return NULL; 1.515 + } 1.516 + 1.517 + start = packet->data + packet->offset; 1.518 + end = packet->data + packet->len; 1.519 + 1.520 + /* TODO - optimize compares inside this loop */ 1.521 + n = 0; 1.522 + for (ptr = start; ptr + size < end; ptr += size, n++) 1.523 + { 1.524 + if (term && array_sentinel (ptr, size)) 1.525 + break; 1.526 + 1.527 + if (nmemb > 0 && n >= nmemb) 1.528 + break; 1.529 + 1.530 + if (swap) 1.531 + { 1.532 + switch (size) 1.533 + { 1.534 + case 2: 1.535 + net_put16 (ptr, gt_get16 (ptr, endian, swap)); 1.536 + break; 1.537 + case 4: 1.538 + net_put32 (ptr, gt_get32 (ptr, endian, swap)); 1.539 + break; 1.540 + default: 1.541 + assert (0); 1.542 + break; 1.543 + } 1.544 + } 1.545 + } 1.546 + 1.547 + /* If the array was not null terminated, then terminate it now */ 1.548 + if (term && !array_sentinel (ptr, size)) 1.549 + { 1.550 + uint32_t zero = 0; 1.551 + size_t len; 1.552 + 1.553 + /* this is the length of the array we read */ 1.554 + len = (ptr - start + size); 1.555 + 1.556 + /* we must have hit the end of the packet */ 1.557 + assert (packet->offset + len == packet->len); 1.558 + 1.559 + if (!gt_packet_resize (packet, packet->len + size)) 1.560 + { 1.561 + packet->offset = packet->len; 1.562 + return NULL; 1.563 + } 1.564 + 1.565 + /* Hrm, this changes the payload, which we really dont want to do. */ 1.566 + if (!gt_packet_append (packet, &zero, size)) 1.567 + { 1.568 + packet->offset = packet->len; 1.569 + return NULL; 1.570 + } 1.571 + } 1.572 + 1.573 + /* invalid data...no sentinel found */ 1.574 + if (ptr + size > end) 1.575 + { 1.576 + packet->offset = packet->len; 1.577 + return NULL; 1.578 + } 1.579 + 1.580 + /* ptr is at the sentinel right now, move one element out to calculate the 1.581 + * next packet start */ 1.582 + if (term) 1.583 + ptr += size; 1.584 + 1.585 + /* this includes the sentinel now */ 1.586 + packet->offset += (ptr - start); 1.587 + 1.588 + return start; 1.589 +} 1.590 + 1.591 +char *gt_packet_get_str (GtPacket *packet) 1.592 +{ 1.593 + return gt_packet_get_array (packet, 0, 1, TRUE, FALSE, FALSE); 1.594 +} 1.595 + 1.596 +unsigned char *gt_packet_get_ustr (GtPacket *packet, size_t len) 1.597 +{ 1.598 + return gt_packet_get_array (packet, len, 1, FALSE, FALSE, FALSE); 1.599 +} 1.600 + 1.601 +/******************************************************************************/ 1.602 + 1.603 +static char *packet_command_str (unsigned char cmd) 1.604 +{ 1.605 + static char buf[16]; 1.606 + 1.607 + switch (cmd) 1.608 + { 1.609 + case GT_MSG_PING: return "PING"; 1.610 + case GT_MSG_PING_REPLY: return "PONG"; 1.611 + case GT_MSG_BYE: return "BYE"; 1.612 + case GT_MSG_QUERY_ROUTE: return "QROUTE"; 1.613 + case GT_MSG_VENDOR: return "VMSG"; 1.614 + case GT_MSG_VENDOR_STD: return "VMSG-S"; 1.615 + case GT_MSG_PUSH: return "PUSH"; 1.616 + case GT_MSG_QUERY: return "QUERY"; 1.617 + case GT_MSG_QUERY_REPLY: return "HITS"; 1.618 + 1.619 + default: 1.620 + snprintf (buf, sizeof (buf), "[<%02hx>]", cmd); 1.621 + return buf; 1.622 + } 1.623 +} 1.624 + 1.625 +static void packet_log (char *data, int len, int sent, char *user_agent, 1.626 + in_addr_t ip) 1.627 +{ 1.628 + uint8_t cmd; 1.629 + char user_buf[32]; 1.630 + char *file; 1.631 + static FILE *ascii_log; 1.632 + 1.633 + if (!ascii_log) 1.634 + { 1.635 + file = PACKET_ASCII_LOG; 1.636 + 1.637 + if (!(ascii_log = fopen (file, "w"))) 1.638 + return; 1.639 + } 1.640 + 1.641 + cmd = get_command (data); 1.642 + 1.643 + user_buf[0] = 0; 1.644 + 1.645 + /* copy the first few chars of user_agent to make it line up */ 1.646 + if (user_agent) 1.647 + { 1.648 + strncpy (user_buf, user_agent, 21); 1.649 + user_buf[21] = 0; 1.650 + } 1.651 + 1.652 + fprintf (ascii_log, "%2s %-6s sz: %-5hu peer: %-22s [%s]\n", 1.653 + (sent ? "<=" : "=>"), 1.654 + packet_command_str (cmd), len, 1.655 + (user_buf[0] ? user_buf : "(None)"), 1.656 + (ip == 0 ? "None" : net_ip_str (ip))); 1.657 + 1.658 + fprint_hex (ascii_log, data, len); 1.659 +} 1.660 + 1.661 +void gt_packet_log (GtPacket *packet, TCPC *src, int sent) 1.662 +{ 1.663 + char *user_agent; 1.664 + in_addr_t ip; 1.665 + 1.666 + if (!PACKET_DEBUG) 1.667 + return; 1.668 + 1.669 + user_agent = NULL; 1.670 + ip = 0; 1.671 + 1.672 + /* append the user-agent string to the packet log */ 1.673 + if (src) 1.674 + { 1.675 + ip = src->host; 1.676 + user_agent = dataset_lookupstr (GT_NODE(src)->hdr, "user-agent"); 1.677 + } 1.678 + 1.679 + packet_log (packet->data, packet->len, sent, user_agent, ip); 1.680 +} 1.681 + 1.682 +/******************************************************************************/ 1.683 + 1.684 +int gt_packet_send (TCPC *c, GtPacket *packet) 1.685 +{ 1.686 + if (!c || c->fd < 0) 1.687 + return -1; 1.688 + 1.689 + if (!gt_node_send (GT_NODE(c), packet)) 1.690 + return -1; 1.691 + 1.692 + return 0; 1.693 +} 1.694 + 1.695 +/******************************************************************************/ 1.696 + 1.697 +static int send_packetva (TCPC *c, uint8_t cmd, 1.698 + gt_guid_t *guid, uint8_t ttl, 1.699 + uint8_t hops, char *fmt, va_list args) 1.700 +{ 1.701 + GtPacket *pkt; 1.702 + char *p; 1.703 + int short_fmt = FALSE; 1.704 + int field_width = 0; 1.705 + int ret; 1.706 + 1.707 + if (!(pkt = gt_packet_new (cmd, ttl, guid))) 1.708 + return -1; 1.709 + 1.710 + for (p = fmt; *p; p++) 1.711 + { 1.712 + switch (*p) 1.713 + { 1.714 + case '%': 1.715 + short_fmt = FALSE; 1.716 + break; 1.717 + case 'h': 1.718 + short_fmt = TRUE; 1.719 + break; 1.720 + case 'l': 1.721 + break; 1.722 + case 'c': 1.723 + { 1.724 + uint8_t bits8 = (uint8_t) va_arg (args, int); 1.725 + gt_packet_put_uint8 (pkt, bits8); 1.726 + } 1.727 + break; 1.728 + case 'u': 1.729 + if (short_fmt) 1.730 + { 1.731 + uint16_t bits16 = (uint16_t) va_arg (args, int); 1.732 + gt_packet_put_uint16 (pkt, bits16); 1.733 + } 1.734 + else 1.735 + { 1.736 + uint32_t bits32 = (uint32_t) va_arg (args, int); 1.737 + gt_packet_put_uint32 (pkt, bits32); 1.738 + } 1.739 + break; 1.740 + case 's': 1.741 + { 1.742 + char *str = va_arg (args, char *); 1.743 + gt_packet_put_str (pkt, str); 1.744 + } 1.745 + break; 1.746 + case '0': case '1': case '2': case '3': case '4': case '5': 1.747 + case '6': case '7': case '8': case '9': 1.748 + field_width = field_width * 10 + (*p - '0'); 1.749 + break; 1.750 + case '*': 1.751 + field_width = va_arg (args, int); 1.752 + break; 1.753 + case 'p': 1.754 + { 1.755 + unsigned char *ustr = va_arg (args, unsigned char *); 1.756 + 1.757 + gt_packet_put_ustr (pkt, ustr, field_width); 1.758 + field_width = 0; 1.759 + } 1.760 + break; 1.761 + default: 1.762 + abort (); 1.763 + break; 1.764 + } 1.765 + } 1.766 + 1.767 + if (gt_packet_error (pkt)) 1.768 + { 1.769 + gt_packet_free (pkt); 1.770 + return -1; 1.771 + } 1.772 + 1.773 + ret = gt_packet_send (c, pkt); 1.774 + gt_packet_free (pkt); 1.775 + 1.776 + return ret; 1.777 +} 1.778 + 1.779 +int gt_packet_send_fmt (TCPC *c, uint8_t cmd, 1.780 + gt_guid_t *guid, uint8_t ttl, 1.781 + uint8_t hops, char *fmt, ...) 1.782 +{ 1.783 + va_list args; 1.784 + int ret; 1.785 + 1.786 + va_start (args, fmt); 1.787 + ret = send_packetva (c, cmd, guid, ttl, hops, fmt, args); 1.788 + va_end (args); 1.789 + 1.790 + return ret; 1.791 +} 1.792 + 1.793 +int gt_packet_reply_fmt (TCPC *c, GtPacket *packet, 1.794 + uint8_t cmd, char *fmt, ...) 1.795 +{ 1.796 + va_list args; 1.797 + int ret; 1.798 + size_t hops; 1.799 + gt_guid_t *guid; 1.800 + 1.801 + guid = gt_packet_guid (packet); 1.802 + hops = gt_packet_hops (packet); 1.803 + 1.804 + va_start (args, fmt); 1.805 + ret = send_packetva (c, cmd, guid, hops + 1, 0, fmt, args); 1.806 + va_end (args); 1.807 + 1.808 + return ret; 1.809 +} 1.810 + 1.811 +/******************************************************************************/ 1.812 + 1.813 +int gt_packet_forward (GtPacket *packet, TCPC *c) 1.814 +{ 1.815 + return -1; 1.816 +}