~ubuntu-branches/ubuntu/karmic/gtk-gnutella/karmic

« back to all changes in this revision

Viewing changes to src/pcache.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Kleineidam
  • Date: 2004-05-22 15:26:55 UTC
  • Revision ID: james.westby@ubuntu.com-20040522152655-lyi6iaswmy4hq4wy
Tags: upstream-0.93.3.0
ImportĀ upstreamĀ versionĀ 0.93.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: pcache.c,v 1.48 2004/01/14 20:52:33 rmanfredi Exp $
 
3
 *
 
4
 * Copyright (c) 2001-2003, Raphael Manfredi
 
5
 *
 
6
 * Pong caching (LimeWire's ping/pong reducing scheme).
 
7
 *
 
8
 *----------------------------------------------------------------------
 
9
 * This file is part of gtk-gnutella.
 
10
 *
 
11
 *  gtk-gnutella is free software; you can redistribute it and/or modify
 
12
 *  it under the terms of the GNU General Public License as published by
 
13
 *  the Free Software Foundation; either version 2 of the License, or
 
14
 *  (at your option) any later version.
 
15
 *
 
16
 *  gtk-gnutella is distributed in the hope that it will be useful,
 
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *  GNU General Public License for more details.
 
20
 *
 
21
 *  You should have received a copy of the GNU General Public License
 
22
 *  along with gtk-gnutella; if not, write to the Free Software
 
23
 *  Foundation, Inc.:
 
24
 *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
25
 *----------------------------------------------------------------------
 
26
 */
 
27
 
 
28
#include "gnutella.h"
 
29
 
 
30
#include <stdlib.h>
 
31
#include <fcntl.h>
 
32
#include <sys/types.h>
 
33
#include <string.h>
 
34
 
 
35
#include <netinet/in.h>
 
36
#include <arpa/inet.h>
 
37
 
 
38
#include "sockets.h"
 
39
#include "hosts.h"
 
40
#include "hcache.h"
 
41
#include "pcache.h"
 
42
#include "nodes.h"
 
43
#include "share.h" /* For files_scanned and kbytes_scanned. */
 
44
#include "routing.h"
 
45
#include "gmsg.h"
 
46
#include "alive.h"
 
47
#include "inet.h"
 
48
#include "gnet_stats.h"
 
49
#include "hostiles.h"
 
50
 
 
51
#include "settings.h"
 
52
#include "override.h"           /* Must be the last header included */
 
53
 
 
54
RCSID("$Id: pcache.c,v 1.48 2004/01/14 20:52:33 rmanfredi Exp $");
 
55
 
 
56
/***
 
57
 *** Messages
 
58
 ***/
 
59
 
 
60
/*
 
61
 * send_ping
 
62
 *
 
63
 * Sends a ping to given node, or broadcast to everyone if `n' is NULL.
 
64
 */
 
65
static void send_ping(struct gnutella_node *n, guint8 ttl)
 
66
{
 
67
        struct gnutella_msg_init m;
 
68
 
 
69
        message_set_muid(&m.header, GTA_MSG_INIT);
 
70
 
 
71
        m.header.function = GTA_MSG_INIT;
 
72
        m.header.ttl = ttl;
 
73
        m.header.hops = 0;
 
74
 
 
75
        WRITE_GUINT32_LE(0, m.header.size);
 
76
 
 
77
        if (n) {
 
78
                if (NODE_IS_WRITABLE(n)) {
 
79
                        n->n_ping_sent++;
 
80
                        gmsg_sendto_one(n, (gchar *) &m, sizeof(struct gnutella_msg_init));
 
81
                }
 
82
        } else {
 
83
                const GSList *sl_nodes = node_all_nodes();
 
84
                const GSList *sl;
 
85
 
 
86
                /*
 
87
                 * XXX Have to loop to count pings sent.
 
88
                 * XXX Need to do that more generically, to factorize code.
 
89
                 */
 
90
 
 
91
                for (sl = sl_nodes; sl; sl = g_slist_next(sl)) {
 
92
                        n = (struct gnutella_node *) sl->data;
 
93
                        if (!NODE_IS_WRITABLE(n))
 
94
                                continue;
 
95
                        n->n_ping_sent++;
 
96
                }
 
97
 
 
98
                gmsg_sendto_all(sl_nodes, (gchar *) &m,
 
99
                        sizeof(struct gnutella_msg_init));
 
100
        }
 
101
}
 
102
 
 
103
/*
 
104
 * send_alive_ping
 
105
 *
 
106
 * Send ping to immediate neighbour, to check its latency and the fact
 
107
 * that it is alive, or get its Gnet sharing information (ip, port).
 
108
 * The message is sent as a "control" one, i.e. it's put ahead of the queue.
 
109
 *
 
110
 * The message ID used is copied back to `muid'.
 
111
 *
 
112
 * NB: this routine is only made visible for "alive.c".
 
113
 */
 
114
void send_alive_ping(struct gnutella_node *n, gchar *muid)
 
115
{
 
116
        struct gnutella_msg_init m;
 
117
 
 
118
        g_assert(NODE_IS_WRITABLE(n));
 
119
        g_assert(muid);
 
120
 
 
121
        message_set_muid(&m.header, GTA_MSG_INIT);
 
122
        memcpy(muid, &m.header, 16);
 
123
 
 
124
        m.header.function = GTA_MSG_INIT;
 
125
        m.header.ttl = 1;
 
126
        m.header.hops = 0;
 
127
 
 
128
        WRITE_GUINT32_LE(0, m.header.size);
 
129
 
 
130
        n->n_ping_sent++;
 
131
        gmsg_ctrl_sendto_one(n, (gchar *) &m, sizeof(struct gnutella_msg_init));
 
132
}
 
133
 
 
134
/*
 
135
 * build_pong_msg
 
136
 *
 
137
 * Build pong message, returns pointer to static data.
 
138
 */
 
139
struct gnutella_msg_init_response *build_pong_msg(
 
140
        guint8 hops, guint8 ttl, gchar *muid,
 
141
        guint32 ip, guint16 port, guint32 files, guint32 kbytes)
 
142
{
 
143
        static struct gnutella_msg_init_response pong;
 
144
 
 
145
        pong.header.function = GTA_MSG_INIT_RESPONSE;
 
146
        pong.header.hops = hops;
 
147
        pong.header.ttl = ttl;
 
148
        memcpy(&pong.header.muid, muid, 16);
 
149
 
 
150
        WRITE_GUINT16_LE(port, pong.response.host_port);
 
151
        WRITE_GUINT32_BE(ip, pong.response.host_ip);
 
152
        WRITE_GUINT32_LE(files, pong.response.files_count);
 
153
        WRITE_GUINT32_LE(kbytes, pong.response.kbytes_count);
 
154
        WRITE_GUINT32_LE(sizeof(struct gnutella_init_response), pong.header.size);
 
155
 
 
156
        return &pong;
 
157
}
 
158
 
 
159
/*
 
160
 * send_pong
 
161
 *
 
162
 * Send pong message back to node.
 
163
 * If `control' is true, send it as a higher priority message.
 
164
 */
 
165
static void send_pong(struct gnutella_node *n, gboolean control,
 
166
        guint8 hops, guint8 ttl, gchar *muid,
 
167
        guint32 ip, guint16 port, guint32 files, guint32 kbytes)
 
168
{
 
169
        struct gnutella_msg_init_response *r;
 
170
 
 
171
        g_assert(ttl >= 1);
 
172
 
 
173
        if (!NODE_IS_WRITABLE(n))
 
174
                return;
 
175
 
 
176
        r = build_pong_msg(hops, ttl, muid, ip, port, files, kbytes);
 
177
        n->n_pong_sent++;
 
178
 
 
179
        if (control)
 
180
                gmsg_ctrl_sendto_one(n, (gchar *) r, sizeof(*r));
 
181
        else
 
182
                gmsg_sendto_one(n, (gchar *) r, sizeof(*r));
 
183
}
 
184
 
 
185
/*
 
186
 * send_personal_info
 
187
 *
 
188
 * Send info about us back to node, using the hopcount information present in
 
189
 * the header of the node structure to construct the TTL of the pong we
 
190
 * send.
 
191
 *
 
192
 * If `control' is true, send it as a higher priority message.
 
193
 */
 
194
static void send_personal_info(struct gnutella_node *n, gboolean control)
 
195
{
 
196
        guint32 kbytes = 0;
 
197
 
 
198
        g_assert(n->header.function == GTA_MSG_INIT);   /* Replying to a ping */
 
199
 
 
200
        if (!force_local_ip && !local_ip)
 
201
                return;         /* If we don't know yet our local IP, we can't reply */
 
202
 
 
203
        /*
 
204
         * Mark pong if we are an ultra node: the amount of kbytes scanned must
 
205
         * be an exact power of two, and at minimum 8.
 
206
         */
 
207
 
 
208
        if (current_peermode == NODE_P_ULTRA) {
 
209
                if (kbytes_scanned <= 8)
 
210
                        kbytes = 8;
 
211
                else
 
212
                        kbytes = next_pow2(kbytes_scanned);
 
213
        } else if (kbytes_scanned)
 
214
                kbytes = kbytes_scanned | 0x1;          /* Ensure not a power of two */
 
215
 
 
216
        /*
 
217
         * Pongs are sent with a TTL just large enough to reach the pinging host,
 
218
         * up to a maximum of max_ttl.  Note that we rely on the hop count being
 
219
         * accurate.
 
220
         *                              --RAM, 15/09/2001
 
221
         */
 
222
 
 
223
        send_pong(n, control, 0, MIN(n->header.hops + 1, max_ttl), n->header.muid,
 
224
                listen_ip(), listen_port, files_scanned, kbytes);
 
225
}
 
226
 
 
227
/*
 
228
 * send_neighbouring_info
 
229
 *
 
230
 * Send a pong for each of our connected neighbours to specified node.
 
231
 */
 
232
static void send_neighbouring_info(struct gnutella_node *n)
 
233
{
 
234
        const GSList *sl;
 
235
 
 
236
        g_assert(n->header.function == GTA_MSG_INIT);   /* Replying to a ping */
 
237
        g_assert(n->header.hops == 0);                                  /* Originates from node */
 
238
        g_assert(n->header.ttl == 2);                                   /* "Crawler" ping */
 
239
 
 
240
        for (sl = node_all_nodes(); sl; sl = g_slist_next(sl)) {
 
241
                struct gnutella_node *cn = (struct gnutella_node *) sl->data;
 
242
 
 
243
                if (!NODE_IS_WRITABLE(cn))
 
244
                        continue;
 
245
 
 
246
                /*
 
247
                 * If we have valid Gnet information for the node, build the pong
 
248
                 * as if it came from the neighbour, only we don't send the ping,
 
249
                 * and don't have to read back the pong and resent it.
 
250
                 *
 
251
                 * Otherwise, don't send anything back: we no longer keep routing
 
252
                 * information for pings.
 
253
                 */
 
254
 
 
255
                if (cn->gnet_ip == 0)
 
256
                        continue;                               /* No information yet */
 
257
 
 
258
                send_pong(n, FALSE,
 
259
                        1, 1, n->header.muid,                   /* hops = 1, TTL = 1 */
 
260
                        cn->gnet_ip, cn->gnet_port,
 
261
                        cn->gnet_files_count, cn->gnet_kbytes_count);
 
262
 
 
263
                /*
 
264
                 * Since we won't see the neighbour pong, we won't be able to store
 
265
                 * it in our reserve, so do it from here.
 
266
                 */
 
267
 
 
268
                if (!NODE_IS_LEAF(n))
 
269
                        host_add(cn->gnet_ip, cn->gnet_port, FALSE);
 
270
 
 
271
                /*
 
272
                 * Node can be removed should its send queue saturate.
 
273
                 */
 
274
 
 
275
                if (!NODE_IS_CONNECTED(n))
 
276
                        return;
 
277
        }
 
278
}
 
279
 
 
280
/***
 
281
 *** Ping/pong reducing scheme.
 
282
 ***/
 
283
 
 
284
/*
 
285
 * Data structures used:
 
286
 *
 
287
 * `pong_cache' is an array of MAX_CACHE_HOPS+1 entries.
 
288
 * Each entry is a structure holding a one-way list and a traversal pointer
 
289
 * so we may iterate over the list of cached pongs at that hop level.
 
290
 *
 
291
 * `cache_expire_time' is the time after which we will expire the whole cache
 
292
 * and ping all our connections.
 
293
 */
 
294
 
 
295
static time_t pcache_expire_time = 0;
 
296
 
 
297
struct cached_pong {            /* A cached pong */
 
298
        gint refcount;                  /* How many lists reference us? */
 
299
        guint32 node_id;                /* The node ID from which we got that pong */
 
300
        guint32 last_sent_id;   /* Node ID to which we last sent this pong */
 
301
        guint32 ip;                             /* Values from the pong message */
 
302
        guint32 port;
 
303
        guint32 files_count;
 
304
        guint32 kbytes_count;
 
305
};
 
306
 
 
307
struct cache_line {                     /* A cache line for a given hop value */
 
308
        gint hops;                              /* Hop count of this cache line */
 
309
        GSList *pongs;                  /* List of cached_pong */
 
310
        GSList *cursor;                 /* Cursor within list: last item traversed */
 
311
};
 
312
 
 
313
struct recent {
 
314
        GHashTable *ht_recent_pongs;    /* Recent pongs we know about */
 
315
        GList *recent_pongs;                    /* Recent pongs we got */
 
316
        GList *last_returned_pong;              /* Last returned from list */
 
317
        gint recent_pong_count;                 /* # of pongs in recent list */
 
318
};
 
319
 
 
320
#define PONG_CACHE_SIZE         (MAX_CACHE_HOPS+1)
 
321
 
 
322
static struct cache_line pong_cache[PONG_CACHE_SIZE];
 
323
static struct recent recent_pongs[HCACHE_MAX];
 
324
 
 
325
#define CACHE_UP_LIFESPAN       5               /* seconds -- ultra/normal mode */
 
326
#define CACHE_LEAF_LIFESPAN     120             /* seconds -- leaf mode */
 
327
#define MAX_PONGS                       10              /* Max pongs returned per ping */
 
328
#define OLD_PING_PERIOD         45              /* Pinging period for "old" clients */
 
329
#define OLD_CACHE_RATIO         20              /* % of pongs from "old" clients we cache */
 
330
#define RECENT_PING_SIZE        50              /* remember last 50 pongs we saw */
 
331
#define MIN_UP_PING                     3               /* ping at least 3 neighbours */
 
332
#define UP_PING_RATIO           20              /* ping 20% of UP, at random */
 
333
 
 
334
#define cache_lifespan(m)       \
 
335
        ((m) == NODE_P_LEAF ? CACHE_LEAF_LIFESPAN : CACHE_UP_LIFESPAN)
 
336
 
 
337
/*
 
338
 * cached_pong_hash
 
339
 * cached_pong_eq
 
340
 *
 
341
 * Callbacks for the `ht_recent_pongs' hash table.
 
342
 */
 
343
 
 
344
static guint cached_pong_hash(gconstpointer key)
 
345
{
 
346
        const struct cached_pong *cp = (const struct cached_pong *) key;
 
347
 
 
348
        return (guint) (cp->ip ^ ((cp->port << 16) | cp->port));
 
349
}
 
350
static gint cached_pong_eq(gconstpointer v1, gconstpointer v2)
 
351
{
 
352
        const struct cached_pong *h1 = (const struct cached_pong *) v1;
 
353
        const struct cached_pong *h2 = (const struct cached_pong *) v2;
 
354
 
 
355
        return h1->ip == h2->ip && h1->port == h2->port;
 
356
}
 
357
 
 
358
/*
 
359
 * pcache_init
 
360
 */
 
361
void pcache_init(void)
 
362
{
 
363
        gint h;
 
364
 
 
365
        memset(pong_cache, 0, sizeof(pong_cache));
 
366
        memset(recent_pongs, 0, sizeof(recent_pongs));
 
367
 
 
368
        for (h = 0; h < PONG_CACHE_SIZE; h++)
 
369
                pong_cache[h].hops = h;
 
370
 
 
371
        recent_pongs[HCACHE_ANY].ht_recent_pongs =
 
372
                g_hash_table_new(cached_pong_hash, cached_pong_eq);
 
373
 
 
374
        recent_pongs[HCACHE_ULTRA].ht_recent_pongs =
 
375
                g_hash_table_new(cached_pong_hash, cached_pong_eq);
 
376
}
 
377
 
 
378
/*
 
379
 * free_cached_pong
 
380
 *
 
381
 * Free cached pong when noone references it any more.
 
382
 */
 
383
static void free_cached_pong(struct cached_pong *cp)
 
384
{
 
385
        g_assert(cp->refcount > 0);             /* Someone was referencing it */
 
386
 
 
387
        if (--(cp->refcount) != 0)
 
388
                return;
 
389
 
 
390
        wfree(cp, sizeof(*cp));
 
391
}
 
392
 
 
393
 
 
394
/*
 
395
 * pcache_get_recent
 
396
 *
 
397
 * Get a recent pong from the list, updating `last_returned_pong' as we
 
398
 * go along, so that we never return twice the same pong instance.
 
399
 *
 
400
 * Fills `ip' and `port' with the pong value and return TRUE if we
 
401
 * got a pong.  Otherwise return FALSE.
 
402
 */
 
403
gboolean pcache_get_recent(hcache_type_t type, guint32 *ip, guint16 *port)
 
404
{
 
405
        static guint32 last_ip = 0;
 
406
        static guint16 last_port = 0;
 
407
        GList *l;
 
408
        struct cached_pong *cp;
 
409
        struct recent *rec;
 
410
 
 
411
        g_assert(type >= 0 && type < HCACHE_MAX);
 
412
 
 
413
        rec = &recent_pongs[type];
 
414
 
 
415
        if (!rec->recent_pongs)         /* List empty */
 
416
                return FALSE;
 
417
 
 
418
        /*
 
419
         * If `last_returned_pong' is NULL, it means we reached the head
 
420
         * of the list, so we traverse faster than we get pongs.
 
421
         *
 
422
         * Try with the head of the list, because maybe we have a recent pong
 
423
         * there, but if it is the same as the last ip/port we returned, then
 
424
         * go back to the tail of the list.
 
425
         */
 
426
 
 
427
        if (rec->last_returned_pong == NULL) {
 
428
                l = g_list_first(rec->recent_pongs);
 
429
                cp = (struct cached_pong *) l->data;
 
430
 
 
431
                if (cp->ip != last_ip || cp->port != last_port)
 
432
                        goto found;
 
433
 
 
434
                if (g_list_next(l) == NULL)             /* Head is the only item in list */
 
435
                        return FALSE;
 
436
        } else {
 
437
                /* Regular case */
 
438
                l = g_list_previous(rec->last_returned_pong);
 
439
                for (/* empty */ ; l; l = g_list_previous(l)) {
 
440
                        cp = (struct cached_pong *) l->data;
 
441
                        if (cp->ip != last_ip || cp->port != last_port)
 
442
                                goto found;
 
443
                }
 
444
        }
 
445
 
 
446
        /*
 
447
         * Still none found, go back to the end of the list.
 
448
         */
 
449
 
 
450
        for (l = g_list_last(rec->recent_pongs); l; l = g_list_previous(l)) {
 
451
                cp = (struct cached_pong *) l->data;
 
452
                if (cp->ip != last_ip || cp->port != last_port)
 
453
                        goto found;
 
454
        }
 
455
 
 
456
        return FALSE;
 
457
 
 
458
found:
 
459
        rec->last_returned_pong = l;
 
460
        *ip = last_ip = cp->ip;
 
461
        *port = last_port = cp->port;
 
462
 
 
463
        if (dbg > 8)
 
464
                printf("returning recent %s PONG %s\n",
 
465
                        hcache_type_to_gchar(type), ip_port_to_gchar(cp->ip, cp->port));
 
466
 
 
467
        return TRUE;
 
468
}
 
469
 
 
470
/*
 
471
 * add_recent_pong
 
472
 *
 
473
 * Add recent pong to the list, handled as a FIFO cache, if not already
 
474
 * present.
 
475
 */
 
476
static void add_recent_pong(hcache_type_t type, struct cached_pong *cp)
 
477
{
 
478
        struct recent *rec;
 
479
 
 
480
        g_assert(type >= 0 && type < HCACHE_MAX);
 
481
 
 
482
        rec = &recent_pongs[type];
 
483
 
 
484
        if (g_hash_table_lookup(rec->ht_recent_pongs, (gconstpointer) cp))
 
485
                return;
 
486
 
 
487
        if (rec->recent_pong_count == RECENT_PING_SIZE) {               /* Full */
 
488
                GList *lnk = g_list_last(rec->recent_pongs);
 
489
                struct cached_pong *cp = (struct cached_pong *) lnk->data;
 
490
 
 
491
                rec->recent_pongs = g_list_remove_link(rec->recent_pongs, lnk);
 
492
                g_hash_table_remove(rec->ht_recent_pongs, cp);
 
493
 
 
494
                if (lnk == rec->last_returned_pong)
 
495
                        rec->last_returned_pong = g_list_previous(rec->last_returned_pong);
 
496
 
 
497
                free_cached_pong(cp);
 
498
                g_list_free_1(lnk);
 
499
        } else
 
500
                rec->recent_pong_count++;
 
501
        
 
502
        rec->recent_pongs = g_list_prepend(rec->recent_pongs, cp);
 
503
        g_hash_table_insert(rec->ht_recent_pongs, cp, (gpointer) 1);
 
504
        cp->refcount++;         /* We don't refcount insertion in the hash table */
 
505
}
 
506
 
 
507
/*
 
508
 * pong_type
 
509
 *
 
510
 * Determine the pong type (any, or of the ultra kind).
 
511
 */
 
512
static hcache_type_t pong_type(struct gnutella_init_response *pong)
 
513
{
 
514
        guint32 kbytes;
 
515
 
 
516
        READ_GUINT32_LE(pong->kbytes_count, kbytes);
 
517
 
 
518
        /*
 
519
         * Ultra pongs are marked by having their kbytes count be an
 
520
         * exact power of two, and greater than 8.
 
521
         */
 
522
 
 
523
        return (kbytes >= 8 && is_pow2(kbytes)) ? HCACHE_ULTRA : HCACHE_ANY;
 
524
}
 
525
 
 
526
/*
 
527
 * pcache_clear_recent
 
528
 *
 
529
 * Clear the whole recent pong list.
 
530
 */
 
531
void pcache_clear_recent(hcache_type_t type)
 
532
{
 
533
        GList *l;
 
534
        struct recent *rec;
 
535
 
 
536
        g_assert(type >= 0 && type < HCACHE_MAX);
 
537
 
 
538
        rec = &recent_pongs[type];
 
539
 
 
540
        for (l = rec->recent_pongs; l; l = g_list_next(l)) {
 
541
                struct cached_pong *cp = (struct cached_pong *) l->data;
 
542
 
 
543
                g_hash_table_remove(rec->ht_recent_pongs, cp);
 
544
                free_cached_pong(cp);
 
545
        }
 
546
 
 
547
        g_list_free(rec->recent_pongs);
 
548
        rec->recent_pongs = NULL;
 
549
        rec->last_returned_pong = NULL;
 
550
        rec->recent_pong_count = 0;
 
551
}
 
552
 
 
553
/*
 
554
 * pcache_outgoing_connection
 
555
 *
 
556
 * Called when a new outgoing connection has been made.
 
557
 *
 
558
 * + If we need a connection, or have less than MAX_PONGS entries in our caught
 
559
 *   list, send a ping at normal TTL value.
 
560
 * + Otherwise, send a handshaking ping with TTL=1
 
561
 */
 
562
void pcache_outgoing_connection(struct gnutella_node *n)
 
563
{
 
564
        g_assert(NODE_IS_CONNECTED(n));
 
565
 
 
566
        if (connected_nodes() < up_connections || hcache_is_low(HCACHE_ANY))
 
567
                send_ping(n, my_ttl);           /* Regular ping, get fresh pongs */
 
568
        else
 
569
                send_ping(n, 1);                        /* Handshaking ping */
 
570
}
 
571
 
 
572
/*
 
573
 * pcache_expire
 
574
 *
 
575
 * Expire the whole cache.
 
576
 */
 
577
static void pcache_expire(void)
 
578
{
 
579
        gint i;
 
580
        gint entries = 0;
 
581
 
 
582
        for (i = 0; i < PONG_CACHE_SIZE; i++) {
 
583
                struct cache_line *cl = &pong_cache[i];
 
584
                GSList *sl;
 
585
 
 
586
                for (sl = cl->pongs; sl; sl = g_slist_next(sl)) {
 
587
                        entries++;
 
588
                        free_cached_pong((struct cached_pong *) sl->data);
 
589
                }
 
590
                g_slist_free(cl->pongs);
 
591
 
 
592
                cl->pongs = NULL;
 
593
                cl->cursor = NULL;
 
594
        }
 
595
 
 
596
        if (dbg > 4)
 
597
                printf("Pong CACHE expired (%d entr%s, %d in reserve)\n",
 
598
                        entries, entries == 1 ? "y" : "ies", hcache_size(HCACHE_ANY));
 
599
}
 
600
 
 
601
/*
 
602
 * pcache_close
 
603
 *
 
604
 * Final shutdown.
 
605
 */
 
606
void pcache_close(void)
 
607
{
 
608
        static hcache_type_t types[] = { HCACHE_ANY, HCACHE_ULTRA };
 
609
        gint i;
 
610
 
 
611
        pcache_expire();
 
612
 
 
613
        for (i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
 
614
                hcache_type_t type = types[i];
 
615
 
 
616
                pcache_clear_recent(type);
 
617
                g_hash_table_destroy(recent_pongs[type].ht_recent_pongs);
 
618
        }
 
619
}
 
620
 
 
621
/*
 
622
 * ping_all_neighbours
 
623
 *
 
624
 * Send a ping to all "new" clients to which we are connected, and one to
 
625
 * older client if and only if at least OLD_PING_PERIOD seconds have
 
626
 * elapsed since our last ping, as determined by `next_ping'.
 
627
 */
 
628
static void ping_all_neighbours(time_t now)
 
629
{
 
630
        const GSList *sl;
 
631
        GSList *may_ping = NULL;
 
632
        GSList *to_ping = NULL;
 
633
        gint ping_cnt = 0;
 
634
        gint selected = 0;
 
635
        gint left;
 
636
 
 
637
        /*
 
638
         * Because nowadays the network has a higher outdegree for ultrapeers,
 
639
         * and because of the widespread use of X-Try-Ultrapeers headers, it is
 
640
         * less critical to use pings as a way to collect hosts.
 
641
         *
 
642
         * Therefore, don't ping all neighbours but only UP_PING_RATIO percent
 
643
         * of them, chosen at random, with at least MIN_UP_PING hosts chosen.
 
644
         *
 
645
         *              --RAM, 12/01/2004
 
646
         */
 
647
 
 
648
        for (sl = node_all_nodes(); sl; sl = g_slist_next(sl)) {
 
649
                struct gnutella_node *n = (struct gnutella_node *) sl->data;
 
650
 
 
651
                if (!NODE_IS_WRITABLE(n) || NODE_IS_LEAF(n))
 
652
                        continue;
 
653
 
 
654
                /*
 
655
                 * If node is in TX flow control, we already have problems,
 
656
                 * so don't increase them by sending more pings.
 
657
                 *              --RAM, 19/06/2003
 
658
                 */
 
659
 
 
660
                if (NODE_IN_TX_FLOW_CONTROL(n))
 
661
                        continue;
 
662
 
 
663
                if ((n->attrs & NODE_A_PONG_CACHING) || now > n->next_ping) {
 
664
                        may_ping = g_slist_prepend(may_ping, n);
 
665
                        ping_cnt++;
 
666
                }
 
667
        }
 
668
 
 
669
        for (sl = may_ping, left = ping_cnt; sl; sl = g_slist_next(sl), left--) {
 
670
                struct gnutella_node *n = (struct gnutella_node *) sl->data;
 
671
 
 
672
                if (
 
673
                        ping_cnt <= MIN_UP_PING ||
 
674
                        (selected < MIN_UP_PING && left <= (MIN_UP_PING - selected)) ||
 
675
                        random_value(99) < UP_PING_RATIO 
 
676
                ) {
 
677
                        to_ping = g_slist_prepend(to_ping, n);
 
678
                        selected++;
 
679
                }
 
680
        }
 
681
 
 
682
        for (sl = to_ping; sl; sl = g_slist_next(sl)) {
 
683
                struct gnutella_node *n = (struct gnutella_node *) sl->data;
 
684
 
 
685
                if (!(n->attrs & NODE_A_PONG_CACHING))
 
686
                        n->next_ping = now + OLD_PING_PERIOD;
 
687
 
 
688
                send_ping(n, my_ttl);
 
689
        }
 
690
 
 
691
        g_slist_free(may_ping);
 
692
        g_slist_free(to_ping);
 
693
}
 
694
 
 
695
/*
 
696
 * pcache_possibly_expired
 
697
 *
 
698
 * Check pong cache for expiration.
 
699
 * If expiration time is reached, flush it and ping all our neighbours.
 
700
 */
 
701
void pcache_possibly_expired(time_t now)
 
702
{
 
703
        if (now >= pcache_expire_time) {
 
704
                pcache_expire();
 
705
                pcache_expire_time = now + cache_lifespan(current_peermode);
 
706
                ping_all_neighbours(now);
 
707
        }
 
708
}
 
709
 
 
710
/*
 
711
 * pcache_set_peermode
 
712
 *
 
713
 * Called when peer mode is changed to recompute the pong cache lifetime.
 
714
 */
 
715
void pcache_set_peermode(node_peer_t mode)
 
716
{
 
717
        pcache_expire_time = time(NULL) + cache_lifespan(mode);
 
718
}
 
719
 
 
720
/*
 
721
 * setup_pong_demultiplexing
 
722
 *
 
723
 * Fill ping_guid[] and pong_needed[] arrays in the node from which we just
 
724
 * accepted a ping.
 
725
 *
 
726
 * When we accept a ping from a connection, we don't really relay the ping.
 
727
 * Our cache is filled by the pongs we receive back from our periodic
 
728
 * pinging of the neighbours.
 
729
 *
 
730
 * However, when we get some pongs back, we forward them back to the nodes
 
731
 * for which we have accepted a ping and which still need results, as
 
732
 * determined by pong_needed[] (index by pong hop count).  The saved GUID
 
733
 * of the ping allows us to fake the pong reply, so the sending node recognizes
 
734
 * those as being "his" pongs.
 
735
 */
 
736
static void setup_pong_demultiplexing(
 
737
        struct gnutella_node *n, gchar *muid, guint8 ttl)
 
738
{
 
739
        gint remains;
 
740
        gint h;
 
741
 
 
742
        g_assert(n->header.function == GTA_MSG_INIT);
 
743
 
 
744
        memcpy(n->ping_guid, n->header.muid, 16);
 
745
        memset(n->pong_needed, 0, sizeof(n->pong_needed));
 
746
        n->pong_missing = 0;
 
747
 
 
748
        /*
 
749
         * `ttl' is currently the amount of hops the ping could travel.
 
750
         * If it's 1, it means it would have travelled on host still, and we
 
751
         * would have got a pong back with an hop count of 0.
 
752
         *
 
753
         * Since our pong_needed[] array is indexed by the hop count of pongs,
 
754
         * we need to substract one from the ttl parameter.
 
755
         */
 
756
 
 
757
        if (ttl-- == 0)
 
758
                return;
 
759
 
 
760
        ttl = MIN(ttl, MAX_CACHE_HOPS);         /* We limit the maximum hop count */
 
761
 
 
762
        /*
 
763
         * Now we're going to distribute "evenly" the MAX_PONGS we can return
 
764
         * to this ping accross the (0..ttl) range.  We start by the beginning
 
765
         * of the array to give more weight to high-hops pongs.
 
766
         */
 
767
 
 
768
        n->pong_missing = remains = MAX_PONGS;
 
769
 
 
770
        for (h = 0; h <= MAX_CACHE_HOPS; h++) {
 
771
                guchar amount = (guchar) (remains / (MAX_CACHE_HOPS + 1 - h));
 
772
                n->pong_needed[h] = amount;
 
773
                remains -= amount;
 
774
                if (dbg > 7)
 
775
                        printf("pong_needed[%d] = %d, remains = %d\n", h, amount, remains);
 
776
        }
 
777
 
 
778
        g_assert(remains == 0);
 
779
}
 
780
 
 
781
/*
 
782
 * iterate_on_cached_line
 
783
 *
 
784
 * Internal routine for send_cached_pongs.
 
785
 *
 
786
 * Iterates on a list of cached pongs and send back any pong to node `n'
 
787
 * that did not originate from it.  Update `cursor' in the cached line
 
788
 * to be the address of the last traversed item.
 
789
 *
 
790
 * Return FALSE if we're definitely done, TRUE if we can still iterate.
 
791
 */
 
792
static gboolean iterate_on_cached_line(
 
793
        struct gnutella_node *n, struct cache_line *cl, guint8 ttl,
 
794
        GSList *start, GSList *end, gboolean strict)
 
795
{
 
796
        gint hops = cl->hops;
 
797
        GSList *l;
 
798
 
 
799
        for (l = start; l && l != end && n->pong_missing; l = g_slist_next(l)) {
 
800
                struct cached_pong *cp = (struct cached_pong *) l->data;
 
801
 
 
802
                cl->cursor = l;
 
803
 
 
804
                /*
 
805
                 * We never send a cached pong to the node from which it came along.
 
806
                 *
 
807
                 * The `last_sent_id' trick is used because we're going to iterate
 
808
                 * twice on the cache list: once to send pongs that strictly match
 
809
                 * the hop counts needed, and another time to send pongs as needed,
 
810
                 * more loosely.  The two runs are consecutive, so we're saving in
 
811
                 * each cached entry the node to which we sent it last, so we don't
 
812
                 * resend the same pong twice.
 
813
                 *
 
814
                 * We're only iterating upon reception of the intial ping from the
 
815
                 * node.  After that, we'll send pongs as we receive them, and
 
816
                 * only if they strictly match the needed TTL.
 
817
                 */
 
818
 
 
819
                if (n->id == cp->node_id)
 
820
                        continue;
 
821
                if (n->id == cp->last_sent_id)
 
822
                        continue;
 
823
                cp->last_sent_id = n->id;
 
824
 
 
825
                /*
 
826
                 * When sending a cached pong, don't forget that its cached hop count
 
827
                 * is the one we got when we received it, i.e. hops=0 means a pong
 
828
                 * from one of our immediate neighbours.  However, we're now "routing"
 
829
                 * it, so we must increase the hop count.
 
830
                 */
 
831
 
 
832
                g_assert(hops < 255);           /* Because of MAX_CACHE_HOPS */
 
833
 
 
834
                send_pong(n, FALSE, hops + 1, ttl, n->ping_guid,
 
835
                        cp->ip, cp->port, cp->files_count, cp->kbytes_count);
 
836
 
 
837
                n->pong_missing--;
 
838
 
 
839
                if (dbg > 7)
 
840
                        printf("iterate: sent cached pong %s (hops=%d, TTL=%d) to %s, "
 
841
                                "missing=%d %s\n", ip_port_to_gchar(cp->ip, cp->port),
 
842
                                hops, ttl, node_ip(n), n->pong_missing,
 
843
                                strict ? "STRICT" : "loose");
 
844
 
 
845
                if (strict && --(n->pong_needed[hops]) == 0)
 
846
                        return FALSE;
 
847
 
 
848
                /*
 
849
                 * Node can be removed should its send queue saturate.
 
850
                 */
 
851
 
 
852
                if (!NODE_IS_CONNECTED(n))
 
853
                        return FALSE;
 
854
        }
 
855
 
 
856
        return n->pong_missing != 0;
 
857
}
 
858
 
 
859
/*
 
860
 * send_cached_pongs
 
861
 *
 
862
 * Send pongs from cache line back to node `n' if more are needed for this
 
863
 * hop count and they are not originating from the node.  When `strict'
 
864
 * is false, we send even if no pong at that hop level is needed.
 
865
 */
 
866
static void send_cached_pongs(struct gnutella_node *n,
 
867
        struct cache_line *cl, guint8 ttl, gboolean strict)
 
868
{
 
869
        gint hops = cl->hops;
 
870
        GSList *old = cl->cursor;
 
871
 
 
872
        if (strict && !n->pong_needed[hops])
 
873
                return;
 
874
 
 
875
        /*
 
876
         * We start iterating after `cursor', until the end of the list, at which
 
877
         * time we restart from the beginning until we reach `cursor', included.
 
878
         * When we leave, `cursor' will point to the last traversed item.
 
879
         */
 
880
 
 
881
        if (old) {
 
882
                if (!iterate_on_cached_line(n, cl, ttl, old->next, NULL, strict))
 
883
                        return;
 
884
                (void) iterate_on_cached_line(n, cl, ttl, cl->pongs, old->next, strict);
 
885
        } else
 
886
                (void) iterate_on_cached_line(n, cl, ttl, cl->pongs, NULL, strict);
 
887
}
 
888
 
 
889
/*
 
890
 * pong_all_neighbours_but_one
 
891
 *
 
892
 * We received a pong we cached from `n'.  Send it to all other nodes if
 
893
 * they need one at this hop count.
 
894
 */
 
895
static void pong_all_neighbours_but_one(
 
896
        struct gnutella_node *n, struct cached_pong *cp, hcache_type_t ptype,
 
897
        guint8 hops, guint8 ttl)
 
898
{
 
899
        const GSList *sl;
 
900
 
 
901
        for (sl = node_all_nodes(); sl; sl = g_slist_next(sl)) {
 
902
                struct gnutella_node *cn = (struct gnutella_node *) sl->data;
 
903
 
 
904
                if (cn == n)
 
905
                        continue;
 
906
 
 
907
                if (!NODE_IS_WRITABLE(cn))
 
908
                        continue;
 
909
 
 
910
                /*
 
911
                 * Since we iterate twice initially at ping reception, once strictly
 
912
                 * and the other time loosly, `pong_missing' is always accurate but
 
913
                 * can be different from the sum of `pong_needed[i]', for all `i'.
 
914
                 */
 
915
 
 
916
                if (!cn->pong_missing)
 
917
                        continue;
 
918
 
 
919
                if (!cn->pong_needed[hops])
 
920
                        continue;
 
921
 
 
922
                /*
 
923
                 * If node is a leaf node, we can only send it Ultra pongs.
 
924
                 */
 
925
 
 
926
                if (NODE_IS_LEAF(cn) && ptype != HCACHE_ULTRA)
 
927
                        continue;
 
928
 
 
929
                cn->pong_missing--;
 
930
                cn->pong_needed[hops]--;
 
931
 
 
932
                /*
 
933
                 * When sending a cached pong, don't forget that its cached hop count
 
934
                 * is the one we got when we received it, i.e. hops=0 means a pong
 
935
                 * from one of our immediate neighbours.  However, we're now "routing"
 
936
                 * it, so we must increase the hop count.
 
937
                 */
 
938
 
 
939
                g_assert(hops < 255);
 
940
 
 
941
                send_pong(cn, FALSE, hops + 1, ttl, cn->ping_guid,
 
942
                        cp->ip, cp->port, cp->files_count, cp->kbytes_count);
 
943
 
 
944
                if (dbg > 7)
 
945
                        printf("pong_all: sent cached pong %s (hops=%d, TTL=%d) to %s "
 
946
                                "missing=%d\n", ip_port_to_gchar(cp->ip, cp->port),
 
947
                                hops, ttl, node_ip(cn), cn->pong_missing);
 
948
        }
 
949
}
 
950
 
 
951
/*
 
952
 * pong_random_leaf
 
953
 *
 
954
 * We received an ultra pong.
 
955
 * Send it to one randomly selected leaf, which is not already missing pongs.
 
956
 */
 
957
static void pong_random_leaf(struct cached_pong *cp, guint8 hops, guint8 ttl)
 
958
{
 
959
        const GSList *sl;
 
960
        gint leaves;
 
961
        struct gnutella_node *leaf = NULL;
 
962
 
 
963
        g_assert(current_peermode == NODE_P_ULTRA);
 
964
 
 
965
        for (sl = node_all_nodes(), leaves = 0; sl; sl = g_slist_next(sl)) {
 
966
                struct gnutella_node *cn = (struct gnutella_node *) sl->data;
 
967
                gint threshold;
 
968
 
 
969
                if (cn->pong_missing)   /* A job for pong_all_neighbours_but_one() */
 
970
                        continue;
 
971
 
 
972
                if (!NODE_IS_LEAF(cn))
 
973
                        continue;
 
974
 
 
975
                if (NODE_IN_TX_FLOW_CONTROL(cn))        /* Already overwhelmed */
 
976
                        continue;
 
977
 
 
978
                /*
 
979
                 * Randomly select one leaf.
 
980
                 *
 
981
                 * As we go along, the probability that we retain the current leaf
 
982
                 * decreases.  It is 1 for the first leaf, 1/2 for the second leaf,
 
983
                 * 1/3 for the third leaf, etc...
 
984
                 */
 
985
 
 
986
                leaves++;
 
987
                threshold = (gint) (1000.0 / leaves);
 
988
 
 
989
                if (random_value(999) < threshold)
 
990
                        leaf = cn;
 
991
        }
 
992
 
 
993
        /*
 
994
         * Send the pong to the selected leaf, if any.
 
995
         *
 
996
         * NB: If the leaf never sent a ping before, leaf->ping_guid will
 
997
         * be a zero GUID.  That's OK.
 
998
         */
 
999
 
 
1000
        if (leaf != NULL) {
 
1001
                send_pong(leaf, FALSE, hops + 1, ttl, leaf->ping_guid,
 
1002
                        cp->ip, cp->port, cp->files_count, cp->kbytes_count);
 
1003
 
 
1004
                if (dbg > 7)
 
1005
                        printf("pong_random_leaf: sent pong %s (hops=%d, TTL=%d) to %s\n",
 
1006
                                ip_port_to_gchar(cp->ip, cp->port), hops, ttl, node_ip(leaf));
 
1007
        }
 
1008
}
 
1009
 
 
1010
/*
 
1011
 * record_fresh_pong
 
1012
 *
 
1013
 * Add pong from node `n' to our cache of recent pongs.
 
1014
 * Returns the cached pong object.
 
1015
 */
 
1016
static struct cached_pong *record_fresh_pong(
 
1017
        hcache_type_t type,
 
1018
        struct gnutella_node *n,
 
1019
        guint8 hops, guint32 ip, guint16 port,
 
1020
        guint32 files_count, guint32 kbytes_count)
 
1021
{
 
1022
        struct cache_line *cl;
 
1023
        struct cached_pong *cp;
 
1024
        guint8 hop;
 
1025
 
 
1026
        g_assert(type >= 0 && type < HCACHE_MAX);
 
1027
 
 
1028
        cp = (struct cached_pong *) walloc(sizeof(struct cached_pong));
 
1029
 
 
1030
        cp->refcount = 1;
 
1031
        cp->node_id = n->id;
 
1032
        cp->last_sent_id = n->id;
 
1033
        cp->ip = ip;
 
1034
        cp->port = port;
 
1035
        cp->files_count = files_count;
 
1036
        cp->kbytes_count = kbytes_count;
 
1037
 
 
1038
        hop = CACHE_HOP_IDX(hops);              /* Trim high values to MAX_CACHE_HOPS */
 
1039
        cl = &pong_cache[hop];
 
1040
        cl->pongs = g_slist_append(cl->pongs, cp);
 
1041
        add_recent_pong(type, cp);
 
1042
 
 
1043
        return cp;
 
1044
}
 
1045
 
 
1046
/*
 
1047
 * pcache_ping_received
 
1048
 *
 
1049
 * Called when a ping is received from a node.
 
1050
 *
 
1051
 * + If current time is less than what `ping_accept' says, drop the ping.
 
1052
 *   Otherwise, accept the ping and increment `ping_accept' by n->ping_throttle.
 
1053
 * + If cache expired, call pcache_expire() and broadcast a new ping to all
 
1054
 *   the "new" clients (i.e. those flagged NODE_A_PONG_CACHING).  For "old"
 
1055
 *   clients, do so only if "next_ping" time was reached.
 
1056
 * + Handle "alive" pings (TTL=1) and "crawler" pings (TTL=2) immediately,
 
1057
 *   then return.
 
1058
 * + Setup pong demultiplexing tables, recording the fact that  the node needs
 
1059
 *   to be sent pongs as we receive them.
 
1060
 * + Return a pong for us if we accept incoming connections right now.
 
1061
 * + Return cached pongs, avoiding to resend a pong coming from that node ID.
 
1062
 */
 
1063
void pcache_ping_received(struct gnutella_node *n)
 
1064
{
 
1065
        time_t now = time((time_t *) 0);
 
1066
        gint h;
 
1067
        guint8 ttl;
 
1068
 
 
1069
        g_assert(NODE_IS_CONNECTED(n));
 
1070
 
 
1071
        /*
 
1072
         * Handle "alive" pings and "crawler" pings specially.
 
1073
         * Besides, we always accept them.
 
1074
         */
 
1075
 
 
1076
        if (n->header.hops == 0 && n->header.ttl <= 2) {
 
1077
                n->n_ping_special++;
 
1078
                if (n->header.ttl == 1)
 
1079
                        send_personal_info(n, TRUE);    /* Control message, prioritary */
 
1080
                else if (n->header.ttl == 2) {
 
1081
                        if (current_peermode != NODE_P_LEAF)
 
1082
                                send_neighbouring_info(n);
 
1083
                } else
 
1084
                        node_sent_ttl0(n);
 
1085
                return;
 
1086
        }
 
1087
 
 
1088
        /*
 
1089
         * If we get a ping with hops != 0 from a host that claims to
 
1090
         * implement ping/pong reduction, then they are not playing
 
1091
         * by the same rules as we are.  Emit a warning.
 
1092
         *              --RAM, 03/03/2001
 
1093
         */
 
1094
 
 
1095
        if (
 
1096
                n->header.hops &&
 
1097
                (n->attrs & (NODE_A_PONG_CACHING|NODE_A_PONG_ALIEN)) ==
 
1098
                        NODE_A_PONG_CACHING
 
1099
        ) {
 
1100
                if (dbg)
 
1101
                        g_warning("node %s (%s) [%d.%d] claimed ping reduction, "
 
1102
                                "got ping with hops=%d", node_ip(n),
 
1103
                                node_vendor(n),
 
1104
                                n->proto_major, n->proto_minor, n->header.hops);
 
1105
                n->attrs |= NODE_A_PONG_ALIEN;          /* Warn only once */
 
1106
        }
 
1107
 
 
1108
        /*
 
1109
         * Accept the ping?.
 
1110
         */
 
1111
 
 
1112
        if (now < n->ping_accept) {
 
1113
                n->n_ping_throttle++;           /* Drop the ping */
 
1114
                n->rx_dropped++;
 
1115
        gnet_stats_count_dropped(n, MSG_DROP_THROTTLE);
 
1116
                return;
 
1117
        } else {
 
1118
                n->n_ping_accepted++;
 
1119
                n->ping_accept = now + n->ping_throttle;        /* Drop all until then */
 
1120
        }
 
1121
 
 
1122
        /*
 
1123
         * Purge cache if needed.
 
1124
         */
 
1125
 
 
1126
        pcache_possibly_expired(now);
 
1127
 
 
1128
        if (!NODE_IS_CONNECTED(n))              /* Can be removed if send queue is full */
 
1129
                return;
 
1130
 
 
1131
        /*
 
1132
         * If TTL = 0, only us can reply, and we'll do that below in any case..
 
1133
         * We call setup_pong_demultiplexing() anyway to reset the pong_needed[]
 
1134
         * array.
 
1135
         *
 
1136
         * A leaf node will not demultiplex pongs, so don't bother.
 
1137
         */
 
1138
 
 
1139
        if (current_peermode != NODE_P_LEAF)
 
1140
                setup_pong_demultiplexing(n, n->header.muid, n->header.ttl);
 
1141
 
 
1142
        /*
 
1143
         * If we can accept an incoming connection, send a reply.
 
1144
         *
 
1145
         * If we are firewalled, we nonetheless send a ping
 
1146
         * when inet_can_answer_ping() tells us we can, irrespective
 
1147
         * of whether we can accept a new node connection: the aim is
 
1148
         * to trigger an incoming connection that will prove us we're
 
1149
         * not firewalled.
 
1150
         */
 
1151
 
 
1152
        if (
 
1153
                (is_firewalled || node_missing() > 0) && inet_can_answer_ping()
 
1154
        ) {
 
1155
                send_personal_info(n, FALSE);
 
1156
                if (!NODE_IS_CONNECTED(n))      /* Can be removed if send queue is full */
 
1157
                        return;
 
1158
        }
 
1159
 
 
1160
        if (current_peermode == NODE_P_LEAF)
 
1161
                return;
 
1162
 
 
1163
        /*
 
1164
         * We continue here only for non-leaf nodes.
 
1165
         */
 
1166
 
 
1167
        /*
 
1168
         * Return cached pongs if we have some and they are needed.
 
1169
         * We first try to send pongs on a per-hop basis, based on pong_needed[].
 
1170
         */
 
1171
 
 
1172
        ttl = MIN(n->header.hops + 1, max_ttl);
 
1173
 
 
1174
        for (h = 0; n->pong_missing && h < n->header.ttl; h++) {
 
1175
                struct cache_line *cl = &pong_cache[CACHE_HOP_IDX(h)];
 
1176
 
 
1177
                if (cl->pongs) {
 
1178
                        send_cached_pongs(n, cl, ttl, TRUE);
 
1179
                        if (!NODE_IS_CONNECTED(n))
 
1180
                                return;
 
1181
                }
 
1182
        }
 
1183
 
 
1184
        /*
 
1185
         * We then re-iterate if some pongs are still needed, sending any we
 
1186
         * did not already send.
 
1187
         */
 
1188
 
 
1189
        for (h = 0; n->pong_missing && h < n->header.ttl; h++) {
 
1190
                struct cache_line *cl = &pong_cache[CACHE_HOP_IDX(h)];
 
1191
 
 
1192
                if (cl->pongs) {
 
1193
                        send_cached_pongs(n, cl, ttl, FALSE);
 
1194
                        if (!NODE_IS_CONNECTED(n))
 
1195
                                return;
 
1196
                }
 
1197
        }
 
1198
}
 
1199
 
 
1200
/*
 
1201
 * pcache_pong_received
 
1202
 *
 
1203
 * Called when a pong is received from a node.
 
1204
 *
 
1205
 * + Record node in the main host catching list.
 
1206
 * + If node is not a "new" client (i.e. flagged as NODE_A_PONG_CACHING),
 
1207
 *   cache randomly OLD_CACHE_RATIO percent of those (older clients need
 
1208
 *   to be able to get incoming connections as well).
 
1209
 * + Cache pong in the pong.hops cache line, associated with the node ID (so we
 
1210
 *   never send back this entry to the node).
 
1211
 * + For all nodes but `n', propagate pong if neeed, with demultiplexing.
 
1212
 */
 
1213
void pcache_pong_received(struct gnutella_node *n)
 
1214
{
 
1215
        guint32 ip;
 
1216
        guint16 port;
 
1217
        guint32 files_count;
 
1218
        guint32 kbytes_count;
 
1219
        struct cached_pong *cp;
 
1220
        hcache_type_t ptype;
 
1221
 
 
1222
        n->n_pong_received++;
 
1223
 
 
1224
        /*
 
1225
         * Decompile the pong information.
 
1226
         */
 
1227
 
 
1228
        READ_GUINT16_LE(n->data, port);
 
1229
        READ_GUINT32_BE(n->data + 2, ip);
 
1230
        READ_GUINT32_LE(n->data + 6, files_count);
 
1231
        READ_GUINT32_LE(n->data + 10, kbytes_count);
 
1232
 
 
1233
        /*
 
1234
         * Handle replies from our neighbours specially
 
1235
         */
 
1236
 
 
1237
        if (n->header.hops == 0) {
 
1238
                /*
 
1239
                 * For an incoming connection, we might not know the GNet IP address
 
1240
                 * of the remote node yet (we know the remote endpoint, but it could
 
1241
                 * be a proxy for a firewalled node).  The information from the pong
 
1242
                 * may help us fill this gap.
 
1243
                 */
 
1244
 
 
1245
                if (n->gnet_ip == 0 && (n->flags & NODE_F_INCOMING)) {
 
1246
                        if (ip == n->ip) {
 
1247
                                n->gnet_ip = ip;                /* Signals: we have figured it out */
 
1248
                                n->gnet_port = port;
 
1249
                        } else if (!(n->flags & NODE_F_ALIEN_IP)) {
 
1250
                                if (dbg) g_warning(
 
1251
                                        "node %s (%s) sent us a pong for itself with alien IP %s",
 
1252
                                        node_ip(n), node_vendor(n), ip_to_gchar(ip));
 
1253
                                n->flags |= NODE_F_ALIEN_IP;    /* Probably firewalled */
 
1254
                        }
 
1255
                }
 
1256
 
 
1257
                /*
 
1258
                 * Only record library stats for the node if it is the first pong
 
1259
                 * we receive from it (likely to be a reply to our handshaking ping)
 
1260
                 * or if it comes from the node's IP.
 
1261
                 * Indeed, LimeWire suffers from a bug where it will forward foreign
 
1262
                 * pongs with hops=0 even though they are not coming from the node.
 
1263
                 *              --RAM, 11/01/2004.
 
1264
                 */
 
1265
 
 
1266
                if (n->n_pong_received == 1 || ip == n->gnet_ip) {
 
1267
                        n->gnet_files_count = files_count;
 
1268
                        n->gnet_kbytes_count = kbytes_count;
 
1269
                }
 
1270
 
 
1271
                /*
 
1272
                 * Spot any change in the pong's IP address.  We try to avoid messages
 
1273
                 * about "connection pongs" by checking whether we have sent at least
 
1274
                 * 2 pings (one handshaking ping plus one another).
 
1275
                 */
 
1276
 
 
1277
                if (n->gnet_pong_ip && ip != n->gnet_pong_ip) {
 
1278
                        if (dbg && n->n_ping_sent > 2) g_warning(
 
1279
                                "node %s (%s) sent us a pong for new IP %s (used %s before)",
 
1280
                                node_ip(n), node_vendor(n),
 
1281
                                ip_port_to_gchar(ip, port), ip_to_gchar(n->gnet_pong_ip));
 
1282
                }
 
1283
 
 
1284
                n->gnet_pong_ip = ip;
 
1285
 
 
1286
                /*
 
1287
                 * If it was an acknowledge for one of our alive pings, don't cache.
 
1288
                 */
 
1289
 
 
1290
                if (alive_ack_ping(n->alive_pings, n->header.muid))
 
1291
                        return;
 
1292
        }
 
1293
 
 
1294
        /*
 
1295
         * If it's not a connectible pong, discard it.
 
1296
         */
 
1297
 
 
1298
        if (!host_is_valid(ip, port)) {
 
1299
                gnet_stats_count_dropped(n, MSG_DROP_PONG_UNUSABLE);
 
1300
                return;
 
1301
        }
 
1302
 
 
1303
        /*
 
1304
         * If pong points to an hostile IP address, discard it.
 
1305
         */
 
1306
 
 
1307
        if (hostiles_check(ip)) {
 
1308
                gnet_stats_count_dropped(n, MSG_DROP_HOSTILE_IP);
 
1309
                return;
 
1310
        }
 
1311
 
 
1312
        /*
 
1313
         * If pong points to us, maybe we explicitly connected to ourselves
 
1314
         * (tests) or someone is trying to fool us.
 
1315
         */
 
1316
 
 
1317
        if (ip == listen_ip() && port == listen_port)
 
1318
                return;
 
1319
 
 
1320
        /*
 
1321
         * Add pong to our reserve, and possibly try to connect.
 
1322
         */
 
1323
 
 
1324
        host_add(ip, port, TRUE);
 
1325
 
 
1326
        /*
 
1327
         * If we got a pong from an "old" client, cache OLD_CACHE_RATIO of
 
1328
         * its pongs, randomly.  Returning from this routine means we won't
 
1329
         * cache it.
 
1330
         */
 
1331
 
 
1332
        if (!(n->attrs & NODE_A_PONG_CACHING)) {
 
1333
                gint ratio = (gint) random_value(100);
 
1334
                if (ratio >= OLD_CACHE_RATIO) {
 
1335
                        if (dbg > 7)
 
1336
                                printf("NOT CACHED pong %s (hops=%d, TTL=%d) from OLD %s\n",
 
1337
                                        ip_port_to_gchar(ip, port), n->header.hops, n->header.ttl,
 
1338
                                        node_ip(n));
 
1339
                        return;
 
1340
                }
 
1341
        }
 
1342
 
 
1343
        /*
 
1344
         * Insert pong within our cache.
 
1345
         */
 
1346
 
 
1347
        ptype = pong_type((struct gnutella_init_response *) n->data);
 
1348
 
 
1349
        cp = record_fresh_pong(HCACHE_ANY, n, n->header.hops, ip, port,
 
1350
                files_count, kbytes_count);
 
1351
 
 
1352
        if (ptype == HCACHE_ULTRA)
 
1353
                (void) record_fresh_pong(HCACHE_ULTRA, n, n->header.hops, ip, port,
 
1354
                        files_count, kbytes_count);
 
1355
 
 
1356
        if (dbg > 6)
 
1357
                printf("CACHED %s pong %s (hops=%d, TTL=%d) from %s %s\n",
 
1358
                        ptype == HCACHE_ULTRA ? "ultra" : "normal",
 
1359
                        ip_port_to_gchar(ip, port), n->header.hops, n->header.ttl,
 
1360
                        (n->attrs & NODE_A_PONG_CACHING) ? "NEW" : "OLD", node_ip(n));
 
1361
 
 
1362
        /*
 
1363
         * Demultiplex pong: send it to all the connections but the one we
 
1364
         * received it from, provided they need more pongs of this hop count.
 
1365
         */
 
1366
 
 
1367
        if (current_peermode != NODE_P_LEAF)
 
1368
                pong_all_neighbours_but_one(n,
 
1369
                        cp, ptype, CACHE_HOP_IDX(n->header.hops), MAX(1, n->header.ttl));
 
1370
 
 
1371
        /*
 
1372
         * If we're in ultra mode, send 33% of all the ultra pongs we get
 
1373
         * to one random leaf.
 
1374
         */
 
1375
 
 
1376
        if (
 
1377
                current_peermode == NODE_P_ULTRA &&
 
1378
                ptype == HCACHE_ULTRA && random_value(99) < 33
 
1379
        )
 
1380
                pong_random_leaf(
 
1381
                        cp, CACHE_HOP_IDX(n->header.hops), MAX(1, n->header.ttl));
 
1382
}
 
1383
 
 
1384
/*
 
1385
 * pcache_pong_fake
 
1386
 *
 
1387
 * Fake a pong for a node from which we received an incoming connection,
 
1388
 * using the supplied IP/port.
 
1389
 *
 
1390
 * This pong is not multiplexed to neighbours, but is used to populate our
 
1391
 * cache, so we can return its address to others, assuming that if it is
 
1392
 * making an incoming connection to us, it is really in need for other
 
1393
 * connections as well.
 
1394
 */
 
1395
void pcache_pong_fake(struct gnutella_node *n, guint32 ip, guint16 port)
 
1396
{
 
1397
        if (!host_is_valid(ip, port))
 
1398
                return;
 
1399
 
 
1400
        host_add(ip, port, FALSE);
 
1401
        (void) record_fresh_pong(HCACHE_ANY, n, 1, ip, port, 0, 0);
 
1402
}
 
1403
 
 
1404
/* vi: set ts=4: */
 
1405