#include "common.h"
#include "gnutella.h"
#include "downloads.h"
#include "uploads.h"
#include "dmesh.h"
#include "huge.h"
#include "http.h"
#include "hostiles.h"
#include "guid.h"
#include "share.h"
#include "fileinfo.h"
#include "settings.h"
#include "hosts.h"
#include "if/gnet_property_priv.h"
#include "lib/atoms.h"
#include "lib/base32.h"
#include "lib/cq.h"
#include "lib/endian.h"
#include "lib/file.h"
#include "lib/getdate.h"
#include "lib/glib-missing.h"
#include "lib/hashlist.h"
#include "lib/header.h"
#include "lib/tm.h"
#include "lib/url.h"
#include "lib/urn.h"
#include "lib/walloc.h"
#include "lib/override.h"
Data Structures | |
| struct | dmesh |
| struct | dmesh_entry |
| struct | dmesh_banned |
Defines | |
| #define | MAX_LIFETIME 86400 |
| 1 day | |
| #define | MAX_ENTRIES 256 |
| Max amount of entries kept per SHA1. | |
| #define | MIN_PFSP_SIZE 524288 |
| 512K, min size for PFSP advertising | |
| #define | MIN_PFSP_PCT 10 |
| 10%, min available data for PFSP | |
| #define | MIN_BAD_REPORT 2 |
| Don't ban before that many X-Nalt. | |
| #define | BAN_LIFETIME 7200 |
| 2 hours | |
| #define | DMESH_MAX MAX_ENTRIES |
Typedefs | |
| typedef void(* | dmesh_add_cb )(const struct sha1 *sha1, host_addr_t addr, guint16 port, gpointer udata) |
| typedef void(* | header_func_t )(FILE *out) |
Functions | |
| void | dmesh_retrieve (void) |
| Retrieve download mesh and add entries that have not expired yet. | |
| void | dmesh_ban_retrieve (void) |
| Retrieve banned mesh and add entries that have not expired yet. | |
| gchar * | dmesh_urlinfo_to_string (const dmesh_urlinfo_t *info) |
| Format the `info' URL and return pointer to static string. | |
| guint | urlinfo_hash (gconstpointer key) |
| Hash a URL info. | |
| gint | urlinfo_eq (gconstpointer a, gconstpointer b) |
| Test equality of two URL infos. | |
| void | dmesh_init (void) |
| Initialize the download mesh. | |
| void | dmesh_entry_free (struct dmesh_entry *dme) |
| Free download mesh entry. | |
| void | dmesh_fill_info (dmesh_urlinfo_t *info, const struct sha1 *sha1, const host_addr_t addr, guint16 port, guint idx, const gchar *name) |
| Fill URL info from externally supplied sha1, addr, port, idx and name. | |
| void | dmesh_urlinfo_free (dmesh_urlinfo_t *info) |
| Free a dmesh_urlinfo_t structure. | |
| void | dmesh_ban_remove_entry (struct dmesh_banned *dmb) |
| Remove entry from banned mesh. | |
| void | dmesh_ban_expire (cqueue_t *unused_cq, gpointer obj) |
| Called from callout queue when it's time to expire the URL ban. | |
| void | dmesh_ban_add (const struct sha1 *sha1, dmesh_urlinfo_t *info, time_t stamp) |
| Add new URL to the banned hash. | |
| void | dmesh_ban_remove (const struct sha1 *sha1, host_addr_t addr, guint16 port) |
| Forcefully remove an entry from the banned mesh. | |
| gboolean | dmesh_is_banned (const dmesh_urlinfo_t *info) |
| Check whether URL is banned from the mesh. | |
| const gchar * | dmesh_url_strerror (dmesh_url_error_t errnum) |
| gboolean | dmesh_url_parse (const gchar *url, dmesh_urlinfo_t *info) |
| Parse URL `url', and fill a structure `info' representing this URL. | |
| dmesh * | dm_alloc (const struct sha1 *sha1) |
| Allocate a new download mesh structure (there is one per SHA1). | |
| void | dm_free (struct dmesh *dm) |
| Free download mesh structure. | |
| void | dm_remove_entry (struct dmesh *dm, struct dmesh_entry *dme) |
| Remove specified entry from mesh bucket and reclaim it. | |
| void | dm_remove (struct dmesh *dm, const host_addr_t addr, guint16 port) |
| Remove the addr:port entry from mesh bucket, if present. | |
| void | dm_expire (struct dmesh *dm, glong agemax) |
| Expire entries older than `agemax' in a given mesh bucket `dm'. | |
| void | dmesh_dispose (const struct sha1 *sha1) |
| Dispose of the entry slot, which must be empty. | |
| gboolean | dmesh_remove (const struct sha1 *sha1, const host_addr_t addr, guint16 port, guint idx, const gchar *name) |
| Remove entry from mesh due to a failed download attempt. | |
| gint | dmesh_count (const struct sha1 *sha1) |
| Get the number of dmesh entries for a given SHA1. | |
| gboolean | dmesh_raw_add (const struct sha1 *sha1, const dmesh_urlinfo_t *info, time_t stamp) |
| Add entry to the download mesh, indexed by the binary `sha1' digest. | |
| gboolean | dmesh_add (const struct sha1 *sha1, const host_addr_t addr, guint16 port, guint idx, const gchar *name, time_t stamp) |
| Same as dmesh_raw_add(), but this is for public consumption. | |
| void | dmesh_add_alternate (const struct sha1 *sha1, host_addr_t addr, guint16 port) |
| Add addr:port as a known alternate location for given sha1. | |
| void | dmesh_add_good_alternate (const struct sha1 *sha1, host_addr_t addr, guint16 port) |
| void | dmesh_add_alternates (const struct sha1 *sha1, const gnet_host_vec_t *alt) |
| Add a set of alternate locations (IP + port) to the mesh. | |
| void | dmesh_remove_alternate (const struct sha1 *sha1, host_addr_t addr, guint16 port) |
| Remove addr:port as a known alternate location for given sha1. | |
| void | dmesh_negative_alt (const struct sha1 *sha1, host_addr_t reporter, host_addr_t addr, guint16 port) |
| Record that addr:port was signalled negatively as an alternate location for given sha1. | |
| void | dmesh_good_mark (const struct sha1 *sha1, host_addr_t addr, guint16 port, gboolean good) |
| Flag dmesh entry for this SHA1, address and port as good or bad. | |
| size_t | dmesh_urlinfo (const dmesh_urlinfo_t *info, gchar *buf, size_t len, gboolean *quoting) |
| Format the URL described by `info' into the provided buffer `buf', which can hold `len' bytes. | |
| size_t | dmesh_entry_compact (const struct dmesh_entry *dme, gchar *buf, size_t size) |
| Format mesh_entry in the provided buffer, as a compact addr:port address. | |
| size_t | dmesh_entry_url_stamp (const struct dmesh_entry *dme, gchar *buf, size_t size) |
| Format dmesh_entry in the provided buffer, as an URL with an appended timestamp in ISO format, GMT time. | |
| const gchar * | dmesh_entry_to_string (const struct dmesh_entry *dme) |
| Format the `dme' mesh entry as "URL timestamp". | |
| gint | dmesh_fill_alternate (const struct sha1 *sha1, gnet_host_t *hvec, gint hcnt) |
| Fill supplied vector `hvec' whose size is `hcnt' with some alternate locations for a given SHA1 key, that can be requested by hash directly. | |
| gint | dmesh_alternate_location (const struct sha1 *sha1, gchar *buf, size_t size, const host_addr_t addr, time_t last_sent, const gchar *vendor, fileinfo_t *fi, gboolean request) |
| Build alternate location header for a given SHA1 key. | |
| gboolean | dmesh_collect_sha1 (const gchar *value, struct sha1 *sha1) |
| Parse the value of the X-Gnutella-Content-URN header in `value', looking for a SHA1. | |
| void | dmesh_parse_addr_port_list (const struct sha1 *sha1, const gchar *value, dmesh_add_cb func, gpointer udata) |
| Parse a list of addr:port, such as typically found in "X-Alt" or "X-Nalt" headers to extract alternate sources. | |
| void | dmesh_collect_compact_locations_cback (const struct sha1 *sha1, host_addr_t addr, guint16 port, gpointer unused_udata) |
| void | dmesh_collect_compact_locations (const struct sha1 *sha1, const gchar *value) |
| Parse the value of the "X-Alt" header to extract alternate sources for a given SHA1 key given in the new compact form. | |
| void | dmesh_collect_negative_locations_cback (const struct sha1 *sha1, host_addr_t addr, guint16 port, gpointer udata) |
| void | dmesh_collect_negative_locations (const struct sha1 *sha1, const gchar *value, host_addr_t reporter) |
| Parse the value of the "X-Nalt" header to extract bad sources for a given SHA1 key, given in the new compact form. | |
| void | dmesh_collect_locations (const struct sha1 *sha1, const gchar *value) |
| Parse value of the "X-Gnutella-Alternate-Location" to extract alternate sources for a given SHA1 key. | |
| gint | dmesh_alt_loc_fill (const struct sha1 *sha1, dmesh_urlinfo_t *buf, gint count) |
| Fill buffer with at most `count' alternative locations for sha1. | |
| void | dmesh_check_results_set (gnet_results_set_t *rs) |
| Parse query hit (result set) for entries whose SHA1 match something we have into the mesh or share, and insert them if needed. | |
| void | dmesh_multiple_downloads (const struct sha1 *sha1, filesize_t size, fileinfo_t *fi) |
| This is called when swarming is first requested to get a list of all the servers with the requested file known by dmesh. | |
| void | dmesh_store_kv (gpointer key, gpointer value, gpointer udata) |
| Store key/value pair in file. | |
| void | dmesh_store_hash (const gchar *what, GHashTable *hash, const gchar *file, header_func_t header_cb, GHFunc store_cb) |
| Store hash table `hash' into `file'. | |
| void | dmesh_header_print (FILE *out) |
| Prints header to dmesh store file. | |
| void | dmesh_store (void) |
| Store download mesh onto file. | |
| void | dmesh_ban_store_kv (gpointer key, gpointer value, gpointer udata) |
| Store key/value pair in file. | |
| void | dmesh_ban_header_print (FILE *out) |
| Prints header to banned mesh store file. | |
| void | dmesh_ban_store (void) |
| Store banned mesh onto file. | |
| gboolean | dmesh_free_kv (gpointer key, gpointer value, gpointer unused_udata) |
| Free key/value pair in download mesh hash. | |
| void | dmesh_ban_prepend_list (gpointer key, gpointer value, gpointer user) |
| Prepend the value to the list, given by reference. | |
| void | dmesh_close (void) |
| Called at servent shutdown time. | |
Variables | |
| dmesh_url_error_t | dmesh_url_errno |
| Error from dmesh_url_parse(). | |
| GHashTable * | mesh = NULL |
| The download mesh records all the known sources for a given SHA1. | |
| const gchar | dmesh_file [] = "dmesh" |
| GHashTable * | ban_mesh = NULL |
| If we get a "bad" URL into the mesh ("bad" = gives 404 or other error when trying to download it), we must remember it for some time and prevent it from re-entering the mesh again within that period to prevent rescheduling for download and a further failure: that would be hammering the poor host, and we're wasting our time and bandwidth. | |
| GHashTable * | ban_mesh_by_sha1 = NULL |
| This table stores the banned entries by SHA1. | |
| const gchar | dmesh_ban_file [] = "dmesh_ban" |
| const gchar *const | parse_errstr [] |
|
|
2 hours
|
|
|
|
|
|
Max amount of entries kept per SHA1.
|
|
|
1 day
|
|
|
Don't ban before that many X-Nalt.
|
|
|
10%, min available data for PFSP
|
|
|
512K, min size for PFSP advertising
|
|
|
|
|
|
|
|
|
Allocate a new download mesh structure (there is one per SHA1).
|
|
||||||||||||
|
Expire entries older than `agemax' in a given mesh bucket `dm'.
|
|
|
Free download mesh structure.
|
|
||||||||||||||||
|
Remove the addr:port entry from mesh bucket, if present.
|
|
||||||||||||
|
Remove specified entry from mesh bucket and reclaim it.
|
|
||||||||||||||||||||||||||||
|
Same as dmesh_raw_add(), but this is for public consumption.
|
|
||||||||||||||||
|
Add addr:port as a known alternate location for given sha1.
|
|
||||||||||||
|
Add a set of alternate locations (IP + port) to the mesh.
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
Fill buffer with at most `count' alternative locations for sha1.
|
|
||||||||||||||||||||||||||||||||||||
|
Build alternate location header for a given SHA1 key. We generate at most `size' bytes of data into `alt'.
|
|
||||||||||||||||
|
Add new URL to the banned hash. If stamp is 0, the current timestamp is used. |
|
||||||||||||
|
Called from callout queue when it's time to expire the URL ban.
|
|
|
Prints header to banned mesh store file.
|
|
||||||||||||||||
|
Prepend the value to the list, given by reference.
|
|
||||||||||||||||
|
Forcefully remove an entry from the banned mesh.
|
|
|
Remove entry from banned mesh.
|
|
|
Retrieve banned mesh and add entries that have not expired yet. The mesh is normally retrieved from ~/.gtk-gnutella/dmesh_ban. |
|
|
Store banned mesh onto file. The banned mesh is normally stored in ~/.gtk-gnutella/dmesh_ban. |
|
||||||||||||||||
|
Store key/value pair in file.
|
|
|
Parse query hit (result set) for entries whose SHA1 match something we have into the mesh or share, and insert them if needed.
|
|
|
Called at servent shutdown time.
|
|
||||||||||||
|
Parse the value of the "X-Alt" header to extract alternate sources for a given SHA1 key given in the new compact form.
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
Parse value of the "X-Gnutella-Alternate-Location" to extract alternate sources for a given SHA1 key.
|
|
||||||||||||||||
|
Parse the value of the "X-Nalt" header to extract bad sources for a given SHA1 key, given in the new compact form.
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
Parse the value of the X-Gnutella-Content-URN header in `value', looking for a SHA1. When found, the SHA1 is extracted and placed into the given `digest' buffer.
|
|
|
Get the number of dmesh entries for a given SHA1.
|
|
|
Dispose of the entry slot, which must be empty.
|
|
||||||||||||||||
|
Format mesh_entry in the provided buffer, as a compact addr:port address. The port is even omitted if it is the standard Gnutella one.
|
|
|
Free download mesh entry.
|
|
|
Format the `dme' mesh entry as "URL timestamp".
|
|
||||||||||||||||
|
Format dmesh_entry in the provided buffer, as an URL with an appended timestamp in ISO format, GMT time.
|
|
||||||||||||||||
|
Fill supplied vector `hvec' whose size is `hcnt' with some alternate locations for a given SHA1 key, that can be requested by hash directly.
|
|
||||||||||||||||||||||||||||
|
Fill URL info from externally supplied sha1, addr, port, idx and name. If sha1 is NULL, we use the name, otherwise the urn:sha1. WARNING: fills structure with pointers to static data. |
|
||||||||||||||||
|
Free key/value pair in download mesh hash.
|
|
||||||||||||||||||||
|
Flag dmesh entry for this SHA1, address and port as good or bad.
|
|
|
Prints header to dmesh store file.
|
|
|
Initialize the download mesh.
|
|
|
Check whether URL is banned from the mesh.
|
|
||||||||||||||||
|
This is called when swarming is first requested to get a list of all the servers with the requested file known by dmesh. It creates a new download for every server found.
|
|
||||||||||||||||||||
|
Record that addr:port was signalled negatively as an alternate location for given sha1. The reporter's address is also given so that we can wait until we have sufficient evidence from at least 2 different parties. When there is sufficient evidence, the entry is evicted from the mesh and placed into the banned mesh. |
|
||||||||||||||||||||
|
Parse a list of addr:port, such as typically found in "X-Alt" or "X-Nalt" headers to extract alternate sources. For each value found, invoke the supplied callback `func' as: func(sha1, addr, port, udata); where udata is opaque user-supplied data. |
|
||||||||||||||||
|
Add entry to the download mesh, indexed by the binary `sha1' digest. If `stamp' is 0, then the current time is used. If `idx' is URN_INDEX, then we can access this file only through an /uri-res request, the URN being given as `name'.
|
|
||||||||||||||||||||||||
|
Remove entry from mesh due to a failed download attempt.
|
|
||||||||||||||||
|
Remove addr:port as a known alternate location for given sha1. This inserts the location into the banned mesh. |
|
|
Retrieve download mesh and add entries that have not expired yet. The mesh is normally retrieved from ~/.gtk-gnutella/dmesh. |
|
|
Store download mesh onto file. The download mesh is normally stored in ~/.gtk-gnutella/dmesh. |
|
||||||||||||||||||||||||
|
Store hash table `hash' into `file'. The file header is emitted by `header_cb'. The storing callback for each item is `store_cb'. |
|
||||||||||||||||
|
Store key/value pair in file.
|
|
||||||||||||
|
Parse URL `url', and fill a structure `info' representing this URL.
|
|
|
|
|
||||||||||||||||||||
|
Format the URL described by `info' into the provided buffer `buf', which can hold `len' bytes.
|
|
|
Free a dmesh_urlinfo_t structure.
|
|
|
Format the `info' URL and return pointer to static string.
|
|
||||||||||||
|
Test equality of two URL infos.
|
|
|
Hash a URL info.
|
|
|
If we get a "bad" URL into the mesh ("bad" = gives 404 or other error when trying to download it), we must remember it for some time and prevent it from re-entering the mesh again within that period to prevent rescheduling for download and a further failure: that would be hammering the poor host, and we're wasting our time and bandwidth. Therefore, each time we get a "bad" URL, we insert it in a hash table. The table entry is then scheduled to be removed after some grace period occurs. The table is keyed by the dmesh_urlinfo_t, and points to a dmesh_banned structure. The table is persisted at regular intervals. |
|
|
This table stores the banned entries by SHA1.
|
|
|
|
|
|
|
|
|
Error from dmesh_url_parse().
|
|
|
The download mesh records all the known sources for a given SHA1. It is implemented as a big hash table, where SHA1 are keys, each value being a struct dmesh pointer. |
|
|
Initial value: {
"OK",
"HTTP parsing error",
"File prefix neither /uri-res nor /get",
"Index in /get/index is reserved",
"No filename after /get/index",
"Bad URL encoding",
"Malformed /uri-res/N2R?",
}
|
1.3.9.1