2
* $Id: ping.c,v 1.4 2004/03/05 17:49:40 hipnod Exp $
4
* Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
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
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.
17
#include "gt_gnutella.h"
18
#include "message/msg_handler.h"
20
#include "gt_node_list.h"
22
#include "gt_netorg.h"
27
/******************************************************************************/
29
BOOL gt_is_pow2 (uint32_t num)
31
return BOOL_EXPR (num > 0 && (num & (num-1)) == 0);
34
static uint32_t get_shared_size (unsigned long size_mb)
38
size_kb = size_mb * 1024;
40
if (GT_SELF->klass & GT_NODE_ULTRA)
41
/* TODO: round up to nearest power of two >= 8 here */;
42
else if (gt_is_pow2 (size_kb))
43
size_kb += 5; /* unmakes all powers of two, including 1 */
48
/* reply to a ping packet */
49
static void ping_reply_self (GtPacket *packet, TCPC *c)
51
unsigned long files, size_kb;
55
share_index (&files, &size_mb);
56
size_kb = get_shared_size (size_mb);
58
if (!(reply = gt_packet_reply (packet, GT_MSG_PING_REPLY)))
61
gt_packet_put_port (reply, GT_SELF->gt_port);
62
gt_packet_put_ip (reply, GT_NODE(c)->my_ip);
63
gt_packet_put_uint32 (reply, (uint32_t)files);
64
gt_packet_put_uint32 (reply, (uint32_t)size_kb);
66
if (gt_packet_error (reply))
68
gt_packet_free (reply);
72
gt_packet_send (c, reply);
73
gt_packet_free (reply);
76
/* send info about node dst to node c */
77
static TCPC *send_status (TCPC *c, GtNode *node, void **data)
79
GtPacket *pkt = (GtPacket *) data[0];
80
TCPC *dst = (TCPC *) data[1];
83
/* don't send a ping for the node itself */
87
if (!(reply = gt_packet_reply (pkt, GT_MSG_PING_REPLY)))
90
gt_packet_put_port (reply, node->gt_port);
91
gt_packet_put_ip (reply, node->ip);
92
gt_packet_put_uint32 (reply, node->files);
93
gt_packet_put_uint32 (reply, node->size_kb);
95
/* set the number of hops travelled to 1 */
96
gt_packet_set_hops (reply, 1);
98
if (gt_packet_error (reply))
100
gt_packet_free (reply);
104
gt_packet_send (dst, reply);
105
gt_packet_free (reply);
110
static void handle_crawler_ping (GtPacket *packet, TCPC *c)
117
/* reply ourselves */
118
ping_reply_self (packet, c);
120
/* send pings from connected hosts */
121
gt_conn_foreach (GT_CONN_FOREACH(send_status), data,
122
GT_NODE_NONE, GT_NODE_CONNECTED, 0);
125
static BOOL need_connections (void)
129
am_ultrapeer = GT_SELF->klass & GT_NODE_ULTRA;
131
/* send a pong if we need connections, but do this
132
* only if this is a search node: leaves shouldnt send pongs */
133
if (gt_conn_need_connections (GT_NODE_ULTRA) > 0 && am_ultrapeer)
136
/* pretend we need connections temporarily even if we don't in order to
137
* figure out whether we are firewalled or not */
138
if (gt_uptime () < 10 * EMINUTES && GT_SELF->firewalled)
144
GT_MSG_HANDLER(gt_msg_ping)
146
time_t last_ping_time, now;
151
ttl = gt_packet_ttl (packet);
152
hops = gt_packet_hops (packet);
154
last_ping_time = GT_NODE(c)->last_ping_time;
155
GT_NODE(c)->last_ping_time = now;
157
if ((ttl == 1 && (hops == 0 || hops == 1)) /* tests if host is up */
158
|| GT_NODE(c)->state == GT_NODE_CONNECTING_2 /* need to reply */
159
|| need_connections ()) /* we need connections */
161
ping_reply_self (packet, c);
166
else if (ttl == 2 && hops == 0)
168
/* crawler ping: respond with all connected nodes */
169
handle_crawler_ping (packet, c);
173
/* dont re-broadcast pings from search nodes if we are not one */
174
if ((GT_NODE(c)->klass & GT_NODE_ULTRA) && !(GT_SELF->klass & GT_NODE_ULTRA))
178
/* notify this host when the pong cache gets full */
179
pong_cache_waiter_add (c, packet);
182
/* dont accept pings too often */
183
if (now - last_ping_time < 30 * ESECONDS)
187
if (!pong_cache_reply (c, packet))
189
/* refill the pong cache */
190
pong_cache_refill ();
194
pong_cache_waiter_remove (c);