195
190
if ((n = sscanf (str, "%dd %dh %dm", &days, &hours, &mins)) != 3)
198
GT->dbg (GT, "uptime parsed: %d days, %d hours, %d minutes",
195
GT->dbg (GT, "uptime parsed: %d days, %d hours, %d minutes",
201
199
return days * EDAYS + hours * EHOURS + mins * EMINUTES;
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)
268
273
GT->DBGSOCK (GT, c, "node handshake response:\n%s", response);
270
275
/* parse and store the response */
271
ok = gnutella_parse_response_headers (response, >_NODE(c)->hdr);
276
ok = gnutella_parse_response_headers (response, &node->hdr);
273
278
/* extract nodes */
274
extract_nodes (GT_NODE(c)->hdr, GT_NODE(c)->ip, "x-try-ultrapeers",
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);
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
if ((uptime = parse_uptime (node->hdr)) > 0)
285
gt_node_cache_add_ipv4 (node->ip, node->gt_port,
286
GT_NODE_ULTRA, time (NULL), uptime, node->ip);
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);
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));
384
/* let remote end know it's ok to send vendor messages */
385
string_appendf (msg, "Vendor-Message: 0.1\r\n");
387
/* support transmission of pings/pongs with GGEP appended */
388
string_append (msg, "GGEP: 0.5\r\n");
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");
398
/* check whether the remote node sent us Accept-Encoding: deflate
400
gnutella_mark_compression (GT_NODE(c));
402
/* compress data if we must */
403
if (GT_NODE(c)->tx_deflated)
404
string_append (msg, "Content-Encoding: deflate\r\n");
384
406
/* Add message terminator */
385
407
string_append (msg, "\r\n");
410
432
string_append (s, "GNUTELLA/0.6 200 OK\r\n");
412
434
/* mark the connection as complete */
413
gnutella_mark_completed (GT_NODE(c));
435
gnutella_mark_compression (GT_NODE(c));
437
if (GT_NODE(c)->tx_deflated)
438
string_append (s, "Content-Encoding: deflate\r\n");
415
440
/* append msg terminator */
416
441
string_append (s, "\r\n");
432
457
/*****************************************************************************/
433
/* PORT VERIFICATION */
458
/* CONNECTABILITY TESTING */
435
static void connect_test_result (GtNode *node, TCPC *verify, int success)
460
static void connect_test_result (GtNode *node, TCPC *c, BOOL success)
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;
445
/* ok, we can connect to this node */
446
GT->DBGFN (GT, "%s isnt firewalled", net_ip_str (node->ip));
447
node->firewalled = FALSE;
462
GT->DBGFN (GT, "connect test to %s %s", net_ip_str (node->ip),
463
(success ? "succeeded" : "failed"));
465
node->firewalled = (success ? FALSE : TRUE);
466
node->verified = TRUE;
453
471
node->gt_port_verify = NULL;
456
node->verified = TRUE;
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)
463
node = verify->udata;
465
if (net_sock_error (verify->fd))
481
if (net_sock_error (c->fd))
467
connect_test_result (node, verify, FALSE);
483
connect_test_result (node, c, FALSE);
472
488
* Send two newlines, because some firewalls will let connections pass
473
489
* through, but no data.
475
* This works just like the TCP ConnectBack vendor message.
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);
481
/* Verify the port of a peer we are connected to is connectable
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.
489
* NOTE: Mangling query hits would break any future
490
* checksum or signing algorithm on query hits that
491
* go to an ultranode */
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.
500
* Mangling query hits would break any future checksum or signing algorithm on
501
* query hits though, so that isn't done.
492
503
void gt_connect_test (GtNode *node, in_port_t port)
524
535
if (node->gt_port_verify)
525
536
tcp_close (node->gt_port_verify);
538
/* keep track of this connection */
527
539
node->gt_port_verify = new_c;
529
node->firewalled = FALSE;
530
node->verified = FALSE;
532
540
new_c->udata = node;
534
542
input_add (new_c->fd, new_c, INPUT_WRITE,
535
(InputCallback)gt_handle_verification, TIMEOUT_DEF);
543
(InputCallback)test_connectable, TIMEOUT_DEF);