2
* $Id: gt_message.c,v 1.6 2004/01/07 07:24:43 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 "msg_handler.h"
20
#include "gt_netorg.h"
21
#include "gt_connect.h"
25
#include "io/rx_stack.h" /* gt_rx_stack_new */
26
#include "io/tx_stack.h" /* gt_tx_stack_new */
28
#include "gt_message.h"
30
/*****************************************************************************/
32
extern void gt_vmsg_send_supported (GtNode *node); /* vendor.c */
34
/*****************************************************************************/
36
extern GT_MSG_HANDLER(gt_msg_ping);
37
extern GT_MSG_HANDLER(gt_msg_ping_reply);
38
extern GT_MSG_HANDLER(gt_msg_bye);
39
extern GT_MSG_HANDLER(gt_msg_push);
40
extern GT_MSG_HANDLER(gt_msg_query_route);
41
extern GT_MSG_HANDLER(gt_msg_query);
42
extern GT_MSG_HANDLER(gt_msg_query_reply);
43
extern GT_MSG_HANDLER(gt_msg_vendor);
45
static struct msg_handler
48
GtMessageHandler func;
52
/* table listed not in numerical order, but by frequency of messages */
53
{ GT_MSG_QUERY, gt_msg_query },
54
{ GT_MSG_QUERY_REPLY, gt_msg_query_reply },
55
{ GT_MSG_PING_REPLY, gt_msg_ping_reply },
56
{ GT_MSG_PING, gt_msg_ping },
57
{ GT_MSG_PUSH, gt_msg_push },
58
{ GT_MSG_QUERY_ROUTE, gt_msg_query_route },
59
{ GT_MSG_VENDOR, gt_msg_vendor },
60
{ GT_MSG_VENDOR_STD, gt_msg_vendor }, /* same as non-standard */
61
{ GT_MSG_BYE, gt_msg_bye },
65
/*****************************************************************************/
67
static BOOL handle_message (TCPC *c, GtPacket *packet)
69
struct msg_handler *handler;
75
command = gt_packet_command (packet);
77
/* locate the handler */
78
for (handler = msg_handler_table; handler->func; handler++)
80
if (command == handler->command)
82
handler->func (GT_NODE(c), c, packet);
87
GIFT_ERROR (("[%s] found no handler for cmd %hx, payload %hx",
88
net_ip_str (GT_NODE(c)->ip), command,
89
gt_packet_payload_len (packet)));
94
static void cleanup_node_rx (GtNode *node)
96
TCPC *c = GT_CONN(node);
98
assert (GT_NODE(c) == node);
99
gt_node_disconnect (c);
102
/* TODO: make this the same type as cleanup_node_rx */
103
static void cleanup_node_tx (GtTxStack *stack, GtNode *node)
105
TCPC *c = GT_CONN(node);
107
assert (GT_NODE(c) == node);
108
gt_node_disconnect (c);
111
static void recv_packet (GtNode *node, GtPacket *packet)
113
assert (packet != NULL);
115
gt_packet_log (packet, GT_CONN(node), FALSE);
116
(void)handle_message (node->c, packet);
119
/* Find out what our IP is */
120
static in_addr_t get_self_ip (TCPC *c)
125
if ((ip_str = dataset_lookupstr (GT_NODE(c)->hdr, "remote-ip")))
128
* Since we may be firewalled, we may not know what our ip is. So set
129
* the ip from what the other node thinks it is.
131
* Doing this allows you to setup port forwarding on a firewall
132
* and accept incoming connections.
134
our_ip = net_ip (ip_str);
138
struct sockaddr_in saddr;
139
int len = sizeof (saddr);
141
if (getsockname (c->fd, (struct sockaddr *)&saddr, &len) == 0)
142
our_ip = saddr.sin_addr.s_addr;
144
our_ip = net_ip ("127.0.0.1");
151
* Begin a node connection with the peer on the specified TCPC.
153
* We arrive here from either an incoming or outgoing connection.
154
* This is the entrance point to the main packet-reading loop.
156
* After setting up the connection, we send the node a ping.
157
* If it doesn't respond after a timeout, we will destroy the
160
void gnutella_start_connection (int fd, input_id id, TCPC *c)
166
assert (GT_CONN(node) == c);
168
/* remove the old input handler first -- need to before sending data */
171
if (net_sock_error (c->fd))
174
gt_node_error (c, NULL);
176
gt_node_disconnect (c);
180
/* if this is the crawler, disconnect */
181
if (dataset_lookupstr (GT_NODE(c)->hdr, "crawler"))
184
GT->DBGSOCK (GT, c, "closing crawler connection");
186
gt_node_disconnect (c);
190
if (!(node->rx_stack = gt_rx_stack_new (node, c, node->rx_inflated)))
193
GT->DBGSOCK (GT, c, "error allocating rx_stack");
195
gt_node_disconnect (c);
199
if (!(node->tx_stack = gt_tx_stack_new (c, node->tx_deflated)))
202
GT->DBGSOCK (GT, c, "error allocating tx stack");
204
gt_node_disconnect (c);
208
/* determine the other node's opinion of our IP address */
209
node->my_ip = get_self_ip (c);
211
/* determine the other ends port */
212
peer_addr (c->fd, NULL, &node->peer_port);
216
GT->DBGSOCK (GT, c, "self IP=[%s]", net_ip_str (node->my_ip));
217
GT->DBGSOCK (GT, c, "peer port=%hu", node->peer_port);
220
if (!(ping = gt_packet_new (GT_MSG_PING, 1, NULL)))
222
gt_node_disconnect (c);
226
/* set the state as intermediately connecting and mark the node connected
227
* only when it replies to our ping */
228
gt_node_state_set (node, GT_NODE_CONNECTING_2);
230
/* give the connection some more time */
231
gnutella_set_handshake_timeout (c, TIMEOUT_3 * SECONDS);
234
* Setup our packet handlers, for both receiving and sending packets.
236
gt_rx_stack_set_handler (node->rx_stack,
237
(GtRxStackHandler)recv_packet,
238
(GtRxStackCleanup)cleanup_node_rx,
241
gt_tx_stack_set_handler (node->tx_stack,
242
(GtTxStackCleanup)cleanup_node_tx,
245
/* send first ping */
246
gt_packet_send (c, ping);
247
gt_packet_free (ping);
249
/* send MessagesSupported Vendor message, if this node supports it */
250
gt_vmsg_send_supported (node);