diff src/message/ping.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/message/ping.c	Sat Feb 20 21:18:28 2010 -0800
     1.3 @@ -0,0 +1,196 @@
     1.4 +/*
     1.5 + * $Id: ping.c,v 1.4 2004/03/05 17:49:40 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 +#include "message/msg_handler.h"
    1.22 +
    1.23 +#include "gt_node_list.h"
    1.24 +#include "gt_bind.h"
    1.25 +#include "gt_netorg.h"
    1.26 +
    1.27 +#include "gt_stats.h"
    1.28 +#include "gt_share.h"
    1.29 +
    1.30 +/******************************************************************************/
    1.31 +
    1.32 +BOOL gt_is_pow2 (uint32_t num)
    1.33 +{
    1.34 +	return BOOL_EXPR (num > 0 && (num & (num-1)) == 0);
    1.35 +}
    1.36 +
    1.37 +static uint32_t get_shared_size (unsigned long size_mb)
    1.38 +{
    1.39 +	uint32_t size_kb;
    1.40 +
    1.41 +	size_kb = size_mb * 1024;
    1.42 +
    1.43 +	if (GT_SELF->klass & GT_NODE_ULTRA)
    1.44 +		/* TODO: round up to nearest power of two >= 8 here */;
    1.45 +	else if (gt_is_pow2 (size_kb))
    1.46 +		size_kb += 5; /* unmakes all powers of two, including 1 */
    1.47 +
    1.48 +	return size_kb;
    1.49 +}
    1.50 +
    1.51 +/* reply to a ping packet */
    1.52 +static void ping_reply_self (GtPacket *packet, TCPC *c)
    1.53 +{
    1.54 +	unsigned long  files, size_kb;
    1.55 +	double         size_mb;
    1.56 +	GtPacket      *reply;
    1.57 +
    1.58 +	share_index (&files, &size_mb);
    1.59 +	size_kb = get_shared_size (size_mb);
    1.60 +
    1.61 +	if (!(reply = gt_packet_reply (packet, GT_MSG_PING_REPLY)))
    1.62 +		return;
    1.63 +
    1.64 +	gt_packet_put_port   (reply, GT_SELF->gt_port);
    1.65 +	gt_packet_put_ip     (reply, GT_NODE(c)->my_ip);
    1.66 +	gt_packet_put_uint32 (reply, (uint32_t)files);
    1.67 +	gt_packet_put_uint32 (reply, (uint32_t)size_kb);
    1.68 +
    1.69 +	if (gt_packet_error (reply))
    1.70 +	{
    1.71 +		gt_packet_free (reply);
    1.72 +		return;
    1.73 +	}
    1.74 +
    1.75 +	gt_packet_send (c, reply);
    1.76 +	gt_packet_free (reply);
    1.77 +}
    1.78 +
    1.79 +/* send info about node dst to node c */
    1.80 +static TCPC *send_status (TCPC *c, GtNode *node, void **data)
    1.81 +{
    1.82 +	GtPacket   *pkt = (GtPacket *)   data[0];
    1.83 +	TCPC       *dst = (TCPC *)       data[1];
    1.84 +	GtPacket   *reply;
    1.85 +
    1.86 +	/* don't send a ping for the node itself */
    1.87 +	if (c == dst)
    1.88 +		return NULL;
    1.89 +
    1.90 +	if (!(reply = gt_packet_reply (pkt, GT_MSG_PING_REPLY)))
    1.91 +		return NULL;
    1.92 +
    1.93 +	gt_packet_put_port   (reply, node->gt_port);
    1.94 +	gt_packet_put_ip     (reply, node->ip);
    1.95 +	gt_packet_put_uint32 (reply, node->files);
    1.96 +	gt_packet_put_uint32 (reply, node->size_kb);
    1.97 +
    1.98 +	/* set the number of hops travelled to 1 */
    1.99 +	gt_packet_set_hops (reply, 1);
   1.100 +
   1.101 +	if (gt_packet_error (reply))
   1.102 +	{
   1.103 +		gt_packet_free (reply);
   1.104 +		return NULL;
   1.105 +	}
   1.106 +
   1.107 +	gt_packet_send (dst, reply);
   1.108 +	gt_packet_free (reply);
   1.109 +
   1.110 +	return NULL;
   1.111 +}
   1.112 +
   1.113 +static void handle_crawler_ping (GtPacket *packet, TCPC *c)
   1.114 +{
   1.115 +	void *data[2];
   1.116 +
   1.117 +	data[0] = packet;
   1.118 +	data[1] = c;
   1.119 +
   1.120 +	/* reply ourselves */
   1.121 +	ping_reply_self (packet, c);
   1.122 +
   1.123 +	/* send pings from connected hosts */
   1.124 +	gt_conn_foreach (GT_CONN_FOREACH(send_status), data,
   1.125 +	                 GT_NODE_NONE, GT_NODE_CONNECTED, 0);
   1.126 +}
   1.127 +
   1.128 +static BOOL need_connections (void)
   1.129 +{
   1.130 +	BOOL am_ultrapeer;
   1.131 +
   1.132 +	am_ultrapeer = GT_SELF->klass & GT_NODE_ULTRA;
   1.133 +
   1.134 +	/* send a pong if we need connections, but do this
   1.135 +	 * only if this is a search node: leaves shouldnt send pongs */
   1.136 +	if (gt_conn_need_connections (GT_NODE_ULTRA) > 0 && am_ultrapeer)
   1.137 +		return TRUE;
   1.138 +
   1.139 +	/* pretend we need connections temporarily even if we don't in order to
   1.140 +	 * figure out whether we are firewalled or not */
   1.141 +	if (gt_uptime () < 10 * EMINUTES && GT_SELF->firewalled)
   1.142 +		return TRUE;
   1.143 +
   1.144 +	return FALSE;
   1.145 +}
   1.146 +
   1.147 +GT_MSG_HANDLER(gt_msg_ping)
   1.148 +{
   1.149 +	time_t   last_ping_time, now;
   1.150 +	uint8_t  ttl, hops;
   1.151 +
   1.152 +	now = time (NULL);
   1.153 +
   1.154 +	ttl  = gt_packet_ttl (packet);
   1.155 +	hops = gt_packet_hops (packet);
   1.156 +
   1.157 +	last_ping_time = GT_NODE(c)->last_ping_time;
   1.158 +	GT_NODE(c)->last_ping_time = now;
   1.159 +
   1.160 +	if ((ttl == 1 && (hops == 0 || hops == 1))    /* tests if host is up */
   1.161 +	 || GT_NODE(c)->state == GT_NODE_CONNECTING_2 /* need to reply */
   1.162 +	 || need_connections ())                      /* we need connections */
   1.163 +	{
   1.164 +		ping_reply_self (packet, c);
   1.165 +
   1.166 +		if (ttl == 1)
   1.167 +			return;
   1.168 +	}
   1.169 +	else if (ttl == 2 && hops == 0)
   1.170 +	{
   1.171 +		/* crawler ping: respond with all connected nodes */
   1.172 +		handle_crawler_ping (packet, c);
   1.173 +		return;
   1.174 +	}
   1.175 +
   1.176 +	/* dont re-broadcast pings from search nodes if we are not one */
   1.177 +	if ((GT_NODE(c)->klass & GT_NODE_ULTRA) && !(GT_SELF->klass & GT_NODE_ULTRA))
   1.178 +	   return;
   1.179 +
   1.180 +#if 0
   1.181 +	/* notify this host when the pong cache gets full */
   1.182 +	pong_cache_waiter_add (c, packet);
   1.183 +#endif
   1.184 +
   1.185 +	/* dont accept pings too often */
   1.186 +	if (now - last_ping_time < 30 * ESECONDS)
   1.187 +		return;
   1.188 +
   1.189 +#if 0
   1.190 +	if (!pong_cache_reply (c, packet))
   1.191 +	{
   1.192 +		/* refill the pong cache */
   1.193 +		pong_cache_refill ();
   1.194 +		return;
   1.195 +	}
   1.196 +
   1.197 +	pong_cache_waiter_remove (c);
   1.198 +#endif
   1.199 +}