summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-12-04 00:58:57 +0100
committerCoren[m] <Break@Ocean>2013-12-08 05:43:24 +0100
commitad9d20c08b59af8d07b646334fd07cbfcad15663 (patch)
treec80a249d74a2c31e5c2491571c31edbe6680ccfe /toxcore
parent632e69257731bf2be5bd6c444f096098e0d5d2c8 (diff)
do_Assoc(): keep the data of the buckets somewhat current
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c9
-rw-r--r--toxcore/DHT.h2
-rw-r--r--toxcore/assoc.c112
-rw-r--r--toxcore/assoc.h7
4 files changed, 130 insertions, 0 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index e7020a05..b07f2003 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -663,6 +663,11 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
663 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); 663 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data));
664} 664}
665 665
666void DHT_getnodes(DHT *dht, IP_Port *from_ipp, uint8_t *from_id, uint8_t *which_id)
667{
668 getnodes(dht, *from_ipp, from_id, which_id);
669}
670
666/* Send a send nodes response. */ 671/* Send a send nodes response. */
667/* because of BINARY compatibility, the Node_format MUST BE Node4_format, 672/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
668 * IPv6 nodes are sent in a different message */ 673 * IPv6 nodes are sent in a different message */
@@ -1666,6 +1671,10 @@ void do_DHT(DHT *dht)
1666 do_DHT_friends(dht); 1671 do_DHT_friends(dht);
1667 do_NAT(dht); 1672 do_NAT(dht);
1668 do_toping(dht->ping); 1673 do_toping(dht->ping);
1674
1675 if (dht->assoc)
1676 do_Assoc(dht->assoc, dht);
1677
1669 dht->last_run = unix_time(); 1678 dht->last_run = unix_time();
1670} 1679}
1671void kill_DHT(DHT *dht) 1680void kill_DHT(DHT *dht)
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 5eddab09..d8e9a51e 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -151,6 +151,8 @@ typedef struct {
151} DHT; 151} DHT;
152/*----------------------------------------------------------------------------------*/ 152/*----------------------------------------------------------------------------------*/
153 153
154void DHT_getnodes(DHT *dht, IP_Port *from_ipp, uint8_t *from_id, uint8_t *which_id);
155
154/* Add a new friend to the friends list. 156/* Add a new friend to the friends list.
155 * client_id must be CLIENT_ID_SIZE bytes long. 157 * client_id must be CLIENT_ID_SIZE bytes long.
156 * 158 *
diff --git a/toxcore/assoc.c b/toxcore/assoc.c
index 6a7f7f94..eea01dfb 100644
--- a/toxcore/assoc.c
+++ b/toxcore/assoc.c
@@ -65,7 +65,9 @@ typedef struct Client_entry {
65 hash_t hash; 65 hash_t hash;
66 66
67 /* shortcuts & rumors: timers and data */ 67 /* shortcuts & rumors: timers and data */
68 uint64_t getnodes;
68 uint64_t used_at; 69 uint64_t used_at;
70
69 uint64_t seen_at; 71 uint64_t seen_at;
70 uint64_t heard_at; 72 uint64_t heard_at;
71 73
@@ -91,6 +93,7 @@ struct Assoc {
91 size_t candidates_bucket_count; 93 size_t candidates_bucket_count;
92 size_t candidates_bucket_size; 94 size_t candidates_bucket_size;
93 candidates_bucket *candidates; 95 candidates_bucket *candidates;
96 uint64_t getnodes;
94}; 97};
95 98
96/*****************************************************************************/ 99/*****************************************************************************/
@@ -803,6 +806,7 @@ Assoc *new_Assoc(size_t bits, size_t entries, uint8_t *public_id)
803 } 806 }
804 807
805 assoc->candidates = lists; 808 assoc->candidates = lists;
809 assoc->getnodes = unix_time();
806 810
807 id_copy(assoc->self_client_id, public_id); 811 id_copy(assoc->self_client_id, public_id);
808 client_id_self_update(assoc); 812 client_id_self_update(assoc);
@@ -827,6 +831,114 @@ void Assoc_self_client_id_changed(Assoc *assoc, uint8_t *id)
827 } 831 }
828} 832}
829 833
834#ifdef LOGGING
835static char *idpart2str(uint8_t *id, size_t len);
836#endif
837
838/* refresh buckets */
839void do_Assoc(Assoc *assoc, DHT *dht)
840{
841 if (is_timeout(assoc->getnodes, ASSOC_BUCKET_REFRESH)) {
842 assoc->getnodes = unix_time();
843
844 size_t candidate = (rand() % assoc->candidates_bucket_count) + assoc->candidates_bucket_count;
845
846 /* in that bucket or the buckets closest to it:
847 * find the best heard candidate
848 * find the best seen candidate
849 * send getnode() requests to both */
850 uint8_t *target_id = NULL;
851 Client_entry *heard = NULL, *seen = NULL;
852 size_t i, k, m, bckt;
853
854 for (i = 1; i < assoc->candidates_bucket_count; i++) {
855 if (i % 2)
856 k = - (i >> 1);
857 else
858 k = i >> 1;
859
860 bckt = (candidate + k) % assoc->candidates_bucket_count;
861
862 for (m = 0; m < assoc->candidates_bucket_size; m++)
863 if (assoc->candidates[bckt].list[m].hash) {
864 Client_entry *entry = &assoc->candidates[bckt].list[m];
865
866 if (!is_timeout(entry->getnodes, CANDIDATES_SEEN_TIMEOUT))
867 continue;
868
869 if (!target_id)
870 target_id = entry->client.client_id;
871
872 if (entry->seen_at) {
873 if (!seen)
874 if (!is_timeout(entry->seen_at, CANDIDATES_SEEN_TIMEOUT))
875 seen = entry;
876 }
877
878 if (entry->heard_at) {
879 if (!heard)
880 if (!is_timeout(entry->heard_at, CANDIDATES_HEARD_TIMEOUT))
881 heard = entry;
882 }
883
884 if (seen && heard)
885 break;
886 }
887
888 if (seen && heard)
889 break;
890 }
891
892#ifdef LOGGING
893 size_t total = 0, written = sprintf(logbuffer, "assoc: [%u] => ",
894 (uint32_t)(candidate % assoc->candidates_bucket_count));
895
896 if (written > 0)
897 total += written;
898
899#endif
900
901 if (seen) {
902 IPPTsPng *ippts = seen->seen_family == AF_INET ? &seen->client.assoc4 : &seen->client.assoc6;
903#ifdef LOGGING
904 written = sprintf(logbuffer + total, " S[%s...] %s:%u", idpart2str(seen->client.client_id, 8),
905 ip_ntoa(&ippts->ip_port.ip), htons(ippts->ip_port.port));
906
907 if (written > 0)
908 total += written;
909
910#endif
911 DHT_getnodes(dht, &ippts->ip_port, seen->client.client_id, target_id);
912 seen->getnodes = unix_time();
913 }
914
915 if (heard && (heard != seen)) {
916 IP_Port *ipp = heard->heard_family == AF_INET ? &heard->assoc_heard4 : &heard->assoc_heard6;
917#ifdef LOGGING
918 written = sprintf(logbuffer + total, " H[%s...] %s:%u", idpart2str(heard->client.client_id, 8), ip_ntoa(&ipp->ip),
919 htons(ipp->port));
920
921 if (written > 0)
922 total += written;
923
924#endif
925 DHT_getnodes(dht, ipp, heard->client.client_id, target_id);
926 heard->getnodes = unix_time();
927 }
928
929#ifdef LOGGING
930
931 if (!heard && !seen)
932 sprintf(logbuffer + total, "no nodes to talk to??\n");
933 else
934 /* for arcane reasons, sprintf(str, "\n") doesn't function */
935 sprintf(logbuffer + total, "%s", "\n");
936
937 loglog(logbuffer);
938#endif
939 }
940}
941
830/* destroy */ 942/* destroy */
831void kill_Assoc(Assoc *assoc) 943void kill_Assoc(Assoc *assoc)
832{ 944{
diff --git a/toxcore/assoc.h b/toxcore/assoc.h
index 26ea3b91..91e4ef8c 100644
--- a/toxcore/assoc.h
+++ b/toxcore/assoc.h
@@ -76,6 +76,13 @@ Assoc *new_Assoc(size_t bits, size_t entries, uint8_t *public_id);
76/* public_id changed (loaded), update which entry isn't stored */ 76/* public_id changed (loaded), update which entry isn't stored */
77void Assoc_self_client_id_changed(Assoc *assoc, uint8_t *public_id); 77void Assoc_self_client_id_changed(Assoc *assoc, uint8_t *public_id);
78 78
79/* every 45s send out a getnodes() for a "random" bucket */
80#define ASSOC_BUCKET_REFRESH 45
81
82/* refresh bucket's data from time to time
83 * this must be called only from DHT */
84void do_Assoc(Assoc *assoc, DHT *dht);
85
79/* destroy */ 86/* destroy */
80void kill_Assoc(Assoc *assoc); 87void kill_Assoc(Assoc *assoc);
81 88