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

« back to all changes in this revision

Viewing changes to src/gt_connect.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
1
/*
2
 
 * $Id: gt_connect.c,v 1.42 2003/12/23 10:28:15 hipnod Exp $
 
2
 * $Id: gt_connect.c,v 1.55 2005/01/04 15:03:40 mkern Exp $
3
3
 *
4
4
 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
5
5
 *
19
19
 
20
20
#include "gt_connect.h"
21
21
#include "gt_accept.h"
22
 
 
23
 
#include "gt_protocol.h"
24
22
#include "gt_packet.h"
25
23
 
26
24
#include "gt_node.h"
32
30
 
33
31
#include "gt_node_cache.h"
34
32
 
 
33
#include "message/gt_message.h"   /* gnutella_start_connection */
 
34
 
35
35
/*****************************************************************************/
36
36
 
37
37
static void send_connect  (int fd, input_id id, TCPC *c);
49
49
 
50
50
        if (!(node->state & GT_NODE_CONNECTED))
51
51
        {
52
 
                GT->DBGSOCK (GT, c, "connection attempt timed out (%s) after %us", 
53
 
                             gt_node_state_str (node->state),
54
 
                             time (NULL) - node->start_connect_time);
55
 
 
56
52
                gt_node_disconnect (c);
57
53
                return FALSE;
58
54
        }
152
148
                   (InputCallback)recv_headers, 0);
153
149
}
154
150
 
155
 
int gnutella_parse_response_headers (char *reply, Dataset **r_headers)
 
151
BOOL gnutella_parse_response_headers (char *reply, Dataset **r_headers)
156
152
{
157
153
        int       code;    /* 200, 404, ... */
158
154
        char     *response;
167
163
        code = ATOI (string_sep (&response, " ")); /* shift past 200 */
168
164
 
169
165
        /* parse the headers */
170
 
        http_headers_parse (reply, &headers);
 
166
        gt_http_header_parse (reply, &headers);
171
167
 
172
168
        if (r_headers)
173
169
                *r_headers = headers;
180
176
        return FALSE;
181
177
}
182
178
 
183
 
#if 0
184
179
static time_t parse_uptime (Dataset *d)
185
180
{
186
181
        char   *str;
195
190
        if ((n = sscanf (str, "%dd %dh %dm", &days, &hours, &mins)) != 3)
196
191
                return 0;
197
192
 
198
 
        GT->dbg (GT, "uptime parsed: %d days, %d hours, %d minutes",
199
 
                 days, hours, mins);
 
193
        if (HANDSHAKE_DEBUG)
 
194
        {
 
195
                GT->dbg (GT, "uptime parsed: %d days, %d hours, %d minutes",
 
196
                         days, hours, mins);
 
197
        }
200
198
 
201
199
        return days * EDAYS + hours * EHOURS + mins * EMINUTES;
202
200
}
203
 
#endif
204
201
 
205
202
/* look in a header field for nodes, and register them */
206
203
static void extract_nodes (Dataset *d, in_addr_t src,
207
 
                           const char *field, GtNodeClass klass)
 
204
                           const char *field, gt_node_class_t klass)
208
205
{
209
206
        char   *str;
210
207
        char   *value;
226
223
                if (port == (in_port_t) -1 || port == 0)
227
224
                        continue;
228
225
 
229
 
                if (ip == (in_addr_t) -1 || ip == 0)
 
226
                if (ip == INADDR_NONE || ip == 0)
230
227
                        continue;
231
228
 
232
229
                if (gt_is_local_ip (ip, src))
245
242
        size_t   response_len = 0;
246
243
        int      n;
247
244
        BOOL     ok;
 
245
        time_t   uptime;
 
246
        GtNode  *node         = GT_NODE(c);
248
247
 
249
248
        buf = tcp_readbuf (c);
250
249
 
255
254
                return;
256
255
        }
257
256
 
 
257
        if (gt_fdbuf_full (buf))
 
258
        {
 
259
                gt_node_disconnect (c);
 
260
                return;
 
261
        }
 
262
 
258
263
        if (n > 0)
259
264
                return;
260
265
 
261
266
        response = fdbuf_data (buf, &response_len);
262
 
        if (!http_headers_terminated (response, response_len))
 
267
        if (!gt_http_header_terminated (response, response_len))
263
268
                return;
264
269
 
265
270
        fdbuf_release (buf);
268
273
                GT->DBGSOCK (GT, c, "node handshake response:\n%s", response);
269
274
 
270
275
        /* parse and store the response */
271
 
        ok = gnutella_parse_response_headers (response, &GT_NODE(c)->hdr);
 
276
        ok = gnutella_parse_response_headers (response, &node->hdr);
272
277
 
273
278
        /* extract nodes */
274
 
        extract_nodes (GT_NODE(c)->hdr, GT_NODE(c)->ip, "x-try-ultrapeers",
275
 
                       GT_NODE_ULTRA);
276
 
        extract_nodes (GT_NODE(c)->hdr, GT_NODE(c)->ip, "x-try", GT_NODE_NONE);
 
279
        extract_nodes (node->hdr, node->ip, "x-try-ultrapeers", GT_NODE_ULTRA);
 
280
        extract_nodes (node->hdr, node->ip, "x-try", GT_NODE_NONE);
277
281
 
278
 
#if 0
279
282
        /* grab the uptime from the "Uptime: " header and update this node */
280
 
        uptime = parse_uptime (GT_NODE(c)->hdr);
281
 
        gt_node_cache_add_ipv4 (GT_NODE(c)->ip, GT_NODE(c)->port, GT_NODE_ULTRA,
282
 
                                time (NULL), uptime);
283
 
#endif
 
283
        if ((uptime = parse_uptime (node->hdr)) > 0)
 
284
        {
 
285
                gt_node_cache_add_ipv4 (node->ip, node->gt_port,
 
286
                                        GT_NODE_ULTRA, time (NULL), uptime, node->ip);
 
287
 
 
288
                /* XXX: remove the item immediately so we trigger the side effect of
 
289
                 * adding this node to the stable list */
 
290
                gt_node_cache_del_ipv4 (node->ip, node->gt_port);
 
291
        }
284
292
 
285
293
        if (!ok)
286
294
        {
354
362
        }
355
363
}
356
364
 
357
 
BOOL gnutella_send_connection_headers (TCPC *c, char *header)
 
365
BOOL gnutella_send_connection_headers (TCPC *c, const char *header)
358
366
{
359
367
        String *msg;
360
368
 
373
381
        /* Add a header describing the remote IP of the peer */
374
382
        string_appendf (msg, "Remote-IP: %s\r\n", net_peer_ip (c->fd));
375
383
 
 
384
        /* let remote end know it's ok to send vendor messages */
 
385
        string_appendf (msg, "Vendor-Message: 0.1\r\n");
 
386
 
 
387
        /* support transmission of pings/pongs with GGEP appended */
 
388
        string_append  (msg, "GGEP: 0.5\r\n");
 
389
 
376
390
        /* If this is the limewire crawler, append "Peers: " and "Leaves: "
377
391
         * headers and close the connection */
378
392
        if (!c->outgoing && dataset_lookupstr (GT_NODE(c)->hdr, "crawler"))
381
395
        /* append willingness to receive compressed data */
382
396
        string_append (msg, "Accept-Encoding: deflate\r\n");
383
397
                
 
398
        /* check whether the remote node sent us Accept-Encoding: deflate
 
399
         * already */
 
400
        gnutella_mark_compression (GT_NODE(c));
 
401
 
 
402
        /* compress data if we must */
 
403
        if (GT_NODE(c)->tx_deflated)
 
404
                string_append (msg, "Content-Encoding: deflate\r\n");
 
405
 
384
406
        /* Add message terminator */
385
407
        string_append (msg, "\r\n");
386
408
 
410
432
        string_append (s, "GNUTELLA/0.6 200 OK\r\n");
411
433
 
412
434
        /* mark the connection as complete */
413
 
        gnutella_mark_completed (GT_NODE(c));
 
435
        gnutella_mark_compression (GT_NODE(c));
 
436
 
 
437
        if (GT_NODE(c)->tx_deflated)
 
438
                string_append (s, "Content-Encoding: deflate\r\n");
414
439
 
415
440
        /* append msg terminator */
416
441
        string_append (s, "\r\n");
430
455
}
431
456
 
432
457
/*****************************************************************************/
433
 
/* PORT VERIFICATION */
 
458
/* CONNECTABILITY TESTING */
434
459
 
435
 
static void connect_test_result (GtNode *node, TCPC *verify, int success)
 
460
static void connect_test_result (GtNode *node, TCPC *c, BOOL success)
436
461
{
437
 
        if (!success)
438
 
        {
439
 
                /* this node isnt connectable, so set it as firewalled */
440
 
                GT->DBGFN (GT, "setting %s as firewalled", net_ip_str (node->ip));
441
 
                node->firewalled = TRUE;
442
 
        }
443
 
        else
444
 
        {
445
 
                /* ok, we can connect to this node */
446
 
                GT->DBGFN (GT, "%s isnt firewalled", net_ip_str (node->ip));
447
 
                node->firewalled = FALSE;
448
 
        }
449
 
 
450
 
        if (verify)
451
 
        {
452
 
                tcp_close (verify);
 
462
        GT->DBGFN (GT, "connect test to %s %s", net_ip_str (node->ip),
 
463
                   (success ? "succeeded" : "failed"));
 
464
 
 
465
        node->firewalled = (success ? FALSE : TRUE);
 
466
        node->verified   = TRUE;
 
467
 
 
468
        if (c)
 
469
        {
 
470
                tcp_close (c);
453
471
                node->gt_port_verify = NULL;
454
472
        }
455
 
 
456
 
        node->verified = TRUE;
457
473
}
458
474
 
459
 
static void gt_handle_verification (int fd, input_id id, TCPC *verify)
 
475
static void test_connectable (int fd, input_id id, TCPC *c)
460
476
{
461
477
        GtNode *node;
462
478
 
463
 
        node = verify->udata;
 
479
        node = c->udata;
464
480
 
465
 
        if (net_sock_error (verify->fd))
 
481
        if (net_sock_error (c->fd))
466
482
        {
467
 
                connect_test_result (node, verify, FALSE);
 
483
                connect_test_result (node, c, FALSE);
468
484
                return;
469
485
        }
470
486
 
471
487
        /*
472
488
         * Send two newlines, because some firewalls will let connections pass 
473
489
         * through, but no data.
474
 
         * 
475
 
         * This works just like the TCP ConnectBack vendor message.
476
490
         */
477
 
        tcp_send (verify, "\n\n", 2);
478
 
        connect_test_result (node, verify, TRUE);
 
491
        tcp_send (c, "\n\n", 2);
 
492
        connect_test_result (node, c, TRUE);
479
493
}
480
494
 
481
 
/* Verify the port of a peer we are connected to is connectable
482
 
 *
483
 
 * Nodes should send a ping response with their port in it
484
 
 * when pinged with a TTL of one, so utilize this info
485
 
 * to verify their firewalled status.  We could use this
486
 
 * info to mangle the 'push' flag on query hits from this
487
 
 * node if it is a leaf.
488
 
 *
489
 
 * NOTE: Mangling query hits would break any future
490
 
 * checksum or signing algorithm on query hits that
491
 
 * go to an ultranode */
 
495
/*
 
496
 * Test if the port of a peer we are connected to is connectable.  This lets a
 
497
 * node know if it's firewalled.  We could use this info to mangle the 'push'
 
498
 * flag on query hits from this node if it is a leaf.
 
499
 *
 
500
 * Mangling query hits would break any future checksum or signing algorithm on
 
501
 * query hits though, so that isn't done.
 
502
 */
492
503
void gt_connect_test (GtNode *node, in_port_t port)
493
504
{
494
505
        TCPC *new_c;
524
535
        if (node->gt_port_verify)
525
536
                tcp_close (node->gt_port_verify);
526
537
 
 
538
        /* keep track of this connection */
527
539
        node->gt_port_verify = new_c;
528
 
 
529
 
        node->firewalled = FALSE;
530
 
        node->verified   = FALSE;
531
 
 
532
540
        new_c->udata = node;
533
541
 
534
542
        input_add (new_c->fd, new_c, INPUT_WRITE,
535
 
                   (InputCallback)gt_handle_verification, TIMEOUT_DEF);
 
543
                   (InputCallback)test_connectable, TIMEOUT_DEF);
536
544
}