annotate 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
rev   line source
paulo@0 1 /*
paulo@0 2 * $Id: ping_reply.c,v 1.7 2005/01/04 15:00:52 mkern Exp $
paulo@0 3 *
paulo@0 4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
paulo@0 5 *
paulo@0 6 * This program is free software; you can redistribute it and/or modify it
paulo@0 7 * under the terms of the GNU General Public License as published by the
paulo@0 8 * Free Software Foundation; either version 2, or (at your option) any
paulo@0 9 * later version.
paulo@0 10 *
paulo@0 11 * This program is distributed in the hope that it will be useful, but
paulo@0 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
paulo@0 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
paulo@0 14 * General Public License for more details.
paulo@0 15 */
paulo@0 16
paulo@0 17 #include "gt_gnutella.h"
paulo@0 18 #include "message/msg_handler.h"
paulo@0 19
paulo@0 20 #include "gt_node_cache.h"
paulo@0 21 #include "gt_connect.h"
paulo@0 22 #include "gt_bind.h"
paulo@0 23
paulo@0 24 #include "gt_search.h"
paulo@0 25 #include "gt_share_state.h"
paulo@0 26 #include "gt_query_route.h"
paulo@0 27 #include "gt_stats.h"
paulo@0 28
paulo@0 29 /*****************************************************************************/
paulo@0 30
paulo@0 31 extern BOOL gt_is_pow2 (uint32_t num); /* ping.c */
paulo@0 32
paulo@0 33 /*****************************************************************************/
paulo@0 34
paulo@0 35 /*
paulo@0 36 * Update the port on the first pong or when the pong contains a different
paulo@0 37 * pong.
paulo@0 38 */
paulo@0 39 static void update_port (GtNode *node, in_port_t new_port)
paulo@0 40 {
paulo@0 41 /* update the port */
paulo@0 42 node->gt_port = new_port;
paulo@0 43
paulo@0 44 /*
paulo@0 45 * Test if the node is connectable. This will play with the node's
paulo@0 46 * ->verified and ->firewalled bits.
paulo@0 47 *
paulo@0 48 * This is only important if this node is running as an ultrapeer, because
paulo@0 49 * it lets us know whether we should route queries from firewalled peers
paulo@0 50 * to the remote node.
paulo@0 51 */
paulo@0 52 if (GT_SELF->klass & GT_NODE_ULTRA)
paulo@0 53 gt_connect_test (node, node->gt_port);
paulo@0 54 }
paulo@0 55
paulo@0 56 /*
paulo@0 57 * Transition the node into state 'connected', and do various things. This
paulo@0 58 * has become a bit crufty and miscellaneous. TODO: change this to a callback
paulo@0 59 * registration system in gt_node.c, register the callbacks in gt_gnutella.c
paulo@0 60 */
paulo@0 61 static BOOL complete_connection (GtNode *node)
paulo@0 62 {
paulo@0 63 /* mark this node as now connected */
paulo@0 64 gt_node_state_set (node, GT_NODE_CONNECTED);
paulo@0 65
paulo@0 66 /* submit the routing table */
paulo@0 67 if ((node->klass & GT_NODE_ULTRA) &&
paulo@0 68 !(GT_SELF->klass & GT_NODE_ULTRA))
paulo@0 69 {
paulo@0 70 query_route_table_submit (GT_CONN(node));
paulo@0 71 }
paulo@0 72
paulo@0 73 /* submit unfinished searches soon */
paulo@0 74 gt_searches_submit (GT_CONN(node), 30 * SECONDS);
paulo@0 75
paulo@0 76 /* let the bind subsystem send a ConnectBack for tracking firewalled
paulo@0 77 * status */
paulo@0 78 gt_bind_completed_connection (node);
paulo@0 79
paulo@0 80 if (!(node->share_state = gt_share_state_new ()))
paulo@0 81 return FALSE;
paulo@0 82
paulo@0 83 gt_share_state_update (node);
paulo@0 84
paulo@0 85 return TRUE;
paulo@0 86 }
paulo@0 87
paulo@0 88 GT_MSG_HANDLER(gt_msg_ping_reply)
paulo@0 89 {
paulo@0 90 in_port_t port;
paulo@0 91 in_addr_t ip;
paulo@0 92 uint32_t files;
paulo@0 93 uint32_t size_kb;
paulo@0 94 gt_node_class_t klass;
paulo@0 95
paulo@0 96 port = gt_packet_get_port (packet);
paulo@0 97 ip = gt_packet_get_ip (packet);
paulo@0 98 files = gt_packet_get_uint32 (packet);
paulo@0 99 size_kb = gt_packet_get_uint32 (packet);
paulo@0 100
paulo@0 101 /* this will keep the node from being disconnected by idle-check loop */
paulo@0 102 if (node->pings_with_noreply > 0)
paulo@0 103 node->pings_with_noreply = 0;
paulo@0 104
paulo@0 105 /* update stats and port */
paulo@0 106 if (gt_packet_ttl (packet) == 1 && gt_packet_hops (packet) == 0)
paulo@0 107 {
paulo@0 108 /* check if this is the first ping response on this connection */
paulo@0 109 if (node->state == GT_NODE_CONNECTING_2)
paulo@0 110 {
paulo@0 111 if (!complete_connection (node))
paulo@0 112 {
paulo@0 113 gt_node_disconnect (c);
paulo@0 114 return;
paulo@0 115 }
paulo@0 116 }
paulo@0 117
paulo@0 118 if (ip == node->ip)
paulo@0 119 {
paulo@0 120 if (node->gt_port != port || !node->verified)
paulo@0 121 update_port (node, port);
paulo@0 122
paulo@0 123 /* update stats information */
paulo@0 124 node->size_kb = size_kb;
paulo@0 125 node->files = files;
paulo@0 126
paulo@0 127 /* don't add this node to the cache */
paulo@0 128 return;
paulo@0 129 }
paulo@0 130
paulo@0 131 /*
paulo@0 132 * Morpheus nodes send pongs for other nodes with Hops=1. If
paulo@0 133 * the IP doesn't equal the observed IP, then add the node to the
paulo@0 134 * node cache. This may create problems with trying to connect twice
paulo@0 135 * to some users, though.
paulo@0 136 */
paulo@0 137 }
paulo@0 138
paulo@0 139 /* add this node to the cache */
paulo@0 140 klass = GT_NODE_LEAF;
paulo@0 141
paulo@0 142 /* LimeWire marks ultrapeer pongs by making files size a power of two */
paulo@0 143 if (size_kb >= 8 && gt_is_pow2 (size_kb))
paulo@0 144 klass = GT_NODE_ULTRA;
paulo@0 145
paulo@0 146 /* don't register this node if its local and the peer isnt */
paulo@0 147 if (gt_is_local_ip (ip, node->ip))
paulo@0 148 return;
paulo@0 149
paulo@0 150 /* keep track of stats from pongs */
paulo@0 151 gt_stats_accumulate (ip, port, node->ip, files, size_kb);
paulo@0 152
paulo@0 153 /* TODO: check uptime GGEP extension and add it here */
paulo@0 154 gt_node_cache_add_ipv4 (ip, port, klass, time (NULL), 0, node->ip);
paulo@0 155 gt_node_cache_trace ();
paulo@0 156 }