Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff src/message/gt_message.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/gt_message.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,251 @@ 1.4 +/* 1.5 + * $Id: gt_message.c,v 1.6 2004/01/07 07:24:43 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 "msg_handler.h" 1.22 + 1.23 +#include "gt_netorg.h" 1.24 +#include "gt_connect.h" 1.25 + 1.26 +#include "gt_utils.h" 1.27 + 1.28 +#include "io/rx_stack.h" /* gt_rx_stack_new */ 1.29 +#include "io/tx_stack.h" /* gt_tx_stack_new */ 1.30 + 1.31 +#include "gt_message.h" 1.32 + 1.33 +/*****************************************************************************/ 1.34 + 1.35 +extern void gt_vmsg_send_supported (GtNode *node); /* vendor.c */ 1.36 + 1.37 +/*****************************************************************************/ 1.38 + 1.39 +extern GT_MSG_HANDLER(gt_msg_ping); 1.40 +extern GT_MSG_HANDLER(gt_msg_ping_reply); 1.41 +extern GT_MSG_HANDLER(gt_msg_bye); 1.42 +extern GT_MSG_HANDLER(gt_msg_push); 1.43 +extern GT_MSG_HANDLER(gt_msg_query_route); 1.44 +extern GT_MSG_HANDLER(gt_msg_query); 1.45 +extern GT_MSG_HANDLER(gt_msg_query_reply); 1.46 +extern GT_MSG_HANDLER(gt_msg_vendor); 1.47 + 1.48 +static struct msg_handler 1.49 +{ 1.50 + uint8_t command; 1.51 + GtMessageHandler func; 1.52 +} 1.53 +msg_handler_table[] = 1.54 +{ 1.55 + /* table listed not in numerical order, but by frequency of messages */ 1.56 + { GT_MSG_QUERY, gt_msg_query }, 1.57 + { GT_MSG_QUERY_REPLY, gt_msg_query_reply }, 1.58 + { GT_MSG_PING_REPLY, gt_msg_ping_reply }, 1.59 + { GT_MSG_PING, gt_msg_ping }, 1.60 + { GT_MSG_PUSH, gt_msg_push }, 1.61 + { GT_MSG_QUERY_ROUTE, gt_msg_query_route }, 1.62 + { GT_MSG_VENDOR, gt_msg_vendor }, 1.63 + { GT_MSG_VENDOR_STD, gt_msg_vendor }, /* same as non-standard */ 1.64 + { GT_MSG_BYE, gt_msg_bye }, 1.65 + { 0x00, NULL } 1.66 +}; 1.67 + 1.68 +/*****************************************************************************/ 1.69 + 1.70 +static BOOL handle_message (TCPC *c, GtPacket *packet) 1.71 +{ 1.72 + struct msg_handler *handler; 1.73 + uint8_t command; 1.74 + 1.75 + if (!packet) 1.76 + return FALSE; 1.77 + 1.78 + command = gt_packet_command (packet); 1.79 + 1.80 + /* locate the handler */ 1.81 + for (handler = msg_handler_table; handler->func; handler++) 1.82 + { 1.83 + if (command == handler->command) 1.84 + { 1.85 + handler->func (GT_NODE(c), c, packet); 1.86 + return TRUE; 1.87 + } 1.88 + } 1.89 + 1.90 + GIFT_ERROR (("[%s] found no handler for cmd %hx, payload %hx", 1.91 + net_ip_str (GT_NODE(c)->ip), command, 1.92 + gt_packet_payload_len (packet))); 1.93 + 1.94 + return FALSE; 1.95 +} 1.96 + 1.97 +static void cleanup_node_rx (GtNode *node) 1.98 +{ 1.99 + TCPC *c = GT_CONN(node); 1.100 + 1.101 + assert (GT_NODE(c) == node); 1.102 + gt_node_disconnect (c); 1.103 +} 1.104 + 1.105 +/* TODO: make this the same type as cleanup_node_rx */ 1.106 +static void cleanup_node_tx (GtTxStack *stack, GtNode *node) 1.107 +{ 1.108 + TCPC *c = GT_CONN(node); 1.109 + 1.110 + assert (GT_NODE(c) == node); 1.111 + gt_node_disconnect (c); 1.112 +} 1.113 + 1.114 +static void recv_packet (GtNode *node, GtPacket *packet) 1.115 +{ 1.116 + assert (packet != NULL); 1.117 + 1.118 + gt_packet_log (packet, GT_CONN(node), FALSE); 1.119 + (void)handle_message (node->c, packet); 1.120 +} 1.121 + 1.122 +/* Find out what our IP is */ 1.123 +static in_addr_t get_self_ip (TCPC *c) 1.124 +{ 1.125 + in_addr_t our_ip; 1.126 + char *ip_str; 1.127 + 1.128 + if ((ip_str = dataset_lookupstr (GT_NODE(c)->hdr, "remote-ip"))) 1.129 + { 1.130 + /* 1.131 + * Since we may be firewalled, we may not know what our ip is. So set 1.132 + * the ip from what the other node thinks it is. 1.133 + * 1.134 + * Doing this allows you to setup port forwarding on a firewall 1.135 + * and accept incoming connections. 1.136 + */ 1.137 + our_ip = net_ip (ip_str); 1.138 + } 1.139 + else 1.140 + { 1.141 + struct sockaddr_in saddr; 1.142 + int len = sizeof (saddr); 1.143 + 1.144 + if (getsockname (c->fd, (struct sockaddr *)&saddr, &len) == 0) 1.145 + our_ip = saddr.sin_addr.s_addr; 1.146 + else 1.147 + our_ip = net_ip ("127.0.0.1"); 1.148 + } 1.149 + 1.150 + return our_ip; 1.151 +} 1.152 + 1.153 +/* 1.154 + * Begin a node connection with the peer on the specified TCPC. 1.155 + * 1.156 + * We arrive here from either an incoming or outgoing connection. 1.157 + * This is the entrance point to the main packet-reading loop. 1.158 + * 1.159 + * After setting up the connection, we send the node a ping. 1.160 + * If it doesn't respond after a timeout, we will destroy the 1.161 + * connection. 1.162 + */ 1.163 +void gnutella_start_connection (int fd, input_id id, TCPC *c) 1.164 +{ 1.165 + GtPacket *ping; 1.166 + GtNode *node; 1.167 + 1.168 + node = GT_NODE(c); 1.169 + assert (GT_CONN(node) == c); 1.170 + 1.171 + /* remove the old input handler first -- need to before sending data */ 1.172 + input_remove (id); 1.173 + 1.174 + if (net_sock_error (c->fd)) 1.175 + { 1.176 + if (HANDSHAKE_DEBUG) 1.177 + gt_node_error (c, NULL); 1.178 + 1.179 + gt_node_disconnect (c); 1.180 + return; 1.181 + } 1.182 + 1.183 + /* if this is the crawler, disconnect */ 1.184 + if (dataset_lookupstr (GT_NODE(c)->hdr, "crawler")) 1.185 + { 1.186 + if (HANDSHAKE_DEBUG) 1.187 + GT->DBGSOCK (GT, c, "closing crawler connection"); 1.188 + 1.189 + gt_node_disconnect (c); 1.190 + return; 1.191 + } 1.192 + 1.193 + if (!(node->rx_stack = gt_rx_stack_new (node, c, node->rx_inflated))) 1.194 + { 1.195 + if (HANDSHAKE_DEBUG) 1.196 + GT->DBGSOCK (GT, c, "error allocating rx_stack"); 1.197 + 1.198 + gt_node_disconnect (c); 1.199 + return; 1.200 + } 1.201 + 1.202 + if (!(node->tx_stack = gt_tx_stack_new (c, node->tx_deflated))) 1.203 + { 1.204 + if (HANDSHAKE_DEBUG) 1.205 + GT->DBGSOCK (GT, c, "error allocating tx stack"); 1.206 + 1.207 + gt_node_disconnect (c); 1.208 + return; 1.209 + } 1.210 + 1.211 + /* determine the other node's opinion of our IP address */ 1.212 + node->my_ip = get_self_ip (c); 1.213 + 1.214 + /* determine the other ends port */ 1.215 + peer_addr (c->fd, NULL, &node->peer_port); 1.216 + 1.217 + if (HANDSHAKE_DEBUG) 1.218 + { 1.219 + GT->DBGSOCK (GT, c, "self IP=[%s]", net_ip_str (node->my_ip)); 1.220 + GT->DBGSOCK (GT, c, "peer port=%hu", node->peer_port); 1.221 + } 1.222 + 1.223 + if (!(ping = gt_packet_new (GT_MSG_PING, 1, NULL))) 1.224 + { 1.225 + gt_node_disconnect (c); 1.226 + return; 1.227 + } 1.228 + 1.229 + /* set the state as intermediately connecting and mark the node connected 1.230 + * only when it replies to our ping */ 1.231 + gt_node_state_set (node, GT_NODE_CONNECTING_2); 1.232 + 1.233 + /* give the connection some more time */ 1.234 + gnutella_set_handshake_timeout (c, TIMEOUT_3 * SECONDS); 1.235 + 1.236 + /* 1.237 + * Setup our packet handlers, for both receiving and sending packets. 1.238 + */ 1.239 + gt_rx_stack_set_handler (node->rx_stack, 1.240 + (GtRxStackHandler)recv_packet, 1.241 + (GtRxStackCleanup)cleanup_node_rx, 1.242 + node); 1.243 + 1.244 + gt_tx_stack_set_handler (node->tx_stack, 1.245 + (GtTxStackCleanup)cleanup_node_tx, 1.246 + node); 1.247 + 1.248 + /* send first ping */ 1.249 + gt_packet_send (c, ping); 1.250 + gt_packet_free (ping); 1.251 + 1.252 + /* send MessagesSupported Vendor message, if this node supports it */ 1.253 + gt_vmsg_send_supported (node); 1.254 +}