diff src/message/ping_reply.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_reply.c	Sat Feb 20 21:18:28 2010 -0800
     1.3 @@ -0,0 +1,156 @@
     1.4 +/*
     1.5 + * $Id: ping_reply.c,v 1.7 2005/01/04 15:00:52 mkern 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_cache.h"
    1.24 +#include "gt_connect.h"
    1.25 +#include "gt_bind.h"
    1.26 +
    1.27 +#include "gt_search.h"
    1.28 +#include "gt_share_state.h"
    1.29 +#include "gt_query_route.h"
    1.30 +#include "gt_stats.h"
    1.31 +
    1.32 +/*****************************************************************************/
    1.33 +
    1.34 +extern BOOL gt_is_pow2 (uint32_t num);   /* ping.c */
    1.35 +
    1.36 +/*****************************************************************************/
    1.37 +
    1.38 +/*
    1.39 + * Update the port on the first pong or when the pong contains a different
    1.40 + * pong.
    1.41 + */
    1.42 +static void update_port (GtNode *node, in_port_t new_port)
    1.43 +{
    1.44 +	/* update the port */
    1.45 +	node->gt_port = new_port;
    1.46 +
    1.47 +	/*
    1.48 +	 * Test if the node is connectable.  This will play with the node's
    1.49 +	 * ->verified and ->firewalled bits.
    1.50 +	 *
    1.51 +	 * This is only important if this node is running as an ultrapeer, because
    1.52 +	 * it lets us know whether we should route queries from firewalled peers
    1.53 +	 * to the remote node.
    1.54 +	 */
    1.55 +	if (GT_SELF->klass & GT_NODE_ULTRA)
    1.56 +		gt_connect_test (node, node->gt_port);
    1.57 +}
    1.58 +
    1.59 +/*
    1.60 + * Transition the node into state 'connected', and do various things.  This
    1.61 + * has become a bit crufty and miscellaneous.  TODO: change this to a callback
    1.62 + * registration system in gt_node.c, register the callbacks in gt_gnutella.c
    1.63 + */
    1.64 +static BOOL complete_connection (GtNode *node)
    1.65 +{
    1.66 +	/* mark this node as now connected */
    1.67 +	gt_node_state_set (node, GT_NODE_CONNECTED);
    1.68 +
    1.69 +	/* submit the routing table */
    1.70 +	if ((node->klass & GT_NODE_ULTRA) &&
    1.71 +	    !(GT_SELF->klass & GT_NODE_ULTRA))
    1.72 +	{
    1.73 +		query_route_table_submit (GT_CONN(node));
    1.74 +	}
    1.75 +
    1.76 +	/* submit unfinished searches soon */
    1.77 +	gt_searches_submit (GT_CONN(node), 30 * SECONDS);
    1.78 +
    1.79 +	/* let the bind subsystem send a ConnectBack for tracking firewalled
    1.80 +	 * status */
    1.81 +	gt_bind_completed_connection (node);
    1.82 +
    1.83 +	if (!(node->share_state = gt_share_state_new ()))
    1.84 +		return FALSE;
    1.85 +
    1.86 +	gt_share_state_update (node);
    1.87 +
    1.88 +	return TRUE;
    1.89 +}
    1.90 +
    1.91 +GT_MSG_HANDLER(gt_msg_ping_reply)
    1.92 +{
    1.93 +	in_port_t       port;
    1.94 +	in_addr_t       ip;
    1.95 +	uint32_t        files;
    1.96 +	uint32_t        size_kb;
    1.97 +	gt_node_class_t klass;
    1.98 +
    1.99 +	port    = gt_packet_get_port   (packet);
   1.100 +	ip      = gt_packet_get_ip     (packet);
   1.101 +	files   = gt_packet_get_uint32 (packet);
   1.102 +	size_kb = gt_packet_get_uint32 (packet);
   1.103 +
   1.104 +	/* this will keep the node from being disconnected by idle-check loop */
   1.105 +	if (node->pings_with_noreply > 0)
   1.106 +		node->pings_with_noreply = 0;
   1.107 +
   1.108 +	/* update stats and port */
   1.109 +	if (gt_packet_ttl (packet) == 1 && gt_packet_hops (packet) == 0)
   1.110 +	{
   1.111 +		/* check if this is the first ping response on this connection */
   1.112 +		if (node->state == GT_NODE_CONNECTING_2)
   1.113 +		{
   1.114 +			if (!complete_connection (node))
   1.115 +			{
   1.116 +				gt_node_disconnect (c);
   1.117 +				return;
   1.118 +			}
   1.119 +		}
   1.120 +
   1.121 +		if (ip == node->ip)
   1.122 +		{
   1.123 +			if (node->gt_port != port || !node->verified)
   1.124 +				update_port (node, port);
   1.125 +
   1.126 +			/* update stats information */
   1.127 +			node->size_kb = size_kb;
   1.128 +			node->files   = files;
   1.129 +
   1.130 +			/* don't add this node to the cache */
   1.131 +			return;
   1.132 +		}
   1.133 +
   1.134 +		/*
   1.135 +		 * Morpheus nodes send pongs for other nodes with Hops=1.  If
   1.136 +		 * the IP doesn't equal the observed IP, then add the node to the
   1.137 +		 * node cache.  This may create problems with trying to connect twice
   1.138 +		 * to some users, though.
   1.139 +		 */
   1.140 +	}
   1.141 +
   1.142 +	/* add this node to the cache */
   1.143 +	klass = GT_NODE_LEAF;
   1.144 +
   1.145 +	/* LimeWire marks ultrapeer pongs by making files size a power of two */
   1.146 +	if (size_kb >= 8 && gt_is_pow2 (size_kb))
   1.147 +		klass = GT_NODE_ULTRA;
   1.148 +
   1.149 +	/* don't register this node if its local and the peer isnt */
   1.150 +	if (gt_is_local_ip (ip, node->ip))
   1.151 +		return;
   1.152 +
   1.153 +	/* keep track of stats from pongs */
   1.154 +	gt_stats_accumulate (ip, port, node->ip, files, size_kb);
   1.155 +
   1.156 +	/* TODO: check uptime GGEP extension and add it here */
   1.157 +	gt_node_cache_add_ipv4 (ip, port, klass, time (NULL), 0, node->ip);
   1.158 +	gt_node_cache_trace ();
   1.159 +}