~ubuntu-branches/ubuntu/raring/gift-gnutella/raring

« back to all changes in this revision

Viewing changes to src/message/gt_message.c

  • Committer: Bazaar Package Importer
  • Author(s): Göran Weinholt
  • Date: 2005-07-31 13:56:53 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050731135653-3i7bcwnrbe7wfd1i
Tags: 0.0.10.1-1
* New upstream version.
  - Fixes FTBFS with gcc-4.0 (closes: #286732).
* Updated debian/patches/update-gwebcaches.patch.
* Updated debian/patches/remove-too-old-check.patch.
* debian/control:
  - Change the encoding of my name to UTF-8.
  - Updated to Standards-Version: 3.6.2 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: gt_message.c,v 1.6 2004/01/07 07:24:43 hipnod Exp $
 
3
 *
 
4
 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
 
5
 *
 
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
 
9
 * later version.
 
10
 *
 
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.
 
15
 */
 
16
 
 
17
#include "gt_gnutella.h"
 
18
#include "msg_handler.h"
 
19
 
 
20
#include "gt_netorg.h"
 
21
#include "gt_connect.h"
 
22
 
 
23
#include "gt_utils.h"
 
24
 
 
25
#include "io/rx_stack.h"               /* gt_rx_stack_new */
 
26
#include "io/tx_stack.h"               /* gt_tx_stack_new */
 
27
 
 
28
#include "gt_message.h"
 
29
 
 
30
/*****************************************************************************/
 
31
 
 
32
extern void gt_vmsg_send_supported (GtNode *node);   /* vendor.c */
 
33
 
 
34
/*****************************************************************************/
 
35
 
 
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);
 
44
 
 
45
static struct msg_handler
 
46
{
 
47
        uint8_t command;
 
48
        GtMessageHandler func;
 
49
}
 
50
msg_handler_table[] =
 
51
{
 
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         },
 
62
        { 0x00,                NULL               }
 
63
};
 
64
 
 
65
/*****************************************************************************/
 
66
 
 
67
static BOOL handle_message (TCPC *c, GtPacket *packet)
 
68
{
 
69
        struct msg_handler *handler;
 
70
        uint8_t command;
 
71
 
 
72
        if (!packet)
 
73
                return FALSE;
 
74
 
 
75
        command = gt_packet_command (packet);
 
76
 
 
77
        /* locate the handler */
 
78
        for (handler = msg_handler_table; handler->func; handler++)
 
79
        {
 
80
                if (command == handler->command)
 
81
                {
 
82
                        handler->func (GT_NODE(c), c, packet);
 
83
                        return TRUE;
 
84
                }
 
85
        }
 
86
 
 
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)));
 
90
 
 
91
        return FALSE;
 
92
}
 
93
 
 
94
static void cleanup_node_rx (GtNode *node)
 
95
{
 
96
        TCPC    *c = GT_CONN(node);
 
97
 
 
98
        assert (GT_NODE(c) == node);
 
99
        gt_node_disconnect (c);
 
100
}
 
101
 
 
102
/* TODO: make this the same type as cleanup_node_rx */
 
103
static void cleanup_node_tx (GtTxStack *stack, GtNode *node)
 
104
{
 
105
        TCPC *c = GT_CONN(node);
 
106
 
 
107
        assert (GT_NODE(c) == node);
 
108
        gt_node_disconnect (c);
 
109
}
 
110
 
 
111
static void recv_packet (GtNode *node, GtPacket *packet)
 
112
{
 
113
        assert (packet != NULL);
 
114
 
 
115
        gt_packet_log (packet, GT_CONN(node), FALSE);
 
116
        (void)handle_message (node->c, packet);
 
117
}
 
118
 
 
119
/* Find out what our IP is */
 
120
static in_addr_t get_self_ip (TCPC *c)
 
121
{
 
122
        in_addr_t our_ip;
 
123
        char     *ip_str;
 
124
 
 
125
        if ((ip_str = dataset_lookupstr (GT_NODE(c)->hdr, "remote-ip")))
 
126
        {
 
127
                /*
 
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.
 
130
                 *
 
131
                 * Doing this allows you to setup port forwarding on a firewall
 
132
                 * and accept incoming connections.
 
133
                 */
 
134
                our_ip = net_ip (ip_str);
 
135
        }
 
136
        else
 
137
        {
 
138
                struct sockaddr_in saddr;
 
139
                int    len = sizeof (saddr);
 
140
 
 
141
                if (getsockname (c->fd, (struct sockaddr *)&saddr, &len) == 0)
 
142
                        our_ip = saddr.sin_addr.s_addr;
 
143
                else
 
144
                        our_ip = net_ip ("127.0.0.1");
 
145
        }
 
146
 
 
147
        return our_ip;
 
148
}
 
149
 
 
150
/*
 
151
 * Begin a node connection with the peer on the specified TCPC.
 
152
 *
 
153
 * We arrive here from either an incoming or outgoing connection.
 
154
 * This is the entrance point to the main packet-reading loop.
 
155
 *
 
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
 
158
 * connection.
 
159
 */
 
160
void gnutella_start_connection (int fd, input_id id, TCPC *c)
 
161
{
 
162
        GtPacket    *ping;
 
163
        GtNode      *node;
 
164
 
 
165
        node = GT_NODE(c);
 
166
        assert (GT_CONN(node) == c);
 
167
 
 
168
        /* remove the old input handler first -- need to before sending data */
 
169
        input_remove (id);
 
170
 
 
171
        if (net_sock_error (c->fd))
 
172
        {
 
173
                if (HANDSHAKE_DEBUG)
 
174
                        gt_node_error (c, NULL);
 
175
 
 
176
                gt_node_disconnect (c);
 
177
                return;
 
178
        }
 
179
 
 
180
        /* if this is the crawler, disconnect */
 
181
        if (dataset_lookupstr (GT_NODE(c)->hdr, "crawler"))
 
182
        {
 
183
                if (HANDSHAKE_DEBUG)
 
184
                        GT->DBGSOCK (GT, c, "closing crawler connection");
 
185
 
 
186
                gt_node_disconnect (c);
 
187
                return;
 
188
        }
 
189
 
 
190
        if (!(node->rx_stack = gt_rx_stack_new (node, c, node->rx_inflated)))
 
191
        {
 
192
                if (HANDSHAKE_DEBUG)
 
193
                        GT->DBGSOCK (GT, c, "error allocating rx_stack");
 
194
 
 
195
                gt_node_disconnect (c);
 
196
                return;
 
197
        }
 
198
 
 
199
        if (!(node->tx_stack = gt_tx_stack_new (c, node->tx_deflated)))
 
200
        {
 
201
                if (HANDSHAKE_DEBUG)
 
202
                        GT->DBGSOCK (GT, c, "error allocating tx stack");
 
203
 
 
204
                gt_node_disconnect (c);
 
205
                return;
 
206
        }
 
207
 
 
208
        /* determine the other node's opinion of our IP address */
 
209
        node->my_ip = get_self_ip (c);
 
210
 
 
211
        /* determine the other ends port */
 
212
        peer_addr (c->fd, NULL, &node->peer_port);
 
213
 
 
214
        if (HANDSHAKE_DEBUG)
 
215
        {
 
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);
 
218
        }
 
219
 
 
220
        if (!(ping = gt_packet_new (GT_MSG_PING, 1, NULL)))
 
221
        {
 
222
                gt_node_disconnect (c);
 
223
                return;
 
224
        }
 
225
 
 
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);
 
229
 
 
230
        /* give the connection some more time */
 
231
        gnutella_set_handshake_timeout (c, TIMEOUT_3 * SECONDS);
 
232
 
 
233
        /*
 
234
         * Setup our packet handlers, for both receiving and sending packets.
 
235
         */
 
236
        gt_rx_stack_set_handler (node->rx_stack,
 
237
                                 (GtRxStackHandler)recv_packet,
 
238
                                 (GtRxStackCleanup)cleanup_node_rx,
 
239
                                 node);
 
240
 
 
241
        gt_tx_stack_set_handler (node->tx_stack,
 
242
                                 (GtTxStackCleanup)cleanup_node_tx,
 
243
                                 node);
 
244
 
 
245
        /* send first ping */
 
246
        gt_packet_send (c, ping);
 
247
        gt_packet_free (ping);
 
248
 
 
249
        /* send MessagesSupported Vendor message, if this node supports it */
 
250
        gt_vmsg_send_supported (node);
 
251
}