Addition of libbitdht.

============================================================

This is intended to be a completely independent library from RS, 
(hosted at sf.net/projects/bitdht) hence is being commited at the top level.

As initial further development / testing will be driven by RS integration
it is being added to the RS repository. Equally important is ensuring
that RS can compile without requiring aux libraries.

Once libbitdht is further developed, this section of the repository
is expected to be removed... But that will not be for a while, I expect.

drbob.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3276 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2010-07-10 11:48:24 +00:00
parent 9b72977bba
commit c415bb6158
56 changed files with 11344 additions and 0 deletions

View File

@ -0,0 +1,44 @@
CPPFLAGS += -g -Wall -D BE_DEBUG -lpthread
LDFLAGS += -g -Wall -D BE_DEBUG -lpthread
CFLAGS += -g -Wall -D BE_DEBUG
CC = g++
LIB = -lpthread
CPPLIB = -lpthread
EXEC = bdmsgs_test bdmetric_test bdquery_test bdspace_test bdspace_test2 bdnode_test bdnode_test2 bdstore_test
EXEC += bdnode_multitest1 bdmidids_test
EXEC += udpbitdht_nettest bencode_test
EXEC += bdmgr_multitest
#EXEC += bdudp_test
all: $(EXEC)
OBJ = bencode.o bdmsgs.o bdobj.o
OBJ += bdpeer.o bdquery.o bdnode.o bdstore.o bdhash.o
OBJ += bdmanager.o bdstddht.o
# udp base objs
OBJ += bdthreads.o udplayer.o udpstack.o
OBJ += udpbitdht.o
bdmsgs_test: $(OBJ) bdmsgs_test.o
bdmetric_test: $(OBJ) bdmetric_test.o
bdquery_test: $(OBJ) bdquery_test.o
bdspace_test: $(OBJ) bdspace_test.o
bdspace_test2: $(OBJ) bdspace_test2.o
bdnode_test: $(OBJ) bdnode_test.o
bdnode_test2: $(OBJ) bdnode_test2.o
bdmidids_test: $(OBJ) bdmidids_test.o
bdnode_multitest1: $(OBJ) bdnode_multitest1.o
bdmgr_multitest: $(OBJ) bdmgr_multitest.o
bdstore_test: $(OBJ) bdstore_test.o
bdudp_test: $(OBJ) bdudp_test.o
udpbitdht_nettest: $(OBJ) udpbitdht_nettest.o
bencode_test: $(OBJ) bencode_test.o
clean:
rm -f *.o core $(EXEC)
.PHONY: all clean

View File

@ -0,0 +1,22 @@
BitDHT Notes
==================================================================
Compiling
------------------------------------------------------------------
Should compile on POSIX platforms.
Testing
------------------------------------------------------------------
Run the program: udpbitdht_nettest to see the
This requires an up-to-date list of dht peers (in bdboot.txt)
Using BitDHT
------------------------------------------------------------------
Use udpbitdht_nettest.cc as an example.

View File

@ -0,0 +1,500 @@
85.84.48.19 62069
188.2.228.28 60928
62.83.45.61 11568
117.254.136.81 18497
98.111.73.242 34446
109.60.19.104 37721
83.86.184.100 36986
95.90.60.246 13411
93.103.249.247 17844
77.83.229.93 64116
24.247.120.140 23842
85.132.104.212 30998
115.132.178.64 11325
85.196.251.212 59225
85.173.224.49 36195
189.245.47.185 55119
75.53.207.9 53187
190.213.101.234 26250
84.203.43.111 57306
96.51.136.17 10484
203.165.188.146 14675
122.25.24.101 14705
114.36.164.228 17732
41.226.62.44 53581
89.236.15.238 14222
210.56.72.100 6881
88.88.85.118 27454
78.31.244.65 21454
89.106.18.4 36678
89.156.180.170 14699
193.150.220.231 30107
188.163.57.203 44741
94.231.147.133 36245
94.26.10.42 62398
123.238.122.209 37115
188.168.95.21 61843
82.131.119.60 13400
187.57.146.165 57592
188.36.217.211 7908
201.87.57.192 22219
173.73.78.128 38903
212.75.14.55 10094
173.179.220.61 22534
96.228.35.250 64059
204.9.160.114 12368
76.20.112.90 12745
178.162.170.237 6837
99.225.40.127 64192
212.174.9.10 64969
68.149.156.129 61517
98.227.233.64 62196
77.250.125.124 6881
62.44.99.141 52068
77.37.139.99 26973
183.178.58.77 16541
109.87.84.249 62000
86.156.8.14 31121
78.96.204.184 37646
95.208.228.12 51852
79.181.10.12 19169
58.179.100.228 47488
70.68.11.80 23032
178.122.193.176 18010
121.102.167.147 61588
89.74.251.47 19639
114.37.157.199 22245
93.152.182.255 19793
217.42.96.8 24111
189.25.9.26 20730
68.1.165.39 16153
83.132.36.86 35107
59.2.54.186 22753
84.30.228.249 3603
190.44.97.178 63549
114.27.99.216 7975
99.226.153.196 18904
24.23.243.23 51030
115.252.101.138 51413
211.30.223.198 32067
113.190.149.88 63726
76.232.119.73 61243
95.25.155.218 42786
99.62.240.185 52482
92.113.120.171 10234
212.233.134.225 8819
70.75.155.80 16019
87.110.100.101 10873
59.146.201.104 57237
201.83.152.32 24543
99.99.31.175 52843
86.143.252.240 50299
201.79.156.40 38331
78.146.142.55 18908
118.241.39.15 26062
61.91.88.16 16880
88.178.52.25 20468
69.123.232.123 23334
220.141.159.163 23769
83.98.249.113 12604
173.2.225.155 20471
66.108.142.1 60204
75.68.198.80 14064
89.253.185.103 14063
82.137.66.237 21717
67.215.242.138 6881
76.119.206.114 6881
188.81.233.217 59939
77.95.25.38 6881
212.3.131.96 53635
70.31.60.158 56555
122.164.78.136 31953
207.204.107.33 12071
83.253.2.148 52645
62.162.165.238 11553
76.103.80.68 32811
90.151.46.103 57998
114.43.239.200 9620
123.120.130.151 20770
118.9.60.210 7813
112.205.90.145 27962
217.234.194.195 20877
212.187.7.68 41823
96.252.93.35 10000
24.192.137.82 56168
174.57.52.107 56989
66.203.164.20 16210
61.216.174.232 21308
78.90.179.122 25664
86.162.62.101 24916
86.72.3.89 22909
81.216.162.216 22372
203.100.241.233 17074
123.191.63.77 1841
61.230.220.21 10879
124.64.109.96 20031
78.90.245.119 22874
91.124.179.132 42780
98.111.11.78 50609
125.230.40.185 22930
78.157.19.76 22610
83.237.177.17 51372
94.168.245.88 35405
188.18.156.133 10346
213.216.240.13 62911
61.223.205.111 7743
220.132.54.41 23993
79.158.58.150 25173
196.221.102.231 11116
62.193.242.154 22820
74.133.3.196 25720
70.144.143.25 50647
88.88.92.13 61596
91.122.175.165 37942
24.83.16.125 15112
95.53.31.85 55555
188.186.79.162 58714
58.89.250.169 26502
41.239.122.211 19233
79.86.29.143 34934
92.82.94.34 52773
118.160.38.186 2470
188.220.252.94 61799
93.97.70.175 10371
88.80.110.116 27521
216.232.103.30 51413
178.128.25.38 23875
71.238.140.152 10899
142.68.209.74 10742
89.83.235.80 40013
76.89.143.130 49160
75.82.252.172 63072
89.136.253.27 6881
114.44.211.193 26085
95.156.120.77 15619
75.42.217.61 49160
68.69.206.227 59769
71.77.79.8 10892
184.52.59.85 2664
85.75.152.112 32480
109.58.9.184 47618
220.130.128.40 18686
95.52.198.215 11043
95.84.230.121 53479
89.158.220.194 17054
79.89.125.107 17636
98.215.87.152 45826
189.61.163.163 31148
95.104.83.111 12834
74.58.113.190 30498
114.43.212.201 24526
24.173.50.164 57812
188.27.127.10 21264
114.39.71.3 8260
112.104.114.13 11403
201.86.195.236 15035
118.169.68.161 26721
80.156.18.64 14332
174.96.252.23 43975
123.130.186.58 19042
187.38.104.144 9879
71.17.38.53 52994
178.123.27.113 25116
90.230.166.70 31359
87.150.183.76 52525
70.26.68.18 13332
94.180.196.210 20700
78.238.140.207 10512
99.3.148.91 17673
83.198.18.142 57125
86.185.168.8 20759
68.103.186.81 42197
190.174.49.173 12198
70.78.24.70 50620
24.138.37.4 13731
85.138.148.57 50005
82.180.32.5 56466
75.159.68.171 39889
220.138.38.116 22904
89.41.77.110 60377
201.246.195.204 13183
90.48.147.199 22636
81.30.221.163 24570
65.92.202.86 6969
84.208.119.213 54480
201.67.179.187 10004
84.110.116.52 10223
70.41.114.21 54838
72.73.29.191 14757
69.206.173.120 42760
197.0.124.143 53121
77.31.230.160 17522
178.46.54.230 6968
66.183.127.122 29982
83.132.220.34 50143
137.101.221.64 47111
186.97.7.96 46409
88.118.71.27 47522
201.223.40.117 39859
118.22.65.110 16460
59.189.228.68 8683
77.38.5.68 56958
92.43.0.11 6881
92.135.130.122 35998
174.24.169.37 19227
123.192.104.68 22971
84.126.89.134 54282
117.197.52.112 39667
203.218.195.79 19524
188.126.32.173 60563
124.108.58.67 13622
60.56.181.126 51044
125.224.164.40 15101
88.169.91.96 17138
74.51.158.228 36152
87.223.171.129 44869
96.236.181.208 50529
86.151.231.115 12800
99.188.246.102 59753
91.52.152.222 36279
79.112.90.188 37635
91.124.83.99 12034
82.238.89.67 58533
83.253.54.19 59453
94.233.244.218 63774
94.189.141.137 31727
38.99.78.30 7914
190.179.181.154 53529
97.114.106.34 45737
77.248.88.206 33146
83.226.250.153 11097
96.48.14.40 34453
41.201.89.51 57110
96.250.221.56 19356
70.65.153.134 51486
211.141.223.132 32004
95.64.159.234 16962
120.83.209.25 19881
66.176.133.161 45717
79.111.89.6 31756
89.212.42.58 32346
203.129.29.223 17051
76.23.14.106 13352
79.109.129.156 5738
98.200.170.188 31325
85.76.113.201 14112
90.212.89.6 13341
187.44.253.130 46324
97.102.54.192 63656
124.128.119.174 16001
80.235.136.233 17866
77.201.51.233 12686
218.186.107.198 13096
81.200.156.184 54547
78.70.254.146 18989
81.155.161.164 10504
98.179.27.15 18674
80.217.104.60 47749
119.247.219.75 9810
87.48.17.225 42002
87.221.120.224 23355
96.48.69.169 17610
116.88.199.8 10231
161.184.223.26 37338
200.117.60.240 4672
85.220.114.184 26414
38.99.78.30 9460
220.71.161.58 36128
190.46.150.58 39162
86.74.41.183 8916
87.226.36.22 33380
69.141.124.24 6799
114.44.115.15 24203
91.122.57.5 6881
95.78.241.143 55568
80.212.223.54 34277
88.106.14.250 46095
80.190.139.91 6899
95.37.64.249 34699
85.155.20.185 12939
219.79.75.139 18716
187.13.146.211 42197
82.183.119.9 10073
87.207.107.103 21022
174.88.187.95 23442
70.145.187.53 50580
188.17.38.90 35691
114.43.157.167 26367
219.84.231.242 20456
121.223.169.207 45625
82.67.171.97 17713
77.70.29.89 51379
88.178.61.229 28038
94.139.216.137 10906
83.226.36.50 49999
72.192.119.73 64855
121.186.2.116 64243
123.193.84.215 16116
78.20.193.150 58408
77.87.93.166 59007
78.232.112.118 25724
88.156.48.177 9585
85.173.122.251 36230
118.101.5.227 52022
173.168.78.83 20187
219.205.182.238 12369
75.31.126.62 35882
120.92.88.19 13448
95.28.45.134 41509
87.206.178.223 14258
76.11.8.174 54491
64.180.168.9 32456
93.136.190.210 58705
95.69.196.253 31010
121.110.127.143 56259
190.178.87.62 40511
118.168.132.95 21413
201.41.31.212 14727
94.169.49.45 65143
94.19.190.4 53965
76.64.48.127 18259
79.100.172.133 51013
201.239.181.200 29658
95.27.110.154 35691
79.165.186.111 15866
90.60.242.211 21502
69.123.70.207 42799
96.233.61.112 34504
178.34.81.203 35691
96.53.209.94 50471
92.255.207.115 10183
218.250.12.65 13837
139.168.118.215 20396
87.194.212.38 40010
88.192.73.144 6881
81.30.187.254 62330
76.10.163.171 62740
91.139.251.30 8376
210.194.9.87 61565
113.193.104.207 38541
201.6.42.113 10101
81.129.112.202 17033
83.87.119.147 6881
87.110.24.173 16166
119.152.161.250 7609
76.121.94.144 21088
81.141.82.27 25454
74.210.214.29 23405
76.253.65.221 54321
81.155.156.214 8856
203.188.212.143 25352
59.94.244.94 34481
72.184.236.214 13526
90.192.46.138 16349
58.179.42.233 26370
222.165.33.19 49875
82.225.159.13 33697
79.100.116.145 16972
218.250.107.167 16743
114.186.101.252 20447
111.240.223.151 25057
89.81.31.122 54510
85.50.103.145 64767
88.101.181.127 11691
213.65.180.73 22326
85.130.27.129 10044
24.36.224.121 21400
201.10.23.83 43773
89.42.100.13 39734
76.115.138.95 60004
193.152.216.83 62411
189.138.136.64 53821
174.107.128.125 51729
193.159.165.146 64735
78.157.4.137 16401
99.28.186.25 51347
58.188.217.223 30147
114.42.167.6 8514
91.121.142.15 35939
87.121.12.164 57469
24.245.47.131 52676
24.77.213.5 21096
95.61.133.212 4658
209.226.103.66 51765
61.93.30.175 7583
24.44.145.176 30911
24.236.193.89 60444
67.181.2.18 18126
99.229.132.47 60053
200.72.149.212 26556
85.246.174.204 33530
121.110.111.149 17487
112.119.195.49 12607
81.195.84.6 57264
98.114.45.206 24295
58.165.136.32 39743
213.60.164.82 44749
188.26.167.182 48135
77.206.7.199 61195
24.126.56.163 64590
75.158.198.166 59643
92.14.76.40 16730
70.80.204.74 38517
64.20.155.53 16351
173.33.176.245 49161
78.93.64.91 22302
87.109.149.40 47695
58.96.48.36 37252
88.192.134.199 6924
78.70.117.209 59473
193.193.193.152 32042
212.87.181.220 54130
69.137.229.210 45681
93.148.138.240 22516
69.73.255.83 25295
72.135.11.99 42315
81.100.239.130 29827
86.125.142.52 30095
93.116.48.180 47676
93.90.252.102 53033
151.21.226.156 63269
89.149.202.125 56351
189.22.50.162 51413
82.24.181.14 6888
83.238.236.178 16049
76.111.181.68 18631
122.106.62.138 60003
221.2.83.190 14418
81.154.92.221 35015
77.238.244.37 45365
83.167.76.124 25705
71.32.58.187 61111
82.127.5.90 55516
114.243.240.89 14022
89.100.108.135 42419
94.253.85.157 39808
71.74.98.133 46791
98.166.220.46 31377
69.76.179.45 15505
201.253.20.230 10063
78.235.15.169 52020
89.216.250.81 52546
99.233.74.84 45147
76.19.148.42 48404
78.87.184.78 52544
182.89.61.7 26752
90.25.2.224 16875
68.192.125.173 32823
71.191.177.11 51413
71.117.207.9 53782
201.223.75.234 39364
94.6.233.187 42289
87.229.158.13 55213
151.51.38.224 34173
85.74.163.171 17165
75.70.154.238 48368
122.172.14.243 56489
94.67.136.84 15686
99.192.18.155 42965
86.207.159.183 50058
85.85.99.46 23409

View File

@ -0,0 +1,279 @@
/*
* bitdht/bdhash.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdhash.h"
#include "bdstddht.h"
#include <iostream>
bdHashEntry::bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store)
:mValue(value), mStoreTS(store), mSecret(secret), mLifetime(lifetime)
{
return;
}
/**************************** class bdHashSet ********************************/
bdHashSet::bdHashSet(bdNodeId *id)
:mId(*id)
{
return;
}
int bdHashSet::search(std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries)
{
std::multimap<std::string, bdHashEntry>::iterator sit, eit, it;
sit = mEntries.lower_bound(key);
eit = mEntries.upper_bound(key);
time_t now = time(NULL);
for(it = sit; it != eit; it++)
{
time_t age = now - it->second.mStoreTS;
if (age < (int32_t) maxAge)
{
entries.push_back(it->second);
}
}
return (0 < entries.size());
}
/***
* With modification.
* If there is no secret -> it cannot be deleted (must timeout), but can be extended.
* If there is a secret -> must include it to modify.
*
* Therefore if identical entry without secret comes along - what do I do?
* -> create duplicate?
*/
int bdHashSet::modify(std::string key, bdHashEntry *entry, uint32_t modFlags)
{
std::multimap<std::string, bdHashEntry>::iterator sit, eit, it;
sit = mEntries.lower_bound(key);
eit = mEntries.upper_bound(key);
time_t now = time(NULL);
bool updated = false;
for(it = sit; it != eit; it++)
{
/* check it all */
if (it->second.mValue == entry->mValue)
{
bool noSecret = (it->second.mSecret == "");
bool sameSecret = (it->second.mSecret == entry->mSecret);
bool update = false;
if (noSecret && sameSecret)
{
/* only allowed to increase lifetime */
if (modFlags == BITDHT_HASH_ENTRY_ADD)
{
time_t existKillTime = it->second.mLifetime + it->second.mStoreTS;
time_t newKillTime = entry->mLifetime + now;
if (newKillTime > existKillTime)
{
update = true;
}
}
}
else if (sameSecret)
{
if (modFlags == BITDHT_HASH_ENTRY_ADD)
{
update = true;
}
else if (modFlags == BITDHT_HASH_ENTRY_DELETE)
{
/* do it here */
mEntries.erase(it);
return 1;
}
}
if (update)
{
it->second.mStoreTS = now;
it->second.mLifetime = entry->mLifetime;
updated = true;
}
}
}
if ((!updated) && (modFlags == BITDHT_HASH_ENTRY_ADD))
{
/* create a new entry */
bdHashEntry newEntry(entry->mValue, entry->mSecret, entry->mLifetime, now);
mEntries.insert(std::pair<std::string, bdHashEntry>(key, newEntry));
updated = true;
}
return updated;
}
int bdHashSet::printHashSet(std::ostream &out)
{
time_t now = time(NULL);
std::multimap<std::string, bdHashEntry>::iterator it;
out << "Hash: ";
bdStdPrintNodeId(out, &mId); // Allowing "Std" as we dont need dht functions everywhere.
out << std::endl;
for(it = mEntries.begin(); it != mEntries.end();it++)
{
time_t age = now - it->second.mStoreTS;
out << "\tK:" << bdStdConvertToPrintable(it->first);
out << " V:" << bdStdConvertToPrintable(it->second.mValue);
out << " A:" << age << " L:" << it->second.mLifetime;
out << " S:" << bdStdConvertToPrintable(it->second.mSecret);
out << std::endl;
}
return 1;
}
int bdHashSet::cleanupHashSet(uint32_t maxAge)
{
time_t now = time(NULL);
/* this is nasty... but don't know how to effectively remove from multimaps
* * Must do full repeat for each removal.
*/
std::multimap<std::string, bdHashEntry>::iterator it;
for(it = mEntries.begin(); it != mEntries.end();)
{
time_t age = now - it->second.mStoreTS;
if ((age > (int32_t) maxAge) || (age > it->second.mLifetime))
{
mEntries.erase(it);
it = mEntries.begin();
}
else
{
it++;
}
}
return 1;
}
/******************************* class bdHashSpace ***************************/
bdHashSpace::bdHashSpace()
{
return;
}
/* accessors */
int bdHashSpace::search(bdNodeId *id, std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries)
{
std::map<bdNodeId, bdHashSet>::iterator it;
it = mHashTable.find(*id);
if (it == mHashTable.end())
{
/* no entry */
return 1;
}
return it->second.search(key, maxAge, entries);
}
int bdHashSpace::modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags)
{
std::map<bdNodeId, bdHashSet>::iterator it;
it = mHashTable.find(*id);
if (it == mHashTable.end())
{
if (modFlags == BITDHT_HASH_ENTRY_DELETE)
{
/* done already */
return 1;
}
//mHashTable[*id] = bdHashSet(id);
mHashTable.insert(std::pair<bdNodeId, bdHashSet>(*id, bdHashSet(id)));
it = mHashTable.find(*id);
}
return it->second.modify(key, entry, modFlags);
}
int bdHashSpace::printHashSpace(std::ostream &out)
{
std::map<bdNodeId, bdHashSet>::iterator it;
out << "bdHashSpace::printHashSpace()" << std::endl;
out << "--------------------------------------------" << std::endl;
for(it = mHashTable.begin(); it != mHashTable.end(); it++)
{
it->second.printHashSet(out);
}
out << "--------------------------------------------" << std::endl;
return 1;
}
int bdHashSpace::cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge)
{
std::map<bdNodeId, bdHashSet>::iterator it;
std::list<bdNodeId> eraseList;
std::list<bdNodeId>::iterator eit;
for(it = mHashTable.begin(); it != mHashTable.end(); it++)
{
if ((it->first < *min) ||
(*max < it->first))
{
/* schedule for erasure */
eraseList.push_back(it->first);
}
else
{
/* clean up Hash Set */
it->second.cleanupHashSet(maxAge);
}
}
/* cleanup */
while(eraseList.size() > 0)
{
bdNodeId &eId = eraseList.front();
it = mHashTable.find(eId);
if (it != mHashTable.end())
{
mHashTable.erase(it);
}
}
return 1;
}

View File

@ -0,0 +1,87 @@
#ifndef BITDHT_HASH_SPACE_H
#define BITDHT_HASH_SPACE_H
/*
* bitdht/bdhash.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdpeer.h"
#include <list>
#include <string>
#include <map>
#define BITDHT_HASH_ENTRY_ADD 1
#define BITDHT_HASH_ENTRY_DELETE 2
class bdHashEntry
{
public:
bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store);
std::string mValue;
time_t mStoreTS;
/* These are nice features that OpenDHT had */
std::string mSecret;
time_t mLifetime;
};
class bdHashSet
{
public:
bdHashSet(bdNodeId *id);
int search(std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries);
int modify(std::string key, bdHashEntry *entry, uint32_t modFlags);
int printHashSet(std::ostream &out);
int cleanupHashSet(uint32_t maxAge);
bdNodeId mId;
std::multimap<std::string, bdHashEntry> mEntries;
};
class bdHashSpace
{
public:
bdHashSpace();
/* accessors */
int search(bdNodeId *id, std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries);
int modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags);
int printHashSpace(std::ostream&);
int cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge);
private:
std::map<bdNodeId, bdHashSet> mHashTable;
};
#endif

View File

@ -0,0 +1,182 @@
#ifndef BIT_DHT_INTERFACE_H
#define BIT_DHT_INTERFACE_H
/*
* bitdht/bdiface.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <iosfwd>
#include <map>
#include <string>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*
* Functions and Classes required for Interfacing with the BitDht.
* This should be the sole header file required to talk to Dht.
* ... though setting it up will require including udpbitdht.h as well.
*
*/
#define BITDHT_KEY_LEN 20
#define BITDHT_KEY_INTLEN 5
#define BITDHT_KEY_BITLEN 160
#define BITDHT_MAX_PKTSIZE 1024
#define BITDHT_TTL 64
#define BITDHT_SEARCH_ONE_SHOT 1
#define BITDHT_SEARCH_REPEATING 2
class bdNodeId
{
public:
unsigned char data[BITDHT_KEY_LEN];
};
class bdMetric: public bdNodeId {};
class bdId
{
public:
bdId();
bdId(bdNodeId in_id, struct sockaddr_in in_addr);
struct sockaddr_in addr;
bdNodeId id;
};
#define BITDHT_LIKELY_SAME_NO 0x00000000
#define BITDHT_LIKELY_SAME_YES 0x00000001
#define BITDHT_LIKELY_SAME_PORT_CHANGED 0x00000002
#define BITDHT_LIKELY_SAME_LOC_CHANGED 0x00000004
#define BITDHT_LIKELY_SAME_IDENTICAL 0x00000008
class bdDhtFunctions
{
public:
// bdDhtFunctions();
/* setup variables */
virtual uint16_t bdNumBuckets() = 0;
virtual uint16_t bdNodesPerBucket() = 0; /* used for query + bdspace */
virtual uint16_t bdBucketBitSize() = 0;
virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric) = 0;
virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) = 0;
virtual int bdBucketDistance(const bdMetric *metric) = 0;
virtual uint32_t bdLikelySameNode(const bdId *id1, const bdId *id2) = 0;
virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) = 0;
virtual void bdPrintId(std::ostream &out, const bdId *a) = 0;
virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0;
};
/* peer flags
* order is important!
* higher bits = more priority.
* BITDHT_PEER_STATUS_RECVPONG
* BITDHT_PEER_STATUS_RECVNODES
* BITDHT_PEER_STATUS_RECVHASHES
* BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx)
* BITDHT_PEER_STATUS_DHT_APPL (XXRSxx)
* BITDHT_PEER_STATUS_DHT_VERSION (XXxx50)
*
*/
#define BITDHT_PEER_STATUS_MASK_RECVD 0x000000ff
#define BITDHT_PEER_STATUS_MASK_DHT 0x000000ff
#define BITDHT_PEER_STATUS_RECV_PONG 0x00000001
#define BITDHT_PEER_STATUS_RECV_NODES 0x00000002
#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000004
#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100
#define BITDHT_PEER_STATUS_DHT_APPL 0x00000200
#define BITDHT_PEER_STATUS_DHT_VERSION 0x00000400
/* Status options */
#define BITDHT_QUERY_QUERYING 1
#define BITDHT_QUERY_FAILURE 2
#define BITDHT_QUERY_FOUND_CLOSEST 3
#define BITDHT_QUERY_PEER_UNREACHABLE 4
#define BITDHT_QUERY_SUCCESS 5
/* Query Flags */
#define BITDHT_QFLAGS_NONE 0
#define BITDHT_QFLAGS_DISGUISE 1
#define BITDHT_QFLAGS_DO_IDLE 2
class BitDhtCallback
{
public:
// ~BitDhtCallback();
// dummy cos not needed for standard dht behaviour;
virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) { return 0; }
// must be implemented.
virtual int dhtPeerCallback(const bdNodeId *id, uint32_t status) = 0;
virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) = 0;
};
class BitDhtInterface
{
public:
/***** Request Lookup (DHT Peer & Keyword) *****/
virtual void addFindNode(bdNodeId *id, uint32_t mode) = 0;
virtual void removeFindNode(bdNodeId *id) = 0;
virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode) = 0;
/***** Add / Remove Callback Clients *****/
virtual void addCallback(BitDhtCallback *cb) = 0;
virtual void removeCallback(BitDhtCallback *cb) = 0;
/***** Get Results Details *****/
virtual int getDhtPeerAddress(bdNodeId *id, struct sockaddr_in &from) = 0;
virtual int getDhtValue(bdNodeId *id, std::string key, std::string &value) = 0;
};
#endif

View File

@ -0,0 +1,741 @@
/*
* bitdht/bdmanager.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
/*******
* Node Manager.
******/
/******************************************
* 1) Maintains a list of ids to search for.
* 2) Sets up initial search for own node.
* 3) Checks on status of queries.
* 4) Callback on successful searches.
*
* This is pretty specific to RS requirements.
****/
#include "bdiface.h"
#include "bdstddht.h"
#include "bdmanager.h"
#include "bdmsgs.h"
#include "bencode.h"
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/***
* #define DEBUG_MGR 1
* #define DEBUG_MGR_PKT 1
***/
//#define DEBUG_MGR 1
bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns)
:bdNode(id, dhtVersion, bootfile, fns)
{
mMode = BITDHT_MGR_STATE_STARTUP;
mFns = fns;
/* setup a query for self */
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::bdNodeManager() ID: ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
}
void bdNodeManager::addFindNode(bdNodeId *id, uint32_t qflags)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::addFindNode() ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
/* check if exists already */
std::map<bdNodeId, bdQueryPeer>::iterator it;
it = mActivePeers.find(*id);
if (it != mActivePeers.end())
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::addFindNode() Found existing....";
std::cerr << std::endl;
#endif
return;
}
/* add to map */
bdQueryPeer peer;
peer.mId.id = (*id);
peer.mStatus = BITDHT_QUERY_QUERYING;
peer.mQFlags = qflags;
mActivePeers[*id] = peer;
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::addFindNode() Added QueryPeer....";
std::cerr << std::endl;
#endif
addQuery(id, qflags | BITDHT_QFLAGS_DISGUISE);
return;
}
void bdNodeManager::removeFindNode(bdNodeId *id)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::removeFindNode() ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
std::map<bdNodeId, bdQueryPeer>::iterator it;
it = mActivePeers.find(*id);
if (it == mActivePeers.end())
{
return;
}
/* cleanup any actions */
clearQuery(&(it->first));
//clearPing(&(it->first));
/* remove from map */
mActivePeers.erase(it);
return;
}
void bdNodeManager::iteration()
{
time_t now = time(NULL);
time_t modeAge = now - mModeTS;
switch(mMode)
{
case BITDHT_MGR_STATE_STARTUP:
/* 10 seconds startup .... then switch to ACTIVE */
if (modeAge > MAX_STARTUP_TIME)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::iteration(): STARTUP ";
std::cerr << std::endl;
#endif
bdNodeId id;
getOwnId(&id);
addQuery(&id, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_DISGUISE);
//mMode = BITDHT_MGR_STATE_ACTIVE;
mMode = BITDHT_MGR_STATE_REFRESH;
mModeTS = now;
}
break;
case BITDHT_MGR_STATE_ACTIVE:
if (modeAge > MAX_REFRESH_TIME)
{
mMode = BITDHT_MGR_STATE_REFRESH;
mModeTS = now;
}
break;
case BITDHT_MGR_STATE_REFRESH:
{
/* select random ids, and perform searchs to refresh space */
mMode = BITDHT_MGR_STATE_ACTIVE;
mModeTS = now;
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::iteration(): Updating Stores";
std::cerr << std::endl;
#endif
updateStore();
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::iteration(): REFRESH ";
std::cerr << std::endl;
#endif
status();
}
break;
case BITDHT_MGR_STATE_QUIET:
{
}
break;
}
/* tick parent */
bdNode::iteration();
}
int bdNodeManager::status()
{
/* do status of bdNode */
printState();
checkStatus();
return 1;
}
int bdNodeManager::checkStatus()
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus()";
std::cerr << std::endl;
#endif
/* check queries */
std::map<bdNodeId, bdQueryStatus>::iterator it;
std::map<bdNodeId, bdQueryStatus> queryStatus;
QueryStatus(queryStatus);
for(it = queryStatus.begin(); it != queryStatus.end(); it++)
{
bool doPing = false;
bool doRemove = false;
bool doCallback = false;
uint32_t callbackStatus = 0;
switch(it->second.mStatus)
{
default:
case BITDHT_QUERY_QUERYING:
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Query in Progress id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
}
break;
case BITDHT_QUERY_FAILURE:
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Query Failed: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
// BAD.
doRemove = true;
doCallback = true;
callbackStatus = BITDHT_MGR_QUERY_FAILURE;
}
break;
case BITDHT_QUERY_FOUND_CLOSEST:
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Found Closest: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
doRemove = true;
doCallback = true;
callbackStatus = BITDHT_MGR_QUERY_PEER_OFFLINE;
}
break;
case BITDHT_QUERY_PEER_UNREACHABLE:
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() the Peer Online but Unreachable: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
doRemove = true;
doCallback = true;
callbackStatus = BITDHT_MGR_QUERY_PEER_UNREACHABLE;
}
break;
case BITDHT_QUERY_SUCCESS:
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Found Query: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
//foundId =
doRemove = true;
doCallback = true;
callbackStatus = BITDHT_MGR_QUERY_PEER_ONLINE;
}
break;
}
/* remove done queries */
if (doRemove)
{
if (it->second.mQFlags & BITDHT_QFLAGS_DO_IDLE)
{
doRemove = false;
}
}
if (doRemove)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Removing query: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
clearQuery(&(it->first));
}
/* FIND in activePeers */
std::map<bdNodeId, bdQueryPeer>::iterator pit;
pit = mActivePeers.find(it->first);
if (pit == mActivePeers.end())
{
/* only internal! - disable Callback / Ping */
doPing = false;
doCallback = false;
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Internal: no cb for id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
}
else if (pit->second.mStatus == it->second.mStatus)
{
/* status is unchanged */
doPing = false;
doCallback = false;
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Status unchanged for : ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << " status: " << it->second.mStatus;
std::cerr << std::endl;
#endif
}
else
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Updating External Status for : ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << " to: " << it->second.mStatus;
std::cerr << std::endl;
#endif
/* update status */
pit->second.mStatus = it->second.mStatus;
}
/* add successful queries to ping list */
if (doPing)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Starting Ping (TODO): id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
/* add first matching peer */
//addPeerPing(foundId);
}
/* callback on new successful queries */
if (doCallback)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::checkStatus() Doing Callback: id: ";
mFns->bdPrintNodeId(std::cerr, &(it->first));
std::cerr << std::endl;
#endif
doPeerCallback(&(it->first), callbackStatus);
}
}
return 1;
}
#if 0
bdNodeManager::checkPingStatus()
{
/* check queries */
std::map<bdNodeId, bdPingStatus>::iterator it;
std::map<bdNodeId, bdPingStatus> pingStatus;
PingStatus(pingStatus);
for(it = pingStatus.begin(); it != pingStatus.end(); it++)
{
switch(it->second.mStatus)
{
case BITDHT_QUERY_QUERYING:
{
}
break;
case BITDHT_QUERY_FAILURE:
{
// BAD.
doRemove = true;
}
break;
case BITDHT_QUERY_FOUND_CLOSEST:
{
doRemove = true;
}
break;
case BITDHT_QUERY_SUCCESS:
{
foundId =
doRemove = true;
}
break;
}
/* remove done queries */
if (doRemove)
{
clearQuery(it->first);
}
/* add successful queries to ping list */
if (doPing)
{
/* add first matching peer */
addPeerPing(foundId);
}
/* callback on new successful queries */
if (doCallback)
{
}
}
}
#endif
int bdNodeManager::SearchOutOfDate()
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::SearchOutOfDate()";
std::cerr << std::endl;
#endif
std::map<bdNodeId, bdQueryPeer>::iterator it;
/* search for out-of-date peers */
for(it = mActivePeers.begin(); it != mActivePeers.end(); it++)
{
#if 0
if (old)
{
addQuery(it->first);
}
#endif
}
return 1;
}
/***** Functions to Call down to bdNodeManager ****/
/* Request DHT Peer Lookup */
/* Request Keyword Lookup */
void bdNodeManager::findDhtValue(bdNodeId *id, std::string key, uint32_t mode)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::findDhtValue() TODO";
std::cerr << std::endl;
#endif
}
/***** Get Results Details *****/
int bdNodeManager::getDhtPeerAddress(bdNodeId *id, struct sockaddr_in &from)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::getDhtPeerAddress() Id: ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << " ... ? TODO" << std::endl;
#endif
return 1;
}
int bdNodeManager::getDhtValue(bdNodeId *id, std::string key, std::string &value)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::getDhtValue() Id: ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << " key: " << key;
std::cerr << " ... ? TODO" << std::endl;
#endif
return 1;
}
/***** Add / Remove Callback Clients *****/
void bdNodeManager::addCallback(BitDhtCallback *cb)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::addCallback()";
std::cerr << std::endl;
#endif
/* search list */
std::list<BitDhtCallback *>::iterator it;
it = std::find(mCallbacks.begin(), mCallbacks.end(), cb);
if (it == mCallbacks.end())
{
/* add it */
mCallbacks.push_back(cb);
}
}
void bdNodeManager::removeCallback(BitDhtCallback *cb)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::removeCallback()";
std::cerr << std::endl;
#endif
/* search list */
std::list<BitDhtCallback *>::iterator it;
it = std::find(mCallbacks.begin(), mCallbacks.end(), cb);
if (it == mCallbacks.end())
{
/* not found! */
return;
}
it = mCallbacks.erase(it);
}
void bdNodeManager::addPeer(const bdId *id, uint32_t peerflags)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::addPeer() Overloaded (doing Callback)";
std::cerr << std::endl;
#endif
doNodeCallback(id, peerflags);
// call parent.
bdNode::addPeer(id, peerflags);
return;
}
void bdNodeManager::doNodeCallback(const bdId *id, uint32_t peerflags)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::doPeerCallback()";
std::cerr << std::endl;
#endif
/* search list */
std::list<BitDhtCallback *>::iterator it;
for(it = mCallbacks.begin(); it != mCallbacks.end(); it++)
{
(*it)->dhtNodeCallback(id, peerflags);
}
return;
}
void bdNodeManager::doPeerCallback(const bdNodeId *id, uint32_t status)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::doPeerCallback()";
std::cerr << std::endl;
#endif
/* search list */
std::list<BitDhtCallback *>::iterator it;
for(it = mCallbacks.begin(); it != mCallbacks.end(); it++)
{
(*it)->dhtPeerCallback(id, status);
}
return;
}
void bdNodeManager::doValueCallback(const bdNodeId *id, std::string key, uint32_t status)
{
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::doValueCallback()";
std::cerr << std::endl;
#endif
/* search list */
std::list<BitDhtCallback *>::iterator it;
for(it = mCallbacks.begin(); it != mCallbacks.end(); it++)
{
(*it)->dhtPeerCallback(id, status);
}
return;
}
/******************* Internals *************************/
int bdNodeManager::isBitDhtPacket(char *data, int size, struct sockaddr_in &from)
{
#ifdef DEBUG_MGR_PKT
std::cerr << "bdNodeManager::isBitDhtPacket() *******************************";
std::cerr << " from " << inet_ntoa(from.sin_addr);
std::cerr << ":" << ntohs(from.sin_port);
std::cerr << std::endl;
{
/* print the fucker... only way to catch bad ones */
std::ostringstream out;
for(int i = 0; i < size; i++)
{
if (isascii(data[i]))
{
out << data[i];
}
else
{
out << "[";
out << std::setw(2) << std::setfill('0')
<< std::hex << (uint32_t) data[i];
out << "]";
}
if ((i % 16 == 0) && (i != 0))
{
out << std::endl;
}
}
std::cerr << out.str();
}
std::cerr << "bdNodeManager::isBitDhtPacket() *******************************";
std::cerr << std::endl;
#endif
/* try to parse it! */
/* convert to a be_node */
be_node *node = be_decoden(data, size);
if (!node)
{
/* invalid decode */
#ifdef DEBUG_MGR
std::cerr << "bdNodeManager::isBitDhtPacket() be_decode failed. dropping";
std::cerr << std::endl;
std::cerr << "bdNodeManager::BadPacket ******************************";
std::cerr << " from " << inet_ntoa(from.sin_addr);
std::cerr << ":" << ntohs(from.sin_port);
std::cerr << std::endl;
{
/* print the fucker... only way to catch bad ones */
std::ostringstream out;
for(int i = 0; i < size; i++)
{
if (isascii(data[i]))
{
out << data[i];
}
else
{
out << "[";
out << std::setw(2) << std::setfill('0')
<< std::hex << (uint32_t) data[i];
out << "]";
}
if ((i % 16 == 0) && (i != 0))
{
out << std::endl;
}
}
std::cerr << out.str();
}
std::cerr << "bdNodeManager::BadPacket ******************************";
std::cerr << std::endl;
#endif
return 0;
}
/* find message type */
uint32_t beType = beMsgType(node);
int ans = (beType != BITDHT_MSG_TYPE_UNKNOWN);
be_free(node);
#ifdef DEBUG_MGR_PKT
if (ans)
{
std::cerr << "bdNodeManager::isBitDhtPacket() YES";
std::cerr << std::endl;
}
else
{
std::cerr << "bdNodeManager::isBitDhtPacket() NO: Unknown Type";
std::cerr << std::endl;
}
#endif
return ans;
}
bdDebugCallback::~bdDebugCallback()
{
}
int bdDebugCallback::dhtPeerCallback(const bdNodeId *id, uint32_t status)
{
std::cerr << "bdDebugCallback::dhtPeerCallback() Id: ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << " status: " << std::hex << status << std::dec << std::endl;
return 1;
}
int bdDebugCallback::dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status)
{
std::cerr << "bdDebugCallback::dhtValueCallback() Id: ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << " key: " << key;
std::cerr << " status: " << std::hex << status << std::dec << std::endl;
return 1;
}

View File

@ -0,0 +1,156 @@
#ifndef BITDHT_MANAGER_H
#define BITDHT_MANAGER_H
/*
* bitdht/bdmanager.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
/*******
* Node Manager.
******/
/******************************************
* 1) Maintains a list of ids to search for.
* 2) Sets up initial search for own node.
* 3) Checks on status of queries.
* 4) Callback on successful searches.
*
* This is pretty specific to RS requirements.
****/
#define BITDHT_PS_MASK_ACTIONS (0x000000ff)
#define BITDHT_PS_MASK_STATE (0x0000ff00)
#define BITDHT_PS_ACTION_SEARCHING (0x00000001)
#define BITDHT_PS_ACTION_WAITING (0x00000002)
#define BITDHT_PS_ACTION_PINGING (0x00000004)
#define BITDHT_PS_STATE_UNKNOWN (0x00000100)
#define BITDHT_PS_STATE_OFFLINE (0x00000200)
#define BITDHT_PS_STATE_ONLINE (0x00000400)
#define BITDHT_PS_STATE_CONNECTED (0x00000800)
#include "bdiface.h"
#include "bdnode.h"
class bdQueryPeer
{
public:
bdId mId;
uint32_t mStatus;
uint32_t mQFlags;
time_t mLastQuery;
time_t mLastFound;
};
#define BITDHT_MGR_STATE_STARTUP 1
#define BITDHT_MGR_STATE_ACTIVE 2
#define BITDHT_MGR_STATE_REFRESH 3
#define BITDHT_MGR_STATE_QUIET 4
#define MAX_STARTUP_TIME 10
#define MAX_REFRESH_TIME 30
#define BITDHT_MGR_QUERY_FAILURE 1
#define BITDHT_MGR_QUERY_PEER_OFFLINE 2
#define BITDHT_MGR_QUERY_PEER_UNREACHABLE 3
#define BITDHT_MGR_QUERY_PEER_ONLINE 4
/*** NB: Nothing in here is protected by mutexes
* must be done at a higher level!
***/
class bdNodeManager: public bdNode, public BitDhtInterface
{
public:
bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns);
void iteration();
/***** Functions to Call down to bdNodeManager ****/
/* Request DHT Peer Lookup */
/* Request Keyword Lookup */
virtual void addFindNode(bdNodeId *id, uint32_t mode);
virtual void removeFindNode(bdNodeId *id);
virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode);
/***** Add / Remove Callback Clients *****/
virtual void addCallback(BitDhtCallback *cb);
virtual void removeCallback(BitDhtCallback *cb);
/***** Get Results Details *****/
virtual int getDhtPeerAddress(bdNodeId *id, struct sockaddr_in &from);
virtual int getDhtValue(bdNodeId *id, std::string key, std::string &value);
/******************* Internals *************************/
// Overloaded from bdnode for external node callback.
virtual void addPeer(const bdId *id, uint32_t peerflags);
int isBitDhtPacket(char *data, int size, struct sockaddr_in &from);
private:
void doNodeCallback(const bdId *id, uint32_t peerflags);
void doPeerCallback(const bdNodeId *id, uint32_t status);
void doValueCallback(const bdNodeId *id, std::string key, uint32_t status);
int status();
int checkStatus();
int checkPingStatus();
int SearchOutOfDate();
std::map<bdNodeId, bdQueryPeer> mActivePeers;
std::list<BitDhtCallback *> mCallbacks;
uint32_t mMode;
time_t mModeTS;
bdDhtFunctions *mFns;
/* future node functions */
//addPeerPing(foundId);
//clearPing(it->first);
//PingStatus(it->first);
};
class bdDebugCallback: public BitDhtCallback
{
public:
~bdDebugCallback();
virtual int dhtPeerCallback(const bdNodeId *id, uint32_t status);
virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status);
};
#endif

View File

@ -0,0 +1,820 @@
/*
* bitdht/bdmsgs.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <stdio.h>
#include <string.h>
#include "bencode.h"
#include "bdmsgs.h"
int create_ping_message();
int response_ping_message();
int find_node_message();
int response_node_message();
int get_peers_message();
int response_peers_message();
int response_closestnodes_message();
/*
ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
*/
/****
* #define DEBUG_MSG_DUMP 1
* #define DEBUG_MSG_TYPE 1
* #define DEBUG_MSGS 1
****/
int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_create_ping_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_add_keypair(iddict, "id", idnode);
be_node *pingnode = be_create_str("ping");
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *qynode = be_create_str("q");
be_add_keypair(dict, "a", iddict);
be_add_keypair(dict, "q", pingnode);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", qynode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/*
Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re
*/
int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_response_ping_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *yqrnode = be_create_str("r");
be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len);
be_add_keypair(iddict, "id", idnode);
be_add_keypair(dict, "r", iddict);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "V", vnode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/*
find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}
bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe
*/
int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_find_node_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *yqrnode = be_create_str("q");
be_node *findnode = be_create_str("find_node");
be_add_keypair(iddict, "id", idnode);
be_add_keypair(iddict, "target", targetnode);
be_add_keypair(dict, "a", iddict);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "q", findnode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/*
Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}
bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re
*/
int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list<bdId> &nodes,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_resp_node_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *replydict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *peersnode = makeCompactNodeIdString(nodes);
be_node *yqrnode = be_create_str("r");
be_add_keypair(replydict, "id", idnode);
be_add_keypair(replydict, "nodes", peersnode);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "r", replydict);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
#ifdef DEBUG_MSG_DUMP
fprintf(stderr, "bitdht_resp_node_msg() len = %d / %d\n", blen, avail);
#endif
return blen;
}
/*
get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}
bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe
*/
int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_get_peers_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *yqrnode = be_create_str("q");
be_node *findnode = be_create_str("get_peers");
be_add_keypair(iddict, "id", idnode);
be_add_keypair(iddict, "info_hash", hashnode);
be_add_keypair(dict, "a", iddict);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "q", findnode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/*
Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}
bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re
*/
int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id,
bdToken *token, std::list<std::string> &values,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_peers_reply_hash_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *replydict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *tokennode = be_create_str_wlen((char *) token->data, token->len);
be_node *valuesnode = makeCompactPeerIds(values);
be_node *yqrnode = be_create_str("r");
be_add_keypair(replydict, "id", idnode);
be_add_keypair(replydict, "token", tokennode);
be_add_keypair(replydict, "values", valuesnode);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "r", replydict);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/**
Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}}
bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re
**/
int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id,
bdToken *token, std::list<bdId> &nodes,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_peers_reply_closest_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *replydict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *tokennode = be_create_str_wlen((char *) token->data, token->len);
be_node *peersnode = makeCompactNodeIdString(nodes);
be_node *yqrnode = be_create_str("r");
be_add_keypair(replydict, "id", idnode);
be_add_keypair(replydict, "token", tokennode);
be_add_keypair(replydict, "nodes", peersnode);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
be_add_keypair(dict, "r", replydict);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/**** FINAL TWO MESSAGES! ***/
/****
announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}}
bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe
****/
int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, uint32_t port, bdToken *token, char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_announce_peers_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN);
be_node *portnode = be_create_int(port);
be_node *tokennode = be_create_str_wlen((char *) token->data, token->len);
be_add_keypair(iddict, "id", idnode);
be_add_keypair(iddict, "info_hash", hashnode);
be_add_keypair(iddict, "port", portnode);
be_add_keypair(iddict, "token", tokennode);
be_node *announcenode = be_create_str("announce_peer");
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *qynode = be_create_str("q");
be_add_keypair(dict, "a", iddict);
be_add_keypair(dict, "q", announcenode);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", qynode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/*****
Response to Announce Peers = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re
****/
/****
* NB: This is the same as a PONG msg!
***/
int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id,
char *msg, int avail)
{
#ifdef DEBUG_MSGS
fprintf(stderr, "bitdht_response_ping_msg()\n");
#endif
be_node *dict = be_create_dict();
be_node *iddict = be_create_dict();
be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN);
be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len);
be_node *yqrnode = be_create_str("r");
be_add_keypair(iddict, "id", idnode);
be_add_keypair(dict, "r", iddict);
be_add_keypair(dict, "t", tidnode);
be_add_keypair(dict, "y", yqrnode);
#ifdef DEBUG_MSG_DUMP
/* dump answer */
be_dump(dict);
#endif
int blen = be_encode(dict, msg, avail);
be_free(dict);
return blen;
}
/************************ Parsing Messages *********************
*
*/
be_node *beMsgGetDictNode(be_node *node, const char *key)
{
/* make sure its a dictionary */
if (node->type != BE_DICT)
{
return NULL;
}
/* get dictionary entry 'y' */
int i;
for(i = 0; node->val.d[i].val; i++)
{
if (0 == strcmp(key, node->val.d[i].key))
{
return node->val.d[i].val;
}
}
return NULL;
}
int beMsgMatchString(be_node *n, const char *str, int len)
{
if (n->type != BE_STR)
{
return 0;
}
if (len != be_str_len(n))
{
return 0;
}
int i;
for(i = 0; i < len; i++)
{
if (n->val.s[i] != str[i])
return 0;
}
return 1;
}
uint32_t beMsgGetY(be_node *n)
{
be_node *val = beMsgGetDictNode(n, "y");
if (val->type != BE_STR)
{
return BE_Y_UNKNOWN;
}
if (val->val.s[0] == 'q')
{
return BE_Y_Q;
}
else if (val->val.s[0] == 'r')
{
return BE_Y_R;
}
return BE_Y_UNKNOWN;
}
uint32_t beMsgType(be_node *n)
{
/* check for
* y: q or r
*/
uint32_t beY = beMsgGetY(n);
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() beY: " << beY << std::endl;
#endif
if (beY == BE_Y_UNKNOWN)
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() UNKNOWN MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_UNKNOWN;
}
if (beY == BE_Y_Q) /* query */
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY MSG TYPE" << std::endl;
#endif
be_node *query = beMsgGetDictNode(n, "q");
if (beMsgMatchString(query, "ping", 4))
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY:ping MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_PING;
}
else if (beMsgMatchString(query, "find_node", 9))
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY:find_node MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_FIND_NODE;
}
else if (beMsgMatchString(query, "get_peers", 9))
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY:get_peers MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_GET_HASH;
}
else if (beMsgMatchString(query, "announce_peer", 13))
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY:announce_peer MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_POST_HASH;
}
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() QUERY:UNKNOWN MSG TYPE, dumping dict" << std::endl;
/* dump answer */
be_dump(n);
#endif
return BITDHT_MSG_TYPE_UNKNOWN;
}
if (beY != BE_Y_R)
{
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() UNKNOWN2 MSG TYPE" << std::endl;
#endif
return BITDHT_MSG_TYPE_UNKNOWN;
}
#ifdef DEBUG_MSG_TYPE
std::cerr << "bsMsgType() REPLY MSG TYPE" << std::endl;
#endif
/* otherwise a reply or - invalid
pong {"id":"mnopqrstuvwxyz123456"}
reply_neigh { "id":"0123456789abcdefghij", "nodes": "def456..."}}
reply_hash { "id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}
reply_near { "id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}
*/
be_node *reply = beMsgGetDictNode(n, "r");
if (!reply)
{
return BITDHT_MSG_TYPE_UNKNOWN;
}
be_node *id = beMsgGetDictNode(reply, "id");
be_node *token = beMsgGetDictNode(reply, "token");
be_node *values = beMsgGetDictNode(reply, "values");
be_node *nodes = beMsgGetDictNode(reply, "nodes");
if (!id)
{
return BITDHT_MSG_TYPE_UNKNOWN;
}
if (token && values)
{
/* reply hash */
return BITDHT_MSG_TYPE_REPLY_HASH;
}
else if (token && nodes)
{
/* reply near */
return BITDHT_MSG_TYPE_REPLY_NEAR;
}
else if (nodes)
{
/* reply neigh */
return BITDHT_MSG_TYPE_REPLY_NODE;
}
else
{
/* pong */
return BITDHT_MSG_TYPE_PONG;
}
/* TODO reply_post */
//return BITDHT_MSG_TYPE_REPLY_POST;
/* can't get here! */
return BITDHT_MSG_TYPE_UNKNOWN;
}
/* extract specific types here */
int beMsgGetToken(be_node *n, bdToken &token)
{
if (n->type != BE_STR)
{
return 0;
}
int len = be_str_len(n);
for(int i = 0; i < len; i++)
{
token.data[i] = n->val.s[i];
}
token.len = len;
return 1;
}
int beMsgGetNodeId(be_node *n, bdNodeId &nodeId)
{
if (n->type != BE_STR)
{
return 0;
}
int len = be_str_len(n);
if (len != BITDHT_KEY_LEN)
{
return 0;
}
for(int i = 0; i < len; i++)
{
nodeId.data[i] = n->val.s[i];
}
return 1;
}
be_node *makeCompactNodeIdString(std::list<bdId> &nodes)
{
int len = BITDHT_COMPACTNODEID_LEN * nodes.size();
std::string cni;
std::list<bdId>::iterator it;
for(it = nodes.begin(); it != nodes.end(); it++)
{
cni += encodeCompactNodeId(&(*it));
}
be_node *cninode = be_create_str_wlen((char *) cni.c_str(), len);
return cninode;
}
be_node *makeCompactPeerIds(std::list<std::string> &values)
{
be_node *valuesnode = be_create_list();
std::list<std::string>::iterator it;
for(it = values.begin(); it != values.end(); it++)
{
be_node *val1 = be_create_str_wlen((char *) it->c_str(), it->length());
be_add_list(valuesnode, val1);
}
return valuesnode;
}
int beMsgGetListBdIds(be_node *n, std::list<bdId> &nodes)
{
/* extract the string pointer, and size */
/* split into parts */
if (n->type != BE_STR)
{
return 0;
}
int len = be_str_len(n);
int count = len / BITDHT_COMPACTNODEID_LEN;
for(int i = 0; i < count; i++)
{
bdId id;
if (decodeCompactNodeId(&id, &(n->val.s[i*BITDHT_COMPACTNODEID_LEN]), BITDHT_COMPACTNODEID_LEN))
{
nodes.push_back(id);
}
}
return 1;
}
std::string encodeCompactNodeId(bdId *id)
{
std::string enc;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
enc += id->id.data[i];
}
/* convert ip address (already in network order) */
enc += encodeCompactPeerId(&(id->addr));
return enc;
}
int decodeCompactNodeId(bdId *id, char *enc, int len)
{
if (len < BITDHT_COMPACTNODEID_LEN)
{
return 0;
}
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
id->id.data[i] = enc[i];
}
char *ipenc = &(enc[BITDHT_COMPACTNODEID_LEN - BITDHT_COMPACTPEERID_LEN]);
if (!decodeCompactPeerId(&(id->addr), ipenc, BITDHT_COMPACTPEERID_LEN))
{
return 0;
}
return 1;
}
std::string encodeCompactPeerId(struct sockaddr_in *addr)
{
std::string encstr;
char enc[BITDHT_COMPACTPEERID_LEN];
uint32_t *ip = (uint32_t *) (enc);
uint16_t *port = (uint16_t *) (&enc[4]);
(*ip) = addr->sin_addr.s_addr;
(*port) = addr->sin_port;
encstr.append(enc, BITDHT_COMPACTPEERID_LEN);
return encstr;
}
int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len)
{
if (len < BITDHT_COMPACTPEERID_LEN)
return 0;
memset(addr, 0, sizeof(struct sockaddr_in));
uint32_t *ip = (uint32_t *) (enc);
uint16_t *port = (uint16_t *) (&enc[4]);
addr->sin_addr.s_addr = (*ip);
addr->sin_port = (*port);
return 1;
}
int beMsgGetListStrings(be_node *n, std::list<std::string> &values)
{
if (n->type != BE_LIST)
{
return 0;
}
for(int i = 0; n->val.l[i] != NULL; i++)
{
be_node *val = n->val.l[i];
if (val->type != BE_STR)
{
return 0;
}
int len = be_str_len(val);
std::string str;
str.append(val->val.s, len);
values.push_back(str);
}
return 1;
}
int beMsgGetUInt32(be_node *n, uint32_t *port)
{
if (n->type != BE_INT)
{
return 0;
}
*port = n->val.i;
return 1;
}

View File

@ -0,0 +1,111 @@
#ifndef BITDHT_MSGS_H
#define BITDHT_MSGS_H
/*
* bitdht/bdmsgs.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <stdio.h>
#include <inttypes.h>
#include <list>
#include "bencode.h"
#include "bdobj.h"
#include "bdpeer.h"
#define BITDHT_MSG_TYPE_UNKNOWN 0
#define BITDHT_MSG_TYPE_PING 1
#define BITDHT_MSG_TYPE_PONG 2
#define BITDHT_MSG_TYPE_FIND_NODE 3
#define BITDHT_MSG_TYPE_REPLY_NODE 4
#define BITDHT_MSG_TYPE_GET_HASH 5
#define BITDHT_MSG_TYPE_REPLY_HASH 6
#define BITDHT_MSG_TYPE_REPLY_NEAR 7
#define BITDHT_MSG_TYPE_POST_HASH 8
#define BITDHT_MSG_TYPE_REPLY_POST 9
#define BITDHT_COMPACTNODEID_LEN 26
#define BITDHT_COMPACTPEERID_LEN 6
#define BE_Y_UNKNOWN 0
#define BE_Y_R 1
#define BE_Y_Q 2
/****** Known BD Version Strings ******/
#define BITDHT_VID_RS1 1
#define BITDHT_VID_UT 2
int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, char *msg, int avail);
int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail);
int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, char *msg, int avail);
int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list<bdId> &nodes,
char *msg, int avail);
int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash,
char *msg, int avail);
int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id,
bdToken *token, std::list<std::string> &values,
char *msg, int avail);
int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id,
bdToken *token, std::list<bdId> &nodes,
char *msg, int avail);
int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash,
uint32_t port, bdToken *token, char *msg, int avail);
int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id,
char *msg, int avail);
//int response_peers_message()
//int response_closestnodes_message()
be_node *beMsgGetDictNode(be_node *node, const char *key);
int beMsgMatchString(be_node *n, const char *str, int len);
uint32_t beMsgGetY(be_node *n);
uint32_t beMsgType(be_node *n);
uint32_t convertBdVersionToVID(bdVersion *version);
be_node *makeCompactPeerIds(std::list<std::string> &values);
be_node *makeCompactNodeIdString(std::list<bdId> &nodes);
int beMsgGetToken(be_node *n, bdToken &token);
int beMsgGetNodeId(be_node *n, bdNodeId &nodeId);
int beMsgGetListBdIds(be_node *n, std::list<bdId> &nodes);
int beMsgGetListStrings(be_node *n, std::list<std::string> &values);
int beMsgGetUInt32(be_node *n, uint32_t *port);
/* Low Level conversion functions */
int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len);
std::string encodeCompactPeerId(struct sockaddr_in *addr);
int decodeCompactNodeId(bdId *id, char *enc, int len);
std::string encodeCompactNodeId(bdId *id);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,235 @@
#ifndef BITDHT_NODE_H
#define BITDHT_NODE_H
/*
* bitdht/bdnode.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdpeer.h"
#include "bdquery.h"
#include "bdstore.h"
#include "bdobj.h"
#include "bdhash.h"
#define BD_QUERY_NEIGHBOURS 1
#define BD_QUERY_HASH 2
/**********************************
* Running a node....
*
* run().
* loops through and checks out of date peers.
* handles searches.
* prints out dht Table.
*
The node handles the i/o traffic from peers.
It
ping, return
peers, return
hash store, return
hash get, return
respond queue.
query queue.
input -> call into recvFunction()
output -> call back to Udp().
*********/
class bdNodeNetMsg
{
public:
bdNodeNetMsg(char *data, int size, struct sockaddr_in *addr);
~bdNodeNetMsg();
void print(std::ostream &out);
char *data;
int mSize;
struct sockaddr_in addr;
};
class bdNode
{
public:
bdNode(bdNodeId *id, std::string dhtVersion, std::string bootfile,
bdDhtFunctions *fns);
// virtual so manager can do callback.
// peer flags defined in bdiface.h
virtual void addPeer(const bdId *id, uint32_t peerflags);
void printState();
void checkPotentialPeer(bdId *id);
void addPotentialPeer(bdId *id);
void addQuery(const bdNodeId *id, uint32_t qflags);
void clearQuery(const bdNodeId *id);
void QueryStatus(std::map<bdNodeId, bdQueryStatus> &statusMap);
void iteration();
void processRemoteQuery();
void updateStore();
/* interaction with outside world */
int outgoingMsg(struct sockaddr_in *addr, char *msg, int *len);
void incomingMsg(struct sockaddr_in *addr, char *msg, int len);
/* internal interaction with network */
void sendPkt(char *msg, int len, struct sockaddr_in addr);
void recvPkt(char *msg, int len, struct sockaddr_in addr);
/* output functions (send msg) */
void msgout_ping(bdId *id, bdToken *transId);
void msgout_pong(bdId *id, bdToken *transId);
void msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query);
void msgout_reply_find_node(bdId *id, bdToken *transId,
std::list<bdId> &peers);
void msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash);
void msgout_reply_hash(bdId *id, bdToken *transId,
bdToken *token, std::list<std::string> &values);
void msgout_reply_nearest(bdId *id, bdToken *transId,
bdToken *token, std::list<bdId> &peers);
void msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash,
uint32_t port, bdToken *token);
void msgout_reply_post(bdId *id, bdToken *transId);
/* input functions (once mesg is parsed) */
void msgin_ping(bdId *id, bdToken *token);
void msgin_pong(bdId *id, bdToken *transId, bdToken *versionId);
void msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query);
void msgin_reply_find_node(bdId *id, bdToken *transId,
std::list<bdId> &entries);
void msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *nodeid);
void msgin_reply_hash(bdId *id, bdToken *transId,
bdToken *token, std::list<std::string> &values);
void msgin_reply_nearest(bdId *id, bdToken *transId,
bdToken *token, std::list<bdId> &nodes);
void msgin_post_hash(bdId *id, bdToken *transId,
bdNodeId *info_hash, uint32_t port, bdToken *token);
void msgin_reply_post(bdId *id, bdToken *transId);
/* token handling */
void genNewToken(bdToken *token);
int queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type);
/* transId handling */
void genNewTransId(bdToken *token);
void registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType);
uint32_t checkIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType);
void cleanupTransIdRegister();
void getOwnId(bdNodeId *id);
void doStats();
void printStats(std::ostream &out);
void printQueries();
private:
bdNodeId mOwnId;
bdId mLikelyOwnId; // Try to workout own id address.
bdSpace mNodeSpace;
bdStore mStore;
std::string mDhtVersion;
bdDhtFunctions *mFns;
bdHashSpace mHashSpace;
std::list<bdQuery> mLocalQueries;
std::list<bdRemoteQuery> mRemoteQueries;
std::list<bdId> mPotentialPeers;
std::list<bdNodeNetMsg *> mOutgoingMsgs;
std::list<bdNodeNetMsg *> mIncomingMsgs;
// Statistics.
double mCounterOutOfDatePing;
double mCounterPings;
double mCounterPongs;
double mCounterQueryNode;
double mCounterQueryHash;
double mCounterReplyFindNode;
double mCounterReplyQueryHash;
double mCounterRecvPing;
double mCounterRecvPong;
double mCounterRecvQueryNode;
double mCounterRecvQueryHash;
double mCounterRecvReplyFindNode;
double mCounterRecvReplyQueryHash;
double mLpfOutOfDatePing;
double mLpfPings;
double mLpfPongs;
double mLpfQueryNode;
double mLpfQueryHash;
double mLpfReplyFindNode;
double mLpfReplyQueryHash;
double mLpfRecvPing;
double mLpfRecvPong;
double mLpfRecvQueryNode;
double mLpfRecvQueryHash;
double mLpfRecvReplyFindNode;
double mLpfRecvReplyQueryHash;
};
#endif // BITDHT_NODE_H

View File

@ -0,0 +1,51 @@
#include "bdobj.h"
/*
* bitdht/bdobj.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
void bdPrintTransId(std::ostream &out, bdToken *transId)
{
out << transId->data;
return;
}
void bdPrintToken(std::ostream &out, bdToken *token)
{
for(unsigned int i = 0; i < token->len; i++)
{
out << std::hex << (uint32_t) token->data[i];
}
out << std::dec;
}
void bdPrintCompactPeerId(std::ostream &out, std::string cpi)
{
out << "DummyCompactPeerId";
}

View File

@ -0,0 +1,61 @@
#ifndef BITDHT_OBJECTS_H
#define BITDHT_OBJECTS_H
/*
* bitdht/bdobj.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#define BITDHT_TOKEN_MAX_LEN 20
#include <iostream>
#include <inttypes.h>
class bdToken
{
public:
uint32_t len;
unsigned char data[BITDHT_TOKEN_MAX_LEN];
};
class bdCompactIds
{
public:
uint32_t len;
unsigned char data[BITDHT_TOKEN_MAX_LEN];
};
class bdVersion
{
public:
uint32_t len;
unsigned char data[BITDHT_TOKEN_MAX_LEN];
};
void bdPrintTransId(std::ostream &out, bdToken *transId);
void bdPrintToken(std::ostream &out, bdToken *transId);
void bdPrintCompactPeerId(std::ostream &out, std::string cpi);
#endif

View File

@ -0,0 +1,739 @@
/*
* bitdht/bdpeer.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdpeer.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <iomanip>
/**
* #define BITDHT_DEBUG 1
**/
bdId::bdId()
{
/* blank everything */
memset(&addr, 0, sizeof(struct sockaddr_in));
memset(&id.data, 0, BITDHT_KEY_LEN);
}
bdId::bdId(bdNodeId in_id, struct sockaddr_in in_addr)
{
addr = in_addr;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
id.data[i] = in_id.data[i];
}
};
void bdZeroNodeId(bdNodeId *id)
{
uint32_t *a_data = (uint32_t *) id->data;
for(int i = 0; i < BITDHT_KEY_INTLEN; i++)
{
a_data[i] = 0;
}
return;
}
int operator<(const bdNodeId &a, const bdNodeId &b)
{
#if 0
std::cerr << "operator<(");
bdPrintNodeId(std::cerr, &a);
std::cerr << ",";
bdPrintNodeId(std::cerr, &b);
std::cerr << ")" << std::endl;
#endif
uint8_t *a_data = (uint8_t *) a.data;
uint8_t *b_data = (uint8_t *) b.data;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
if (*a_data < *b_data)
{
//fprintf(stderr, "Return 1, at i = %d\n", i);
return 1;
}
else if (*a_data > *b_data)
{
//fprintf(stderr, "Return 0, at i = %d\n", i);
return 0;
}
a_data++;
b_data++;
}
//fprintf(stderr, "Return 0, at i = KEYLEN\n");
return 0;
}
#if 0
int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b)
{
/* else NodeIds the same - check id addresses */
if (a.sin_addr.s_addr < b.sin_addr.s_addr)
return 1;
if (b.sin_addr.s_addr > a.sin_addr.s_addr)
return 0;
if (a.sin_port < b.sin_port)
return 1;
return 0;
}
#endif
int operator<(const bdId &a, const bdId &b)
{
if (a.id < b.id)
return 1;
if (b.id < a.id)
return 0;
/* else NodeIds the same - check id addresses */
if (a.addr.sin_addr.s_addr < b.addr.sin_addr.s_addr)
return 1;
if (b.addr.sin_addr.s_addr > a.addr.sin_addr.s_addr)
return 0;
if (a.addr.sin_port < b.addr.sin_port)
return 1;
return 0;
}
int operator==(const bdNodeId &a, const bdNodeId &b)
{
uint8_t *a_data = (uint8_t *) a.data;
uint8_t *b_data = (uint8_t *) b.data;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
if (*a_data < *b_data)
{
return 0;
}
else if (*a_data > *b_data)
{
return 0;
}
a_data++;
b_data++;
}
return 1;
}
int operator==(const bdId &a, const bdId &b)
{
if (a.id == b.id)
return 1;
if ((a.addr.sin_addr.s_addr == b.addr.sin_addr.s_addr) &&
(a.addr.sin_port == b.addr.sin_port))
{
return 1;
}
return 0;
}
#if 0
void bdRandomId(bdId *id)
{
bdRandomNodeId(&(id->id));
id->addr.sin_addr.s_addr = rand();
id->addr.sin_port = rand();
return;
}
void bdRandomNodeId(bdNodeId *id)
{
uint32_t *a_data = (uint32_t *) id->data;
for(int i = 0; i < BITDHT_KEY_INTLEN; i++)
{
a_data[i] = rand();
}
return;
}
/* fills in dbNodeId r, with XOR of a and b */
int bdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r)
{
uint8_t *a_data = (uint8_t *) a->data;
uint8_t *b_data = (uint8_t *) b->data;
uint8_t *ans = (uint8_t *) r->data;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
*(ans++) = *(a_data++) ^ *(b_data++);
}
return 1;
}
void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *midId)
{
bdMetric dist;
/* get distance between a & c */
bdDistance(target, other, &dist);
/* generate Random Id */
bdRandomNodeId(midId);
/* zero bits of Random Id until under 1/2 of distance
* done in bytes for ease... matches one extra byte than distance = 0
* -> hence wierd order of operations
*/
bool done = false;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
midId->data[i] = target->data[i];
if (dist.data[i] != 0)
break;
}
}
std::string bdConvertToPrintable(std::string input)
{
std::ostringstream out;
for(uint32_t i = 0; i < input.length(); i++)
{
/* sensible chars */
if ((input[i] > 31) && (input[i] < 127))
{
out << input[i];
}
else
{
out << "[0x" << std::hex << (uint32_t) input[i] << "]";
out << std::dec;
}
}
return out.str();
}
void bdPrintNodeId(std::ostream &out, const bdNodeId *a)
{
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) (a->data)[i];
}
out << std::dec;
return;
}
void bdPrintId(std::ostream &out, const bdId *a)
{
bdPrintNodeId(out, &(a->id));
out << " ip:" << inet_ntoa(a->addr.sin_addr);
out << ":" << ntohs(a->addr.sin_port);
return;
}
/* returns 0-160 depending on bucket */
int bdBucketDistance(const bdNodeId *a, const bdNodeId *b)
{
bdMetric m;
bdDistance(a, b, &m);
return bdBucketDistance(&m);
}
/* returns 0-160 depending on bucket */
int bdBucketDistance(const bdMetric *m)
{
for(int i = 0; i < BITDHT_KEY_BITLEN; i++)
{
int bit = BITDHT_KEY_BITLEN - i - 1;
int byte = i / 8;
int bbit = 7 - (i % 8);
unsigned char comp = (1 << bbit);
#ifdef BITDHT_DEBUG
fprintf(stderr, "bdBucketDistance: bit:%d byte:%d bbit:%d comp:%x, data:%x\n", bit, byte, bbit, comp, m->data[byte]);
#endif
if (comp & m->data[byte])
{
return bit;
}
}
return 0;
}
#endif
bdBucket::bdBucket()
{
return;
}
bdSpace::bdSpace(bdNodeId *ownId, bdDhtFunctions *fns)
:mOwnId(*ownId), mFns(fns)
{
/* make some space for data */
buckets.resize(mFns->bdNumBuckets());
return;
}
int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, std::list<bdId> excluding, std::multimap<bdMetric, bdId> &nearest)
{
std::multimap<bdMetric, bdId> closest;
std::multimap<bdMetric, bdId>::iterator mit;
bdMetric dist;
mFns->bdDistance(id, &(mOwnId), &dist);
#ifdef DEBUG_BD_SPACE
int bucket = mFns->bdBucketDistance(&dist);
std::cerr << "bdSpace::find_nearest_nodes(NodeId:";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << " Number: " << number;
std::cerr << " Query Bucket #: " << bucket;
std::cerr << std::endl;
#endif
std::vector<bdBucket>::iterator it;
std::list<bdPeer>::iterator eit;
/* iterate through the buckets, and sort by distance */
for(it = buckets.begin(); it != buckets.end(); it++)
{
for(eit = it->entries.begin(); eit != it->entries.end(); eit++)
{
mFns->bdDistance(id, &(eit->mPeerId.id), &dist);
closest.insert(std::pair<bdMetric, bdId>(dist, eit->mPeerId));
#if 0
std::cerr << "Added NodeId: ";
bdPrintNodeId(std::cerr, &(eit->mPeerId.id));
std::cerr << " Metric: ";
bdPrintNodeId(std::cerr, &(dist));
std::cerr << std::endl;
#endif
}
}
/* take the first number of nodes */
int i = 0;
for(mit = closest.begin(); (mit != closest.end()) && (i < number); mit++, i++)
{
mFns->bdDistance(&(mOwnId), &(mit->second.id), &dist);
#ifdef DEBUG_BD_SPACE
int iBucket = mFns->bdBucketDistance(&(mit->first));
std::cerr << "Closest " << i << ": ";
mFns->bdPrintNodeId(std::cerr, &(mit->second.id));
std::cerr << " Bucket: " << iBucket;
std::cerr << std::endl;
#endif
#if 0
std::cerr << "\tNodeId: ";
mFns->bdPrintNodeId(std::cerr, &(mit->second.id));
std::cerr << std::endl;
std::cerr << "\tOwn Id: ";
mFns->bdPrintNodeId(std::cerr, &(mOwnId));
std::cerr << std::endl;
std::cerr << " Us Metric: ";
mFns->bdPrintNodeId(std::cerr, &dist);
std::cerr << " Bucket: " << oBucket;
std::cerr << std::endl;
std::cerr << "\tFindId: ";
mFns->bdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
std::cerr << " Id Metric: ";
mFns->bdPrintNodeId(std::cerr, &(mit->first));
std::cerr << " Bucket: " << iBucket;
std::cerr << std::endl;
#endif
nearest.insert(*mit);
}
#ifdef DEBUG_BD_SPACE
std::cerr << "#Nearest: " << (int) nearest.size();
std::cerr << " #Closest: " << (int) closest.size();
std::cerr << " #Requested: " << number;
std::cerr << std::endl << std::endl;
#endif
return 1;
}
int bdSpace::out_of_date_peer(bdId &id)
{
/*
*
*/
std::map<bdMetric, bdId> closest;
std::map<bdMetric, bdId>::iterator mit;
std::vector<bdBucket>::iterator it;
std::list<bdPeer>::iterator eit;
time_t ts = time(NULL);
/* iterate through the buckets, and sort by distance */
for(it = buckets.begin(); it != buckets.end(); it++)
{
for(eit = it->entries.begin(); eit != it->entries.end(); eit++)
{
/* timeout on last send time! */
if (ts - eit->mLastSendTime > BITDHT_MAX_SEND_PERIOD )
{
id = eit->mPeerId;
eit->mLastSendTime = ts;
return 1;
}
}
}
return 0;
}
/* Called to add or update peer.
* sorts bucket lists by lastRecvTime.
* updates requested node.
*/
/* peer flags
* order is important!
* higher bits = more priority.
* BITDHT_PEER_STATUS_RECVPONG
* BITDHT_PEER_STATUS_RECVNODES
* BITDHT_PEER_STATUS_RECVHASHES
* BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx)
* BITDHT_PEER_STATUS_DHT_APPL (XXRSxx)
* BITDHT_PEER_STATUS_DHT_VERSION (XXxx50)
*
*/
int bdSpace::add_peer(const bdId *id, uint32_t peerflags)
{
/* find the peer */
bool add = false;
time_t ts = time(NULL);
#ifdef DEBUG_BD_SPACE
fprintf(stderr, "bdSpace::add_peer()\n");
#endif
/* calculate metric */
bdMetric met;
mFns->bdDistance(&(mOwnId), &(id->id), &met);
int bucket = mFns->bdBucketDistance(&met);
#ifdef DEBUG_BD_SPACE
fprintf(stderr, "peer:");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, " bucket: %d", bucket);
fprintf(stderr, "\n");
#endif
/* select correct bucket */
bdBucket &buck = buckets[bucket];
std::list<bdPeer>::iterator it;
/* calculate the score for this new peer */
uint32_t minScore = peerflags;
/* loop through ids, to find it */
for(it = buck.entries.begin(); it != buck.entries.end(); it++)
{
if (*id == it->mPeerId)
// should check addr too!
{
bdPeer peer = *it;
it = buck.entries.erase(it);
peer.mLastRecvTime = ts;
peer.mPeerFlags |= peerflags; /* must be cumulative ... so can do online, replynodes, etc */
buck.entries.push_back(peer);
#ifdef DEBUG_BD_SPACE
std::cerr << "Peer already in bucket: moving to back of the list" << std::endl;
#endif
return 1;
}
/* find lowest score */
if (it->mPeerFlags < minScore)
{
minScore = it->mPeerFlags;
}
}
/* not in the list! */
if (buck.entries.size() < mFns->bdNodesPerBucket())
{
#ifdef DEBUG_BD_SPACE
std::cerr << "Bucket not full: allowing add" << std::endl;
#endif
add = true;
}
else
{
/* check head of list */
bdPeer &peer = buck.entries.front();
if (peer.mLastRecvTime - ts > BITDHT_MAX_RECV_PERIOD)
{
#ifdef DEBUG_BD_SPACE
std::cerr << "Dropping Out-of-Date peer in bucket" << std::endl;
#endif
buck.entries.pop_front();
add = true;
}
else if (peerflags > minScore)
{
/* find one to drop */
for(it = buck.entries.begin(); it != buck.entries.end(); it++)
{
if (it->mPeerFlags == minScore)
{
/* delete low priority peer */
it = buck.entries.erase(it);
add = true;
break;
}
}
#ifdef DEBUG_BD_SPACE
std::cerr << "Inserting due to Priority: minScore: " << minScore
<< " new Peer Score: " << peerscore << << std::endl;
#endif
}
else
{
#ifdef DEBUG_BD_SPACE
std::cerr << "No Out-Of-Date peers in bucket... dropping new entry" << std::endl;
#endif
}
}
if (add)
{
bdPeer newPeer;
newPeer.mPeerId = *id;
newPeer.mLastRecvTime = ts;
newPeer.mLastSendTime = ts; //????
newPeer.mPeerFlags = peerflags;
buck.entries.push_back(newPeer);
#ifdef DEBUG_BD_SPACE
#endif
/* useful debug */
std::cerr << "bdSpace::add_peer() Added Bucket[";
std::cerr << bucket << "] Entry: ";
mFns->bdPrintId(std::cerr, id);
std::cerr << std::endl;
}
return add;
}
/* print tables.
*/
int bdSpace::printDHT()
{
std::map<bdMetric, bdId> closest;
std::map<bdMetric, bdId>::iterator mit;
std::vector<bdBucket>::iterator it;
std::list<bdPeer>::iterator eit;
fprintf(stderr, "bdSpace::printDHT()\n");
/* iterate through the buckets, and sort by distance */
int i = 0;
for(it = buckets.begin(); it != buckets.end(); it++, i++)
{
if (it->entries.size() > 0)
{
fprintf(stderr, "Bucket %d ----------------------------\n", i);
}
for(eit = it->entries.begin(); eit != it->entries.end(); eit++)
{
bdMetric dist;
mFns->bdDistance(&(mOwnId), &(eit->mPeerId.id), &dist);
fprintf(stderr, " Metric: ");
mFns->bdPrintNodeId(std::cerr, &(dist));
fprintf(stderr, " Id: ");
mFns->bdPrintId(std::cerr, &(eit->mPeerId));
fprintf(stderr, " PeerFlags: %08x", eit->mPeerFlags);
fprintf(stderr, "\n");
}
}
fprintf(stderr, "--------------------------------------\n");
fprintf(stderr, "Summary ------------------------------\n");
/* little summary */
unsigned long long sum = 0;
unsigned long long no_peers = 0;
uint32_t count = 0;
bool doPrint = false;
bool doAvg = false;
i = 0;
for(it = buckets.begin(); it != buckets.end(); it++, i++)
{
int size = it->entries.size();
int shift = BITDHT_KEY_BITLEN - i;
bool toBig = false;
if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1)
{
toBig = true;
shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1;
}
unsigned long long no_nets = ((unsigned long long) 1 << shift);
/* use doPrint so it acts as a single switch */
if (size && !doAvg && !doPrint)
{
doAvg = true;
}
if (size && !doPrint)
{
doPrint = true;
}
if (size == 0)
{
/* reset counters - if empty slot - to discount outliers in average */
sum = 0;
no_peers = 0;
count = 0;
}
if (doPrint)
{
if (size)
fprintf(stderr, "Bucket %d: %d peers: ", i, size);
#ifdef BITDHT_DEBUG
else
fprintf(stderr, "Bucket %d: %d peers: ", i, size);
#endif
}
if (toBig)
{
if (size)
{
if (doPrint)
fprintf(stderr, "Estimated NetSize >> %llu\n", no_nets);
}
else
{
#ifdef BITDHT_DEBUG
if (doPrint)
fprintf(stderr, " Bucket = Net / >> %llu\n", no_nets);
#endif
}
}
else
{
no_peers = no_nets * size;
if (size)
{
if (doPrint)
fprintf(stderr, "Estimated NetSize = %llu\n", no_peers);
}
else
{
#ifdef BITDHT_DEBUG
if (doPrint)
fprintf(stderr, " Bucket = Net / %llu\n", no_nets);
#endif
}
}
if (doPrint && doAvg && !toBig)
{
if (size == mFns->bdNodesPerBucket())
{
/* last average */
doAvg = false;
}
if (no_peers != 0)
{
sum += no_peers;
count++;
#ifdef BITDHT_DEBUG
fprintf(stderr, "Est: %d: %llu => %llu / %d\n",
i, no_peers, sum, count);
#endif
}
}
}
if (count == 0)
{
fprintf(stderr, "Zero Network Size (count = 0)\n");
}
else
{
fprintf(stderr, "Estimated Network Size = (%llu / %d) = %llu\n", sum, count, sum / count);
}
return 1;
}

View File

@ -0,0 +1,171 @@
#ifndef BITDHT_PEER_H
#define BITDHT_PEER_H
/*
* bitdht/bdpeer.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdiface.h"
/*******
* These type of parameters are now DHT Function dependent
*
#define BITDHT_BUCKET_SIZE 20
#define BITDHT_BUCKET_SIZE_BITS 5
#define BITDHT_N_BUCKETS BITDHT_KEY_BITLEN
*
*
***/
/***
* DEFINED in bdiface.h
* #define BITDHT_KEY_LEN 20
* #define BITDHT_KEY_INTLEN 5
* #define BITDHT_KEY_BITLEN 160
***/
#define BITDHT_ULLONG_BITS 64
#define BITDHT_MAX_SEND_PERIOD 600 // retry every 10 secs.
#define BITDHT_MAX_RECV_PERIOD 1500 // out-of-date
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <list>
#include <string>
#include <map>
#include <vector>
/****
* DEFINED in bdiface.h
*
* class bdNodeId
* {
* public:
* unsigned char data[BITDHT_KEY_LEN];
* };
****/
/****
* DEFINED in bdiface.h
*
class bdMetric: public bdNodeId {};
class bdId
{
public:
bdId();
bdId(bdNodeId in_id, struct sockaddr_in in_addr);
struct sockaddr_in addr;
bdNodeId id;
};
*
*********/
//void bdRandomNodeId(bdNodeId *id);
// Only Functions that are common for all Dhts.
// zero, basic comparisons..
void bdZeroNodeId(bdNodeId *id);
//void bdRandomId(bdId *id);
//int bdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r);
//int bdBucketDistance(const bdMetric *m);
//int bdBucketDistance(const bdNodeId *a, const bdNodeId *b);
//int operator<(const bdMetric &a, const bdMetric &b);
//int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b);
int operator<(const bdNodeId &a, const bdNodeId &b);
int operator<(const bdId &a, const bdId &b);
int operator==(const bdNodeId &a, const bdNodeId &b);
int operator==(const bdId &a, const bdId &b);
//void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid);
//void bdPrintId(std::ostream &out, const bdId *a);
//void bdPrintNodeId(std::ostream &out, const bdNodeId *a);
//std::string bdConvertToPrintable(std::string input);
class bdPeer
{
public:
bdId mPeerId;
uint32_t mPeerFlags;
time_t mLastSendTime;
time_t mLastRecvTime;
};
class bdBucket
{
public:
bdBucket();
/* list so we can queue properly */
std::list<bdPeer> entries;
};
class bdSpace
{
public:
bdSpace(bdNodeId *ownId, bdDhtFunctions *fns);
/* accessors */
int find_nearest_nodes(const bdNodeId *id, int number,
std::list<bdId> excluding, std::multimap<bdMetric, bdId> &nearest);
int out_of_date_peer(bdId &id); // side-effect updates, send flag on peer.
int add_peer(const bdId *id, uint32_t mode);
int printDHT();
/* to add later */
int updateOwnId(bdNodeId *newOwnId);
private:
std::vector<bdBucket> buckets;
bdNodeId mOwnId;
bdDhtFunctions *mFns;
};
#endif

View File

@ -0,0 +1,577 @@
/*
* bitdht/bdquery.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdquery.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
/**
* #define DEBUG_QUERY 1
**/
//#define DEBUG_QUERY 1
#define EXPECTED_REPLY 10
#define QUERY_IDLE_RETRY_PEER_PERIOD (mFns->bdNodesPerBucket() * 15)
/************************************************************
* bdQuery logic:
* 1) as replies come in ... maintain list of M closest peers to ID.
* 2) select non-queried peer from list, and query.
* 3) halt when we have asked all M closest peers about the ID.
*
* Flags can be set to disguise the target of the search.
* This involves
*/
bdQuery::bdQuery(const bdNodeId *id, std::list<bdId> &startList, uint32_t queryFlags, bdDhtFunctions *fns)
{
/* */
mId = *id;
mFns = fns;
std::list<bdId>::iterator it;
for(it = startList.begin(); it != startList.end(); it++)
{
bdPeer peer;
peer.mLastSendTime = 0;
peer.mLastRecvTime = 0;
peer.mPeerId = *it;
bdMetric dist;
mFns->bdDistance(&mId, &(peer.mPeerId.id), &dist);
mClosest.insert(std::pair<bdMetric, bdPeer>(dist, peer));
}
mState = BITDHT_QUERY_QUERYING;
mQueryFlags = queryFlags;
mQueryTS = time(NULL);
/* setup the limit of the search
* by default it is setup to 000000 = exact match
*/
bdZeroNodeId(&mLimit);
}
bool bdQuery::result(std::list<bdId> &answer)
{
/* get all the matches to our query */
std::multimap<bdMetric, bdPeer>::iterator sit, eit;
sit = mClosest.begin();
eit = mClosest.upper_bound(mLimit);
int i = 0;
for(; sit != eit; sit++, i++)
{
answer.push_back(sit->second.mPeerId);
}
return (i > 0);
}
int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId)
{
if ((mState != BITDHT_QUERY_QUERYING) && !(mQueryFlags & BITDHT_QFLAGS_DO_IDLE))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Query is done\n");
#endif
return 0;
}
/* search through through list, find closest not queried */
time_t now = time(NULL);
bool notFinished = false;
std::multimap<bdMetric, bdPeer>::iterator it;
for(it = mClosest.begin(); it != mClosest.end(); it++)
{
bool queryPeer = false;
/* if never queried */
if (it->second.mLastSendTime == 0)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Found non-sent peer. queryPeer = true : ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
std::cerr << std::endl;
#endif
queryPeer = true;
}
/* re-request every so often */
if ((mQueryFlags & BITDHT_QFLAGS_DO_IDLE) && (now - it->second.mLastSendTime > QUERY_IDLE_RETRY_PEER_PERIOD))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Found out-of-date. queryPeer = true : ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
std::cerr << std::endl;
#endif
queryPeer = true;
}
/* expecting every peer to be up-to-date is too hard...
* enough just to have received lists from each
* - replacement policy will still work.
*/
if (it->second.mLastRecvTime == 0)
//if (it->second.mLastRecvTime < it->second.mLastSendTime)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Never Received: notFinished = true: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
std::cerr << std::endl;
#endif
notFinished = true;
}
if (queryPeer)
{
id = it->second.mPeerId;
it->second.mLastSendTime = now;
if (mQueryFlags & BITDHT_QFLAGS_DISGUISE)
{
/* calc Id mid point between Target and Peer */
bdNodeId midRndId;
mFns->bdRandomMidId(&mId, &(id.id), &midRndId);
targetNodeId = midRndId;
}
else
{
targetNodeId = mId;
}
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Querying Peer: ");
mFns->bdPrintId(std::cerr, &id);
std::cerr << std::endl;
#endif
return 1;
}
}
/* allow query to run for a minimal amount of time
* This is important as startup - when we might not have any peers.
* Probably should be handled elsewhere.
*/
time_t age = now - mQueryTS;
if (age < BITDHT_MIN_QUERY_AGE)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n");
#endif
return 0;
}
if (age > BITDHT_MAX_QUERY_AGE)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n");
#endif
/* fall through and stop */
}
else if ((mClosest.size() < mFns->bdNodesPerBucket()) || (notFinished))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() notFinished | !size(): Query not finished / No Query\n");
#endif
/* not full yet... */
return 0;
}
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Finished\n");
#endif
/* if we get here - query finished */
/* check if we found the node */
if (mClosest.size() > 0)
{
if ((mClosest.begin()->second).mPeerId.id == mId)
{
mState = BITDHT_QUERY_SUCCESS;
}
else if ((mPotentialClosest.begin()->second).mPeerId.id == mId)
{
mState = BITDHT_QUERY_PEER_UNREACHABLE;
}
else
{
mState = BITDHT_QUERY_FOUND_CLOSEST;
}
}
else
{
mState = BITDHT_QUERY_FAILURE;
}
return 0;
}
int bdQuery::addPeer(const bdId *id, uint32_t mode)
{
bdMetric dist;
time_t ts = time(NULL);
mFns->bdDistance(&mId, &(id->id), &dist);
#ifdef DEBUG_QUERY
fprintf(stderr, "bdQuery::addPeer(");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, ", %u)\n", mode);
#endif
std::multimap<bdMetric, bdPeer>::iterator it, sit, eit;
sit = mClosest.lower_bound(dist);
eit = mClosest.upper_bound(dist);
int i = 0;
int actualCloser = 0;
int toDrop = 0;
for(it = mClosest.begin(); it != sit; it++, i++, actualCloser++)
{
time_t sendts = ts - it->second.mLastSendTime;
bool hasSent = (it->second.mLastSendTime != 0);
//bool hasReply = (it->second.mLastRecvTime != 0);
bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime);
if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY))
{
i--; /* dont count this one */
toDrop++;
}
}
// Counts where we are.
#ifdef DEBUG_QUERY
fprintf(stderr, "Searching.... %di = %d - %d peers closer than this one\n", i, actualCloser, toDrop);
#endif
if (i > mFns->bdNodesPerBucket() - 1)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Distance to far... dropping\n");
#endif
/* drop it */
return 0;
}
for(it = sit; it != eit; it++, i++)
{
/* full id check */
if (it->second.mPeerId == *id)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer Already here!\n");
#endif
if (mode & BITDHT_PEER_STATUS_RECV_NODES)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Updating LastRecvTime\n");
#endif
it->second.mLastRecvTime = ts;
}
return 1;
}
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer not in Query\n");
#endif
/* firstly drop unresponded (bit ugly - but hard structure to extract from) */
int j;
for(j = 0; j < toDrop; j++)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Dropping Peer that dont reply\n");
#endif
bool removed = false;
for(it = mClosest.begin(); (!removed) && (it != mClosest.end()); it++)
{
time_t sendts = ts - it->second.mLastSendTime;
bool hasSent = (it->second.mLastSendTime != 0);
//bool hasReply = (it->second.mLastRecvTime != 0);
bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime);
if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Dropped: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
#endif
mClosest.erase(it);
removed = true;
}
}
}
/* trim it back */
while(mClosest.size() > (uint32_t) (mFns->bdNodesPerBucket() - 1))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mClosest.end();
if (mClosest.begin() != mClosest.end())
{
it--;
#ifdef DEBUG_QUERY
fprintf(stderr, "Removing Furthest Peer: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
#endif
mClosest.erase(it);
}
}
fprintf(stderr, "bdQuery::addPeer(): Closer Peer!: ");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, "\n");
/* add it in */
bdPeer peer;
peer.mPeerId = *id;
peer.mLastSendTime = 0;
peer.mLastRecvTime = 0;
if (mode & BITDHT_PEER_STATUS_RECV_NODES)
{
peer.mLastRecvTime = ts;
}
mClosest.insert(std::pair<bdMetric, bdPeer>(dist, peer));
return 1;
}
/* we also want to track unreachable node ... this allows us
* to detect if peer are online - but uncontactible by dht.
*
* simple list of closest.
*/
int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode)
{
bdMetric dist;
time_t ts = time(NULL);
mFns->bdDistance(&mId, &(id->id), &dist);
#ifdef DEBUG_QUERY
fprintf(stderr, "bdQuery::addPotentialPeer(");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, ", %u)\n", mode);
#endif
/* first we check if this is a worthy potential peer....
* if it is already in mClosest -> false. old peer.
* if it is > mClosest.rbegin() -> false. too far way.
*/
int retval = 1;
std::multimap<bdMetric, bdPeer>::iterator it, sit, eit;
sit = mClosest.lower_bound(dist);
eit = mClosest.upper_bound(dist);
for(it = sit; it != eit; it++)
{
if (it->second.mPeerId == *id)
{
/* already there */
retval = 0;
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer already in mClosest\n");
#endif
}
//empty loop.
}
/* check if outside range, & bucket is full */
if ((sit == mClosest.end()) && (mClosest.size() >= mFns->bdNodesPerBucket()))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer to far away for Potential\n");
#endif
retval = 0; /* too far way */
}
/* return if false; */
if (!retval)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Not a Potential Peer!\n");
#endif
return retval;
}
/* finally if a worthy & new peer -> add into potential closest
* and repeat existance tests with PotentialPeers
*/
sit = mPotentialClosest.lower_bound(dist);
eit = mPotentialClosest.upper_bound(dist);
int i = 0;
for(it = mPotentialClosest.begin(); it != sit; it++, i++)
{
//empty loop.
}
if (i > mFns->bdNodesPerBucket() - 1)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Distance to far... dropping\n");
fprintf(stderr, "Flagging as Potential Peer!\n");
#endif
/* outside the list - so we won't add to mPotentialClosest
* but inside mClosest still - so should still try it
*/
retval = 1;
return retval;
}
for(it = sit; it != eit; it++, i++)
{
if (it->second.mPeerId == *id)
{
/* this means its already been pinged */
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer Already here in mPotentialClosest!\n");
#endif
if (mode & BITDHT_PEER_STATUS_RECV_NODES)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Updating LastRecvTime\n");
#endif
it->second.mLastRecvTime = ts;
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Not a Potential Peer!\n");
#endif
retval = 0;
return retval;
}
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer not in Query\n");
#endif
/* trim it back */
while(mPotentialClosest.size() > (uint32_t) (mFns->bdNodesPerBucket() - 1))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mPotentialClosest.end();
if (mPotentialClosest.begin() != mPotentialClosest.end())
{
it--;
#ifdef DEBUG_QUERY
fprintf(stderr, "Removing Furthest Peer: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
#endif
mPotentialClosest.erase(it);
}
}
fprintf(stderr, "bdQuery::addPotentialPeer(): Closer Peer!: ");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, "\n");
/* add it in */
bdPeer peer;
peer.mPeerId = *id;
peer.mLastSendTime = 0;
peer.mLastRecvTime = ts;
mPotentialClosest.insert(std::pair<bdMetric, bdPeer>(dist, peer));
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Potential Peer!\n");
#endif
retval = 1;
return retval;
}
/* print query.
*/
int bdQuery::printQuery()
{
fprintf(stderr, "bdQuery::printQuery()\n");
time_t ts = time(NULL);
fprintf(stderr, "Query for: ");
mFns->bdPrintNodeId(std::cerr, &mId);
fprintf(stderr, " Query State: %d", mState);
fprintf(stderr, "\n");
fprintf(stderr, "Closest Available Peers:\n");
std::multimap<bdMetric, bdPeer>::iterator it;
for(it = mClosest.begin(); it != mClosest.end(); it++)
{
fprintf(stderr, "Id: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first)));
fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime);
fprintf(stderr, "\n");
}
fprintf(stderr, "\nClosest Potential Peers:\n");
for(it = mPotentialClosest.begin(); it != mPotentialClosest.end(); it++)
{
fprintf(stderr, "Id: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first)));
fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime);
fprintf(stderr, "\n");
}
return 1;
}
/********************************* Remote Query **************************************/
bdRemoteQuery::bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type)
:mId(*id), mQuery(*query), mTransId(*transId), mQueryType(query_type)
{
mQueryTS = time(NULL);
}

View File

@ -0,0 +1,98 @@
#ifndef BITDHT_QUERY_H
#define BITDHT_QUERY_H
/*
* bitdht/bdquery.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdiface.h"
#include "bdpeer.h"
#include "bdobj.h"
/* Query result flags are in bdiface.h */
#define BITDHT_MIN_QUERY_AGE 10
#define BITDHT_MAX_QUERY_AGE 300
class bdQuery
{
public:
bdQuery(const bdNodeId *id, std::list<bdId> &startList, uint32_t queryFlags,
bdDhtFunctions *fns);
// get the answer.
bool result(std::list<bdId> &answer);
// returning results get passed to all queries.
//void addNode(const bdId *id, int mode);
int nextQuery(bdId &id, bdNodeId &targetId);
int addPeer(const bdId *id, uint32_t mode);
int addPotentialPeer(const bdId *id, uint32_t mode);
int printQuery();
// searching for
bdNodeId mId;
bdMetric mLimit;
uint32_t mState;
time_t mQueryTS;
uint32_t mQueryFlags;
private:
// closest peers
std::multimap<bdMetric, bdPeer> mClosest;
std::multimap<bdMetric, bdPeer> mPotentialClosest;
bdDhtFunctions *mFns;
};
class bdQueryStatus
{
public:
uint32_t mStatus;
uint32_t mQFlags;
std::list<bdId> mResults;
};
/* this is just a container class.
* we locally seach for this, once then discard.
*/
class bdRemoteQuery
{
public:
bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type);
bdId mId;
bdNodeId mQuery;
bdToken mTransId;
uint32_t mQueryType;
time_t mQueryTS;
};
#endif

View File

@ -0,0 +1,253 @@
/*
* bitdht/bdstddht.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdstddht.h"
#include "bdpeer.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/**
* #define BITDHT_DEBUG 1
**/
void bdStdRandomId(bdId *id)
{
bdStdRandomNodeId(&(id->id));
id->addr.sin_addr.s_addr = rand();
id->addr.sin_port = rand();
return;
}
void bdStdRandomNodeId(bdNodeId *id)
{
uint32_t *a_data = (uint32_t *) id->data;
for(int i = 0; i < BITDHT_KEY_INTLEN; i++)
{
a_data[i] = rand();
}
return;
}
void bdStdZeroNodeId(bdNodeId *id)
{
uint32_t *a_data = (uint32_t *) id->data;
for(int i = 0; i < BITDHT_KEY_INTLEN; i++)
{
a_data[i] = 0;
}
return;
}
uint32_t bdStdLikelySameNode(const bdId *n1, const bdId *n2)
{
if (*n1 == *n2)
{
return 1;
}
return 0;
}
/* fills in bdNodeId r, with XOR of a and b */
int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r)
{
uint8_t *a_data = (uint8_t *) a->data;
uint8_t *b_data = (uint8_t *) b->data;
uint8_t *ans = (uint8_t *) r->data;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
*(ans++) = *(a_data++) ^ *(b_data++);
}
return 1;
}
void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *midId)
{
bdMetric dist;
/* get distance between a & c */
bdStdDistance(target, other, &dist);
/* generate Random Id */
bdStdRandomNodeId(midId);
/* zero bits of Random Id until under 1/2 of distance
* done in bytes for ease... matches one extra byte than distance = 0
* -> hence wierd order of operations
*/
//bool done = false;
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
midId->data[i] = target->data[i];
if (dist.data[i] != 0)
break;
}
}
std::string bdStdConvertToPrintable(std::string input)
{
std::ostringstream out;
for(uint32_t i = 0; i < input.length(); i++)
{
/* sensible chars */
if ((input[i] > 31) && (input[i] < 127))
{
out << input[i];
}
else
{
out << "[0x" << std::hex << (uint32_t) input[i] << "]";
out << std::dec;
}
}
return out.str();
}
void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a)
{
for(int i = 0; i < BITDHT_KEY_LEN; i++)
{
out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) (a->data)[i];
}
out << std::dec;
return;
}
void bdStdPrintId(std::ostream &out, const bdId *a)
{
bdStdPrintNodeId(out, &(a->id));
out << " ip:" << inet_ntoa(a->addr.sin_addr);
out << ":" << ntohs(a->addr.sin_port);
return;
}
/* returns 0-160 depending on bucket */
int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b)
{
bdMetric m;
bdStdDistance(a, b, &m);
return bdStdBucketDistance(&m);
}
/* returns 0-160 depending on bucket */
int bdStdBucketDistance(const bdMetric *m)
{
for(int i = 0; i < BITDHT_KEY_BITLEN; i++)
{
int bit = BITDHT_KEY_BITLEN - i - 1;
int byte = i / 8;
int bbit = 7 - (i % 8);
unsigned char comp = (1 << bbit);
#ifdef BITDHT_DEBUG
fprintf(stderr, "bdStdBucketDistance: bit:%d byte:%d bbit:%d comp:%x, data:%x\n", bit, byte, bbit, comp, m->data[byte]);
#endif
if (comp & m->data[byte])
{
return bit;
}
}
return 0;
}
bdStdDht::bdStdDht()
{
return;
}
/* setup variables */
uint16_t bdStdDht::bdNumBuckets()
{
return BITDHT_STANDARD_N_BUCKETS;
}
uint16_t bdStdDht::bdNodesPerBucket() /* used for query + bdspace */
{
return BITDHT_STANDARD_BUCKET_SIZE;
}
uint16_t bdStdDht::bdBucketBitSize()
{
return BITDHT_STANDARD_BUCKET_SIZE_BITS;
}
int bdStdDht::bdDistance(const bdNodeId *n1, const bdNodeId *n2, class bdMetric *metric)
{
return bdStdDistance(n1, n2, metric);
}
int bdStdDht::bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2)
{
return bdStdBucketDistance(n1, n2);
}
int bdStdDht::bdBucketDistance(const bdMetric *metric)
{
return bdStdBucketDistance(metric);
}
uint32_t bdStdDht::bdLikelySameNode(const bdId *id1, const bdId *id2)
{
return bdStdLikelySameNode(id1, id2);
}
void bdStdDht::bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid)
{
return bdStdRandomMidId(target, other, mid);
}
void bdStdDht::bdPrintId(std::ostream &out, const bdId *a)
{
return bdStdPrintId(out, a);
}
void bdStdDht::bdPrintNodeId(std::ostream &out, const bdNodeId *a)
{
return bdStdPrintNodeId(out, a);
}

View File

@ -0,0 +1,92 @@
#ifndef BITDHT_STANDARD_DHT_H
#define BITDHT_STANDARD_DHT_H
/*
* bitdht/bdstddht.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdiface.h"
#define BITDHT_STANDARD_BUCKET_SIZE 20
#define BITDHT_STANDARD_BUCKET_SIZE_BITS 5
#define BITDHT_STANDARD_N_BUCKETS BITDHT_KEY_BITLEN
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <list>
#include <string>
#include <map>
#include <vector>
void bdStdRandomNodeId(bdNodeId *id);
void bdStdZeroNodeId(bdNodeId *id);
void bdStdRandomId(bdId *id);
int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r);
int bdStdBucketDistance(const bdMetric *m);
int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b);
void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid);
void bdStdPrintId(std::ostream &out, const bdId *a);
void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a);
std::string bdStdConvertToPrintable(std::string input);
uint32_t bdStdLikelySameNode(const bdId*, const bdId*);
class bdStdDht: public bdDhtFunctions
{
public:
bdStdDht();
/* setup variables */
virtual uint16_t bdNumBuckets();
virtual uint16_t bdNodesPerBucket(); /* used for query + bdspace */
virtual uint16_t bdBucketBitSize();
virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric);
virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2);
virtual int bdBucketDistance(const bdMetric *metric);
virtual uint32_t bdLikelySameNode(const bdId *id1, const bdId *id2);
virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid);
virtual void bdPrintId(std::ostream &out, const bdId *a);
virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a);
};
#endif

View File

@ -0,0 +1,199 @@
/*
* bitdht/bdstore.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdstore.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <iostream>
//#define DEBUG_STORE 1
bdStore::bdStore(std::string file, bdDhtFunctions *fns)
:mFns(fns)
{
#ifdef DEBUG_STORE
std::cerr << "bdStore::bdStore(" << file << ")";
std::cerr << std::endl;
#endif
/* read data from file */
mIndex = 0;
mStoreFile = file;
FILE *fd = fopen(file.c_str(), "r");
if (!fd)
{
fprintf(stderr, "Failed to Open File: %s ... No Peers\n", file.c_str());
return;
}
char line[10240];
char addr_str[10240];
struct sockaddr_in addr;
addr.sin_family = PF_INET;
unsigned short port;
while(line == fgets(line, 10240, fd))
{
if (2 == sscanf(line, "%s %hd", addr_str, &port))
{
if (inet_aton(addr_str, &(addr.sin_addr)))
{
addr.sin_port = htons(port);
bdPeer peer;
//bdZeroNodeId(&(peer.mPeerId.id));
peer.mPeerId.addr = addr;
peer.mLastSendTime = 0;
peer.mLastRecvTime = 0;
store.push_back(peer);
#ifdef DEBUG_STORE
fprintf(stderr, "Read: %s %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
#endif
}
}
}
fclose(fd);
#ifdef DEBUG_STORE
fprintf(stderr, "Read %ld Peers\n", (long) store.size());
#endif
}
int bdStore::getPeer(bdPeer *peer)
{
#ifdef DEBUG_STORE
fprintf(stderr, "bdStore::getPeer() %ld Peers left\n", (long) store.size());
#endif
std::list<bdPeer>::iterator it;
int i = 0;
for(it = store.begin(); (it != store.end()) && (i < mIndex); it++, i++);
if (it != store.end())
{
*peer = *it;
mIndex++;
return 1;
}
return 0;
}
#define MAX_ENTRIES 500
/* maintain a sorted list */
void bdStore::addStore(bdPeer *peer)
{
#ifdef DEBUG_STORE
std::cerr << "bdStore::addStore() ";
mFns->bdPrintId(std::cerr, &(peer->mPeerId));
std::cerr << std::endl;
#endif
/* remove old entry */
bool removed = false;
std::list<bdPeer>::iterator it;
for(it = store.begin(); it != store.end(); )
{
if ((it->mPeerId.addr.sin_addr.s_addr == peer->mPeerId.addr.sin_addr.s_addr) &&
(it->mPeerId.addr.sin_port == peer->mPeerId.addr.sin_port))
{
removed = true;
#ifdef DEBUG_STORE
std::cerr << "bdStore::addStore() Removed Existing Entry: ";
mFns->bdPrintId(std::cerr, &(it->mPeerId));
std::cerr << std::endl;
#endif
it = store.erase(it);
}
else
{
it++;
}
}
#ifdef DEBUG_STORE
std::cerr << "bdStore::addStore() Push_back";
std::cerr << std::endl;
#endif
store.push_back(*peer);
while(store.size() > MAX_ENTRIES)
{
#ifdef DEBUG_STORE
std::cerr << "bdStore::addStore() pop_front()";
std::cerr << std::endl;
#endif
store.pop_front();
}
}
void bdStore::writeStore(std::string file)
{
/* write out store */
#ifdef DEBUG_STORE
fprintf(stderr, "bdStore::writeStore(%s) = %d entries\n", file.c_str(), store.size());
#endif
FILE *fd = fopen(file.c_str(), "w");
if (!fd)
{
#ifdef DEBUG_STORE
#endif
fprintf(stderr, "bdStore::writeStore() FAILED to Open File\n");
return;
}
std::list<bdPeer>::iterator it;
for(it = store.begin(); it != store.end(); it++)
{
fprintf(fd, "%s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port));
#ifdef DEBUG_STORE
fprintf(stderr, "Storing Peer Address: %s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port));
#endif
}
fclose(fd);
}
void bdStore::writeStore()
{
#if 0
if (mStoreFile == "")
{
return;
}
#endif
return writeStore(mStoreFile);
}

View File

@ -0,0 +1,52 @@
#ifndef BITDHT_STORE_H
#define BITDHT_STORE_H
/*
* bitdht/bdstore.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <string>
#include "bdiface.h"
#include "bdpeer.h"
class bdStore
{
public:
bdStore(std::string file, bdDhtFunctions *fns);
int getPeer(bdPeer *peer);
void addStore(bdPeer *peer);
void writeStore(std::string file);
void writeStore();
private:
std::string mStoreFile;
std::list<bdPeer> store;
int mIndex;
bdDhtFunctions *mFns;
};
#endif

View File

@ -0,0 +1,602 @@
/*
* C implementation of a bencode decoder.
* This is the format defined by BitTorrent:
* http://wiki.theory.org/BitTorrentSpecification#bencoding
*
* The only external requirements are a few [standard] function calls and
* the long long type. Any sane system should provide all of these things.
*
* See the bencode.h header file for usage information.
*
* This is released into the public domain.
* Written by Mike Frysinger <vapier@gmail.com>.
*/
/*
* This implementation isn't optimized at all as I wrote it to support
* a bogus system. I have no real interest in this format. Feel free
* to send me patches (so long as you don't copyright them and you release
* your changes into the public domain as well).
*/
#include <stdio.h>
#include <stdlib.h> /* malloc() realloc() free() strtoll() */
#include <string.h> /* memset() */
#include "bencode.h"
/***
* #define BE_DEBUG_DECODE 1
***/
//#define BE_DEBUG_DECODE 1
#ifdef BE_DEBUG_DECODE
#include <stdio.h> /* debug */
#endif
static be_node *be_alloc(be_type type)
{
be_node *ret = (be_node *) malloc(sizeof(*ret));
if (ret) {
memset(ret, 0x00, sizeof(*ret));
ret->type = type;
}
return ret;
}
static long long _be_decode_int(const char **data, long long *data_len)
{
char *endp;
long long ret = strtoll(*data, &endp, 10);
*data_len -= (endp - *data);
*data = endp;
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_int(pnt: %p, rem: %lld) = %lld\n", *data, *data_len, ret);
#endif
return ret;
}
long long be_str_len(be_node *node)
{
long long ret = 0;
if (node->val.s)
memcpy(&ret, node->val.s - sizeof(ret), sizeof(ret));
return ret;
}
static char *_be_decode_str(const char **data, long long *data_len)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str(pnt: %p, rem: %lld)\n", *data, *data_len);
#endif
long long sllen = _be_decode_int(data, data_len);
long slen = sllen;
unsigned long len;
char *ret = NULL;
/* slen is signed, so negative values get rejected */
if (sllen < 0)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str() reject bad length\n");
#endif
return ret;
}
/* reject attempts to allocate large values that overflow the
* size_t type which is used with malloc()
*/
if (sizeof(long long) != sizeof(long))
if (sllen != slen)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str() reject large_values\n");
#endif
return ret;
}
/* make sure we have enough data left */
if (sllen > *data_len - 1)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str() reject large_values\n");
#endif
return ret;
}
/* switch from signed to unsigned so we don't overflow below */
len = slen;
if (**data == ':') {
char *_ret = (char *) malloc(sizeof(sllen) + len + 1);
memcpy(_ret, &sllen, sizeof(sllen));
ret = _ret + sizeof(sllen);
memcpy(ret, *data + 1, len);
ret[len] = '\0';
*data += len + 1;
*data_len -= len + 1;
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str() read %ld bytes\n", len+1);
#endif
}
else
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode_str() reject missing :\n");
#endif
}
return ret;
}
static be_node *_be_decode(const char **data, long long *data_len)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len);
#endif
be_node *ret = NULL;
if (!*data_len)
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n");
#endif
return ret;
}
switch (**data) {
/* lists */
case 'l': {
unsigned int i = 0;
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() found list\n");
#endif
ret = be_alloc(BE_LIST);
--(*data_len);
++(*data);
while (**data != 'e') {
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i);
#endif
ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l));
ret->val.l[i] = _be_decode(data, data_len);
if (ret->val.l[i] == NULL)
{
/* failed decode - kill decode */
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n");
#endif
be_free(ret);
return NULL;
}
++i;
}
--(*data_len);
++(*data);
/* empty list case. */
if (i == 0)
{
ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l));
}
ret->val.l[i] = NULL;
return ret;
}
/* dictionaries */
case 'd': {
unsigned int i = 0;
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() found dictionary\n");
#endif
ret = be_alloc(BE_DICT);
--(*data_len);
++(*data);
while (**data != 'e') {
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i);
#endif
ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d));
ret->val.d[i].key = _be_decode_str(data, data_len);
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() dictionary get val\n");
#endif
ret->val.d[i].val = _be_decode(data, data_len);
if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL))
{
/* failed decode - kill decode */
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n");
#endif
be_free(ret);
return NULL;
}
++i;
}
--(*data_len);
++(*data);
/* empty dictionary case. */
if (i == 0)
{
ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d));
}
ret->val.d[i].val = NULL;
return ret;
}
/* integers */
case 'i': {
ret = be_alloc(BE_INT);
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() found int\n");
#endif
--(*data_len);
++(*data);
ret->val.i = _be_decode_int(data, data_len);
if (**data != 'e')
{
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n");
#endif
be_free(ret);
return NULL;
}
--(*data_len);
++(*data);
return ret;
}
/* byte strings */
case '0'...'9': {
ret = be_alloc(BE_STR);
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() found string\n");
#endif
ret->val.s = _be_decode_str(data, data_len);
return ret;
}
/* invalid */
default:
#ifdef BE_DEBUG_DECODE
fprintf(stderr, "bencode::_be_decode() found invalid - kill\n");
#endif
return NULL;
break;
}
return ret;
}
be_node *be_decoden(const char *data, long long len)
{
return _be_decode(&data, &len);
}
be_node *be_decode(const char *data)
{
return be_decoden(data, strlen(data));
}
static inline void _be_free_str(char *str)
{
if (str)
free(str - sizeof(long long));
}
void be_free(be_node *node)
{
switch (node->type) {
case BE_STR:
_be_free_str(node->val.s);
break;
case BE_INT:
break;
case BE_LIST: {
unsigned int i;
for (i = 0; node->val.l[i]; ++i)
be_free(node->val.l[i]);
free(node->val.l);
break;
}
case BE_DICT: {
unsigned int i;
for (i = 0; node->val.d[i].val; ++i) {
_be_free_str(node->val.d[i].key);
be_free(node->val.d[i].val);
}
free(node->val.d);
break;
}
}
free(node);
}
#ifdef BE_DEBUG
#include <stdio.h>
#include <stdint.h>
static void _be_dump_indent(ssize_t indent)
{
while (indent-- > 0)
printf(" ");
}
static void _be_dump(be_node *node, ssize_t indent)
{
size_t i;
_be_dump_indent(indent);
indent = abs(indent);
switch (node->type) {
case BE_STR:
be_dump_str(node);
//printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node));
break;
case BE_INT:
printf("int = %lli\n", node->val.i);
break;
case BE_LIST:
puts("list [");
for (i = 0; node->val.l[i]; ++i)
_be_dump(node->val.l[i], indent + 1);
_be_dump_indent(indent);
puts("]");
break;
case BE_DICT:
puts("dict {");
for (i = 0; node->val.d[i].val; ++i) {
_be_dump_indent(indent + 1);
printf("%s => ", node->val.d[i].key);
_be_dump(node->val.d[i].val, -(indent + 1));
}
_be_dump_indent(indent);
puts("}");
break;
}
}
void be_dump(be_node *node)
{
_be_dump(node, 0);
}
void be_dump_str(be_node *node)
{
if (node->type != BE_STR)
{
printf("be_dump_str(): error not a string\n");
return;
}
int len = be_str_len(node);
printf("str[%d] = ", len);
for(int i = 0; i < len; i++)
{
/* sensible chars */
if ((node->val.s[i] > 31) && (node->val.s[i] < 127))
{
printf("%c", node->val.s[i]);
}
else
{
printf("[%d]", node->val.s[i]);
}
}
printf("\n");
}
#endif
/******************** New Functions added by drBob *************
* Output bencode
*
*/
int be_encode(be_node *node, char *str, int len)
{
size_t i;
int loc = 0;
switch (node->type) {
case BE_STR:
snprintf(str, len, "%lli:", be_str_len(node));
loc += strlen(&(str[loc]));
memcpy(&(str[loc]), node->val.s, be_str_len(node));
loc += be_str_len(node);
break;
case BE_INT:
snprintf(str, len, "i%llie", node->val.i);
loc += strlen(&(str[loc]));
break;
case BE_LIST:
snprintf(str, len, "l");
loc += 1;
for (i = 0; node->val.l[i]; ++i)
{
loc += be_encode(node->val.l[i], &(str[loc]), len-loc);
}
snprintf(&(str[loc]), len - loc, "e");
loc += 1;
break;
case BE_DICT:
snprintf(str, len, "d");
loc += 1;
for (i = 0; node->val.d[i].val; ++i) {
/* assumption that key must be ascii! */
snprintf(&(str[loc]), len-loc, "%i:%s",
(int) strlen(node->val.d[i].key),
node->val.d[i].key);
loc += strlen(&(str[loc]));
loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc);
}
snprintf(&(str[loc]), len - loc, "e");
loc += 1;
break;
}
return loc;
}
/* hackish way to create nodes! */
be_node *be_create_dict()
{
be_node *n = be_decode("de");
return n;
}
be_node *be_create_list()
{
be_node *n = be_decode("le");
return n;
}
be_node *be_create_str(const char *str)
{
/* must */
be_node *n = be_alloc(BE_STR);
int len = strlen(str);
long long int sllen = len;
char *_ret = (char *) malloc(sizeof(sllen) + len + 1);
char *ret = NULL;
memcpy(_ret, &sllen, sizeof(sllen));
ret = _ret + sizeof(sllen);
memcpy(ret, str, len);
ret[len] = '\0';
n->val.s = ret;
return n;
}
be_node *be_create_str_wlen(const char *str, int len) /* not including \0 */
{
/* must */
be_node *n = be_alloc(BE_STR);
long long int sllen = len;
char *_ret = (char *) malloc(sizeof(sllen) + len + 1);
char *ret = NULL;
memcpy(_ret, &sllen, sizeof(sllen));
ret = _ret + sizeof(sllen);
memcpy(ret, str, len);
ret[len] = '\0';
n->val.s = ret;
return n;
}
be_node *be_create_int(long long int num)
{
/* must */
be_node *n = be_alloc(BE_INT);
n->val.i = num;
return n;
}
int be_add_keypair(be_node *dict, const char *str, be_node *node)
{
int i = 0;
/* only if dict type */
if (dict->type != BE_DICT)
{
return 0;
}
// get to end of dict.
for(i = 0; dict->val.d[i].val; i++);
//fprintf(stderr, "be_add_keypair() i = %d\n",i);
/* realloc space */
dict->val.d = (be_dict *) realloc(dict->val.d, (i + 2) * sizeof(*dict->val.d));
/* stupid key storage system */
int len = strlen(str);
long long int sllen = len;
char *_ret = (char *) malloc(sizeof(sllen) + len + 1);
char *ret = NULL;
//fprintf(stderr, "be_add_keypair() key len = %d\n",len);
memcpy(_ret, &sllen, sizeof(sllen));
ret = _ret + sizeof(sllen);
memcpy(ret, str, len);
ret[len] = '\0';
dict->val.d[i].key = ret;
dict->val.d[i].val = node;
i++;
dict->val.d[i].val = NULL;
return 1;
}
int be_add_list(be_node *list, be_node *node)
{
int i = 0;
/* only if dict type */
if (list->type != BE_LIST)
{
return 0;
}
// get to end of dict.
for(i = 0; list->val.l[i]; i++);
/* realloc space */
list->val.l = (be_node **) realloc(list->val.l, (i + 2) * sizeof(*list->val.l));
list->val.l[i] = node;
++i;
list->val.l[i] = NULL;
return 1;
}

View File

@ -0,0 +1,82 @@
/*
* C implementation of a bencode decoder.
* This is the format defined by BitTorrent:
* http://wiki.theory.org/BitTorrentSpecification#bencoding
*
* The only external requirements are a few [standard] function calls and
* the long long type. Any sane system should provide all of these things.
*
* This is released into the public domain.
* Written by Mike Frysinger <vapier@gmail.com>.
*/
/* USAGE:
* - pass the string full of the bencoded data to be_decode()
* - parse the resulting tree however you like
* - call be_free() on the tree to release resources
*/
#ifndef _BENCODE_H
#define _BENCODE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
BE_STR,
BE_INT,
BE_LIST,
BE_DICT,
} be_type;
struct be_dict;
struct be_node;
/*
* XXX: the "val" field of be_dict and be_node can be confusing ...
*/
typedef struct be_dict {
char *key;
struct be_node *val;
} be_dict;
typedef struct be_node {
be_type type;
union {
char *s;
long long i;
struct be_node **l;
struct be_dict *d;
} val;
} be_node;
extern long long be_str_len(be_node *node);
// This function uses strlen, so is unreliable.
//extern be_node *be_decode(const char *bencode);
extern be_node *be_decoden(const char *bencode, long long bencode_len);
extern void be_free(be_node *node);
extern void be_dump(be_node *node);
extern void be_dump_str(be_node *node);
// New Functions for the other half of the work - encoding */
extern int be_encode(be_node *node, char *str, int len);
// Creating the data structure.
extern int be_add_list(be_node *list, be_node *node);
extern int be_add_keypair(be_node *dict, const char *str, be_node *node);
extern be_node *be_create_int(long long int num);
extern be_node *be_create_list();
extern be_node *be_create_str(const char *str);
extern be_node *be_create_str_wlen(const char *str, int len); /* not including \0 */
extern be_node *be_create_dict();
#ifdef __cplusplus
}
#endif
#endif

108
libbitdht/src/libbitdht.pro Normal file
View File

@ -0,0 +1,108 @@
TEMPLATE = lib
CONFIG += staticlib release
CONFIG -= qt
TARGET = bitdht
QMAKE_CXXFLAGS *= -Wall -DBE_DEBUG
profiling {
QMAKE_CXXFLAGS -= -fomit-frame-pointer
QMAKE_CXXFLAGS *= -pg -g -fno-omit-frame-pointer
}
release {
# not much here yet.
}
#CONFIG += debug
debug {
QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer
QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer
}
################################# Linux ##########################################
linux-* {
DESTDIR = lib
QMAKE_CC = g++
}
linux-g++ {
OBJECTS_DIR = temp/linux-g++/obj
}
linux-g++-64 {
OBJECTS_DIR = temp/linux-g++-64/obj
}
#################### Cross compilation for windows under Linux ####################
win32-x-g++ {
OBJECTS_DIR = temp/win32xgcc/obj
DESTDIR = lib.win32xgcc
DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU
QMAKE_CXXFLAGS *= -Wmissing-include-dirs
QMAKE_CC = i586-mingw32msvc-g++
QMAKE_LIB = i586-mingw32msvc-ar
QMAKE_AR = i586-mingw32msvc-ar
DEFINES *= STATICLIB WIN32
INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/
}
################################# Windows ##########################################
win32 {
QMAKE_CC = g++
OBJECTS_DIR = temp/obj
MOC_DIR = temp/moc
DEFINES *= WINDOWS_SYS WIN32 STATICLIB MINGW
DESTDIR = lib
}
################################# MacOSX ##########################################
mac {
QMAKE_CC = g++
OBJECTS_DIR = temp/obj
MOC_DIR = temp/moc
DESTDIR = lib
}
################################### COMMON stuff ##################################
################################### COMMON stuff ##################################
#DEPENDPATH += . \
INCLUDEPATH += . \
HEADERS += \
bitdht/bdiface.h \
bitdht/bencode.h \
bitdht/bdobj.h \
bitdht/bdmsgs.h \
bitdht/bdpeer.h \
bitdht/bdquery.h \
bitdht/bdhash.h \
bitdht/bdstore.h \
bitdht/bdnode.h \
bitdht/bdmanager.h \
bitdht/bdstddht.h \
util/bdthreads.h \
udp/udplayer.h \
udp/udpstack.h \
udp/udpbitdht.h \
SOURCES += \
bitdht/bencode.c \
bitdht/bdobj.cc \
bitdht/bdmsgs.cc \
bitdht/bdpeer.cc \
bitdht/bdquery.cc \
bitdht/bdhash.cc \
bitdht/bdstore.cc \
bitdht/bdnode.cc \
bitdht/bdmanager.cc \
bitdht/bdstddht.cc \
util/bdthreads.cc \
udp/udplayer.cc \
udp/udpstack.cc \
udp/udpbitdht.cc \

View File

@ -0,0 +1,80 @@
LIB_TOP_DIR = ..
TEST_TOP_DIR = $(LIB_TOP_DIR)/tests
##### Define any flags that are needed for this section #######
###############################################################
###############################################################
include $(TEST_TOP_DIR)/scripts/config.mk
###############################################################
# Generic Test Harnesses.
TESTOBJ = bdmetric_test.o bdmsgs_test.o bdnode_test.o bdspace_test.o
TESTOBJ += bdmgr_multitest.o bdnode_multitest1.o bdquery_test.o bdstore_test.o
TESTOBJ += bdmidids_test.o bdnode_test2.o bdspace_test2.o
#TESTOBJ += bencode_test.o bdudp_test.o
TESTS = bdmetric_test bdmsgs_test bdnode_test bdspace_test
TESTS += bdmgr_multitest bdnode_multitest1 bdquery_test bdstore_test
TESTS += bdmidids_test bdnode_test2 bdspace_test2
#TESTS += bencode_test bdudp_test
MANUAL_TESTS =
all: tests $(MANUAL_TESTS)
bdmsgs_test: bdmsgs_test.o
$(CC) $(CFLAGS) -o bdmsgs_test bdmsgs_test.o $(LIBS)
bdmetric_test: bdmetric_test.o
$(CC) $(CFLAGS) -o bdmetric_test bdmetric_test.o $(LIBS)
bdquery_test: bdquery_test.o
$(CC) $(CFLAGS) -o bdquery_test bdquery_test.o $(LIBS)
bdspace_test: bdspace_test.o
$(CC) $(CFLAGS) -o bdspace_test bdspace_test.o $(LIBS)
bdspace_test2: bdspace_test2.o
$(CC) $(CFLAGS) -o bdspace_test2 bdspace_test2.o $(LIBS)
bdnode_test: bdnode_test.o
$(CC) $(CFLAGS) -o bdnode_test bdnode_test.o $(LIBS)
bdnode_test2: bdnode_test2.o
$(CC) $(CFLAGS) -o bdnode_test2 bdnode_test2.o $(LIBS)
bdmidids_test: bdmidids_test.o
$(CC) $(CFLAGS) -o bdmidids_test bdmidids_test.o $(LIBS)
bdnode_multitest1: bdnode_multitest1.o
$(CC) $(CFLAGS) -o bdnode_multitest1 bdnode_multitest1.o $(LIBS)
bdmgr_multitest: bdmgr_multitest.o
$(CC) $(CFLAGS) -o bdmgr_multitest bdmgr_multitest.o $(LIBS)
bdstore_test: bdstore_test.o
$(CC) $(CFLAGS) -o bdstore_test bdstore_test.o $(LIBS)
bdudp_test: bdudp_test.o
$(CC) $(CFLAGS) -o bdudp_test bdudp_test.o $(LIBS)
udpbitdht_nettest: udpbitdht_nettest.o
$(CC) $(CFLAGS) -o udpbitdht_test udpbitdht_test.o $(LIBS)
bencode_test: bencode_test.o
$(CC) $(CFLAGS) -o bencode_test bencode_test.o $(LIBS)
clobber: remove_extra_files
remove_extra_files:
-$(RM) $(MANUAL_TESTS)
###############################################################
include $(TEST_TOP_DIR)/scripts/rules.mk
###############################################################

View File

@ -0,0 +1,166 @@
/*
* bitdht/bdmetric_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#include <iostream>
#include <stdio.h>
int main(int argc, char **argv)
{
/* create some ids */
bdId id1;
bdId id2;
bdId id3;
bdId id4;
bdId id5;
bdId id6;
bdStdRandomId(&id1);
bdStdRandomId(&id2);
bdStdRandomId(&id3);
bdStdRandomId(&id4);
bdStdRandomId(&id5);
bdStdRandomId(&id6);
fprintf(stderr, "id1:");
bdStdPrintId(std::cerr,&id1);
fprintf(stderr, "\n");
fprintf(stderr, "id2:");
bdStdPrintId(std::cerr,&id2);
fprintf(stderr, "\n");
fprintf(stderr, "id3:");
bdStdPrintId(std::cerr,&id3);
fprintf(stderr, "\n");
fprintf(stderr, "id4:");
bdStdPrintId(std::cerr,&id4);
fprintf(stderr, "\n");
fprintf(stderr, "id5:");
bdStdPrintId(std::cerr,&id5);
fprintf(stderr, "\n");
fprintf(stderr, "id6:");
bdStdPrintId(std::cerr,&id6);
fprintf(stderr, "\n");
/* now do the sums */
bdMetric met;
bdMetric met2;
int bdist = 0;
bdStdDistance(&(id1.id), &(id2.id), &met);
fprintf(stderr, "1^2:");
bdStdPrintNodeId(std::cerr,&met);
fprintf(stderr, "\n");
bdist = bdStdBucketDistance(&met);
fprintf(stderr, " bucket: %d\n", bdist);
bdStdDistance(&(id1.id), &(id3.id), &met2);
bdist = bdStdBucketDistance(&met2);
fprintf(stderr, "1^3:");
bdStdPrintNodeId(std::cerr,&met2);
fprintf(stderr, "\n");
fprintf(stderr, " bucket: %d\n", bdist);
int c1 = met < met2;
int c2 = met2 < met;
fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2);
bdStdDistance(&(id1.id), &(id4.id), &met2);
bdist = bdStdBucketDistance(&met2);
fprintf(stderr, "1^4:");
bdStdPrintNodeId(std::cerr,&met2);
fprintf(stderr, "\n");
fprintf(stderr, " bucket: %d\n", bdist);
c1 = met < met2;
c2 = met2 < met;
fprintf(stderr, "1^2<1^4? : %d 1^4<1^2?: %d\n", c1, c2);
bdStdDistance(&(id1.id), &(id5.id), &met);
bdist = bdStdBucketDistance(&met);
fprintf(stderr, "1^5:");
bdStdPrintNodeId(std::cerr,&met);
fprintf(stderr, "\n");
fprintf(stderr, " bucket: %d\n", bdist);
bdStdDistance(&(id1.id), &(id6.id), &met);
bdist = bdStdBucketDistance(&met);
fprintf(stderr, "1^6:");
bdStdPrintNodeId(std::cerr,&met);
fprintf(stderr, "\n");
fprintf(stderr, " bucket: %d\n", bdist);
bdStdDistance(&(id2.id), &(id3.id), &met);
bdist = bdStdBucketDistance(&met);
fprintf(stderr, "2^3:");
bdStdPrintNodeId(std::cerr,&met);
fprintf(stderr, "\n");
fprintf(stderr, " bucket: %d\n", bdist);
fprintf(stderr, "id1:");
bdStdPrintId(std::cerr,&id1);
fprintf(stderr, "\n");
fprintf(stderr, "id2:");
bdStdPrintId(std::cerr,&id2);
fprintf(stderr, "\n");
fprintf(stderr, "id3:");
bdStdPrintId(std::cerr,&id3);
fprintf(stderr, "\n");
fprintf(stderr, "id4:");
bdStdPrintId(std::cerr,&id4);
fprintf(stderr, "\n");
fprintf(stderr, "id5:");
bdStdPrintId(std::cerr,&id5);
fprintf(stderr, "\n");
fprintf(stderr, "id6:");
bdStdPrintId(std::cerr,&id6);
fprintf(stderr, "\n");
return 1;
}

View File

@ -0,0 +1,185 @@
/*
* bitdht/bdmgr_multitest.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdmanager.h"
#include "bitdht/bdstddht.h"
#include "udp/udplayer.h"
#include <stdlib.h>
/**********************************************************************************
* tests of multi bdnodes all connected together.
* in these cases, the networking step is shortcut and the ip addresses ignored.
* instead the port number is used as an index to peers.
*
* test1()
* Small cross seeding, and static list of peers.
* Set it going - and see what happens.
*/
std::map<bdId, bdNodeManager *> nodes;
std::map<struct sockaddr_in, bdId> addrIdx;
int main(int argc, char **argv)
{
time_t sim_time = 600;
time_t starttime = time(NULL);
int n_nodes = 1000;
std::map<bdId, bdNodeManager *>::iterator it;
std::map<bdId, bdNodeManager *>::iterator nit;
std::map<struct sockaddr_in, bdId>::iterator ait;
int i, j;
bdDhtFunctions *fns = new bdStdDht();
std::cerr << "bdmgr_multitest() Setting up Nodes" << std::endl;
/* setup nodes */
for(i = 0; i < n_nodes; i++)
{
bdId id;
bdStdRandomId(&id);
//id.addr.sin_port = htons(i);
//((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */
std::cerr << "bdmgr_multitest() Id: ";
fns->bdPrintId(std::cerr, &id);
std::cerr << std::endl;
bdNodeManager *mgr = new bdNodeManager(&(id.id), "bdTEST", "", fns);
/* Store in nodes */
nodes[id] = mgr;
/* Store in indices */
addrIdx[id.addr] = id;
}
std::cerr << "bdmgr_multitest() Cross Seeding" << std::endl;
/* do a little cross seeding */
for(nit = nodes.begin(); nit != nodes.end(); nit++)
{
for(j = 0; j < 2; j++)
{
int peeridx = rand() % n_nodes;
for(i = 0, it = nodes.begin();
(i < peeridx) && (it != nodes.end()); i++, it++)
{
/* empty */
}
if (it != nodes.end())
{
nit->second->addPotentialPeer((bdId *) &(it->first));
}
}
}
/* ready to run */
std::cerr << "bdmgr_multitest() Simulation Time....." << std::endl;
i = 0;
while(time(NULL) < starttime + sim_time)
{
i++;
std::cerr << "bdmgr_multitest() Iteration: " << i << std::endl;
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* extract messages to go -> and deliver */
#define MAX_MSG_SIZE 10240
struct sockaddr_in addr;
char data[MAX_MSG_SIZE];
int len = MAX_MSG_SIZE;
while(it->second->outgoingMsg(&addr, data, &len))
{
std::cerr << "bdmgr_multitest() Msg from Peer: " << j;
/* find the peer */
ait = addrIdx.find(addr);
nit = nodes.end();
if (ait != addrIdx.end())
{
nit = nodes.find(ait->second);
std::cerr << " For: ";
fns->bdPrintId(std::cerr, &(nit->first));
std::cerr << std::endl;
}
else
{
std::cerr << " For Unknown Destination";
std::cerr << std::endl;
}
if (nit != nodes.end())
{
/* set from address */
nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len);
}
/* reset message size */
len = MAX_MSG_SIZE;
}
}
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* tick */
std::cerr << "bdmgr_multitest() Ticking peer: " << j << std::endl;
it->second->iteration();
}
/* have a rest */
sleep(1);
}
std::cerr << "bdmgr_multitest() Displying States"<< std::endl;
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* tick */
std::cerr << "bdmgr_multitest() Peer State: " << j << std::endl;
it->second->printState();
}
}

View File

@ -0,0 +1,96 @@
/*
* bitdht/bdmidids_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#include <iostream>
int main(int argc, char **argv)
{
/* Do this multiple times */
int i, j;
std::cerr << "Test Mid Peer Intersection....." << std::endl;
for(i = 0; i < 10; i++)
{
bdNodeId targetId;
bdNodeId peerId;
bdStdRandomNodeId(&targetId);
bdStdRandomNodeId(&peerId);
std::cerr << "-------------------------------------------------" << std::endl;
for(j = 0; j < 10; j++)
{
bdNodeId midId;
bdStdRandomMidId(&targetId, &peerId, &midId);
bdMetric TPmetric;
bdMetric TMmetric;
bdMetric PMmetric;
bdStdDistance(&targetId, &peerId, &TPmetric);
bdStdDistance(&targetId, &midId, &TMmetric);
bdStdDistance(&peerId, &midId, &PMmetric);
int TPdist = bdStdBucketDistance(&TPmetric);
int TMdist = bdStdBucketDistance(&TMmetric);
int PMdist = bdStdBucketDistance(&PMmetric);
std::cerr << "Target: ";
bdStdPrintNodeId(std::cerr,&targetId);
std::cerr << " Peer: ";
bdStdPrintNodeId(std::cerr,&peerId);
std::cerr << std::endl;
std::cerr << "\tTarget ^ Peer: ";
bdStdPrintNodeId(std::cerr,&TPmetric);
std::cerr << " Bucket: " << TPdist;
std::cerr << std::endl;
std::cerr << "\tTarget ^ Mid: ";
bdStdPrintNodeId(std::cerr,&TMmetric);
std::cerr << " Bucket: " << TMdist;
std::cerr << std::endl;
std::cerr << "\tPeer ^ Mid: ";
bdStdPrintNodeId(std::cerr,&PMmetric);
std::cerr << " Bucket: " << PMdist;
std::cerr << std::endl;
/* now save mid to peer... and repeat */
peerId = midId;
}
}
return 1;
}

View File

@ -0,0 +1,102 @@
/*
* bitdht/bdmsgs_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdmsgs.h"
#include "bitdht/bdstddht.h"
#include <string.h>
/*******************************************************************
* Test of bencode message creation functions in bdmsgs.cc
*
* Create a couple of each type.
*/
#define MAX_MESSAGE_LEN 10240
int main(int argc, char **argv)
{
/***** create messages *****/
char msg[MAX_MESSAGE_LEN];
int avail = MAX_MESSAGE_LEN -1;
bdToken tid;
bdToken vid;
bdToken token;
bdNodeId ownId;
bdNodeId peerId;
bdNodeId target;
bdNodeId info_hash;
bdStdRandomNodeId(&ownId);
bdStdRandomNodeId(&peerId);
bdStdRandomNodeId(&target);
bdStdRandomNodeId(&info_hash);
std::list<bdId> nodes;
std::list<std::string> values;
/* setup tokens */
strncpy((char*)tid.data, "tid", 4);
strncpy((char*)vid.data, "RS50", 5);
strncpy((char*)token.data, "ToKEn", 6);
tid.len = 3;
vid.len = 4;
token.len = 5;
/* setup lists */
for(int i = 0; i < 8; i++)
{
bdId rndId;
bdStdRandomId(&rndId);
nodes.push_back(rndId);
values.push_back("values");
}
uint32_t port = 1234;
bitdht_create_ping_msg(&tid, &ownId, msg, avail);
bitdht_response_ping_msg(&tid, &ownId, &vid, msg, avail);
bitdht_find_node_msg(&tid, &ownId, &target, msg, avail);
bitdht_resp_node_msg(&tid, &ownId, nodes, msg, avail);
bitdht_get_peers_msg(&tid, &ownId, &info_hash, msg, avail);
bitdht_peers_reply_hash_msg(&tid, &ownId, &token, values, msg, avail);
bitdht_peers_reply_closest_msg(&tid, &ownId, &token, nodes, msg, avail);
bitdht_announce_peers_msg(&tid, &ownId, &info_hash, port, &token, msg, avail);
bitdht_reply_announce_msg(&tid, &ownId, msg, avail);
return 1;
}

View File

@ -0,0 +1,184 @@
/*
* bitdht/bdnode_multitest1.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdnode.h"
#include "bitdht/bdstddht.h"
#include <stdlib.h>
/**********************************************************************************
* tests of multi bdnodes all connected together.
* in these cases, the networking step is shortcut and the ip addresses ignored.
* instead the port number is used as an index to peers.
*
* test1()
* Small cross seeding, and static list of peers.
* Set it going - and see what happens.
*/
std::map<bdId, bdNode *> nodes;
std::map<uint16_t, bdId> portIdx;
int main(int argc, char **argv)
{
time_t sim_time = 60;
time_t starttime = time(NULL);
int n_nodes = 10;
std::map<bdId, bdNode *>::iterator it;
std::map<bdId, bdNode *>::iterator nit;
std::map<uint16_t, bdId>::iterator pit;
int i, j;
bdDhtFunctions *fns = new bdStdDht();
std::cerr << "bdnode_multitest1() Setting up Nodes" << std::endl;
/* setup nodes */
for(i = 0; i < n_nodes; i++)
{
bdId id;
bdStdRandomId(&id);
id.addr.sin_port = htons(i);
((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */
std::cerr << "bdnode_multitest1() Id: ";
fns->bdPrintId(std::cerr, &id);
std::cerr << std::endl;
bdNode *node = new bdNode(&(id.id), "bdTEST", "", fns);
/* Store in nodes */
nodes[id] = node;
/* Store in indices */
portIdx[i] = id;
}
std::cerr << "bdnode_multitest1() Cross Seeding" << std::endl;
/* do a little cross seeding */
for(i = 0; i < n_nodes; i++)
{
bdId nid = portIdx[i];
bdNode *node = nodes[nid];
for(j = 0; j < 5; j++)
{
int peeridx = rand() % n_nodes;
bdId pid = portIdx[peeridx];
node->addPotentialPeer(&pid);
}
}
/* ready to run */
std::cerr << "bdnode_multitest1() Simulation Time....." << std::endl;
i = 0;
while(time(NULL) < starttime + sim_time)
{
i++;
std::cerr << "bdnode_multitest1() Iteration: " << i << std::endl;
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* extract messages to go -> and deliver */
#define MAX_MSG_SIZE 10240
struct sockaddr_in addr;
char data[MAX_MSG_SIZE];
int len = MAX_MSG_SIZE;
while(it->second->outgoingMsg(&addr, data, &len))
{
std::cerr << "bdnode_multitest1() Msg from Peer: " << j;
/* find the peer */
int peeridx = htons(addr.sin_port);
pit = portIdx.find(peeridx);
nit = nodes.end();
if (pit != portIdx.end())
{
nit = nodes.find(pit->second);
std::cerr << " For: ";
fns->bdPrintId(std::cerr, &(nit->first));
std::cerr << std::endl;
}
else
{
std::cerr << " For Unknown Destination";
std::cerr << std::endl;
}
if (nit != nodes.end())
{
/* set from address */
nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len);
}
/* reset message size */
len = MAX_MSG_SIZE;
}
}
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* tick */
std::cerr << "bdnode_multitest1() Ticking peer: " << j << std::endl;
it->second->iteration();
}
if (i % 5 == 0)
{
std::cerr << "bdnode_multitest1() Displying States"<< std::endl;
for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++)
{
/* tick */
std::cerr << "bdnode_multitest1() Peer State: " << j << std::endl;
it->second->printState();
}
}
/* have a rest */
sleep(1);
}
}

View File

@ -0,0 +1,89 @@
/*
* bitdht/bdnode_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#include "bitdht/bdquery.h"
#include "bitdht/bdnode.h"
#define N_PEERS_TO_ADD_INIT 10
#define N_PEERS_TO_ADD 11
#define N_PEERS_TO_START 10
#define N_PEERS_TO_PRINT 1
#define N_QUERIES 2
int main(int argc, char **argv)
{
/* create some ids */
bdDhtFunctions *fns = new bdStdDht();
bdNodeId ownId;
bdStdRandomNodeId(&ownId);
bdNode node(&ownId, "bdTEST","./dht.log", fns);
int i = 0;
for (i = 0; i < N_PEERS_TO_ADD_INIT; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
node.addPeer(&tmpId, 0);
}
node.printState();
for(i = 0; i < N_QUERIES; i++)
{
/* create a query */
bdNodeId queryId;
bdStdRandomNodeId(&queryId);
node.addQuery(&queryId, 0);
}
node.printState();
for (i = 0; i < N_PEERS_TO_ADD; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
node.addPeer(&tmpId, 0);
if (i % N_PEERS_TO_PRINT == 0)
{
node.printState();
node.iteration();
sleep(5);
}
}
return 1;
}

View File

@ -0,0 +1,56 @@
/*
* bitdht/bdnode_test2.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#include "bitdht/bdquery.h"
#include "bitdht/bdnode.h"
#define N_PEERS_TO_ADD_INIT 10
#define N_PEERS_TO_ADD 11
#define N_PEERS_TO_START 10
#define N_PEERS_TO_PRINT 1
#define N_QUERIES 2
int main(int argc, char **argv)
{
/* create some ids */
bdNodeId ownId;
bdStdRandomNodeId(&ownId);
bdDhtFunctions *fns = new bdStdDht();
bdNode node(&ownId, "bdTEST", "./dht.log", fns);
while(1)
{
node.iteration();
sleep(1);
}
return 1;
}

View File

@ -0,0 +1,83 @@
/*
* bitdht/bdquery_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#include "bitdht/bdquery.h"
#define N_PEERS_TO_ADD 10000
#define N_PEERS_TO_PRINT 1000
#define N_PEERS_TO_START 10
int main(int argc, char **argv)
{
/* create some ids */
bdNodeId ownId;
bdStdRandomNodeId(&ownId);
bdDhtFunctions *fns = new bdStdDht();
bdSpace space(&ownId, fns);
int i = 0;
for (i = 0; i < N_PEERS_TO_ADD; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
space.add_peer(&tmpId, 0);
}
space.printDHT();
/* create a query */
bdId queryId;
bdStdRandomId(&queryId);
std::list<bdId> startList;
std::multimap<bdMetric, bdId> nearest;
std::multimap<bdMetric, bdId>::iterator it;
space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, startList, nearest);
for(it = nearest.begin(); it != nearest.end(); it++)
{
startList.push_back(it->second);
}
bdQuery query(&(queryId.id), startList, BITDHT_QFLAGS_DISGUISE, fns);
/* */
query.printQuery();
return 1;
}

View File

@ -0,0 +1,60 @@
/*
* bitdht/bdspace_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#define N_PEERS_TO_ADD 10000
#define N_PEERS_TO_PRINT 1000
int main(int argc, char **argv)
{
/* create some ids */
bdNodeId ownId;
bdStdRandomNodeId(&ownId);
bdDhtFunctions *fns = new bdStdDht();
bdSpace space(&ownId, fns);
int i = 0;
for (i = 0; i < N_PEERS_TO_ADD; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
space.add_peer(&tmpId, 0);
if (i % N_PEERS_TO_PRINT == 0)
{
space.printDHT();
}
}
space.printDHT();
return 1;
}

View File

@ -0,0 +1,68 @@
/*
* bitdht/bdspace_test2.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdstddht.h"
#define N_PEERS_TO_ADD 10000
#define N_PEERS_TO_TEST 100
#define N_PEERS_TO_FIND 10
int main(int argc, char **argv)
{
/* create some ids */
bdNodeId ownId;
bdStdRandomNodeId(&ownId);
bdDhtFunctions *fns = new bdStdDht();
bdSpace space(&ownId, fns);
int i = 0;
for (i = 0; i < N_PEERS_TO_ADD; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
space.add_peer(&tmpId, 0);
}
space.printDHT();
/* now generate random id's and test closeness */
for(i = 0; i < N_PEERS_TO_TEST; i++)
{
bdId tmpId;
bdStdRandomId(&tmpId);
std::list<bdId> list1;
std::multimap<bdMetric, bdId> list2;
space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list1, list2);
}
return 1;
}

View File

@ -0,0 +1,47 @@
/*
* bitdht/bdstore_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdstore.h"
#include "bitdht/bdstddht.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
/* load store */
if (argc < 2)
{
fprintf(stderr, "Missing Store File\n");
exit(1);
}
bdDhtFunctions *fns = new bdStdDht();
bdStore store(argv[1], fns);
return 1;
}

View File

@ -0,0 +1,66 @@
/*
* bitdht/bdudp_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bdpeer.h"
#include "bitdht/bdquery.h"
#include "udp/udpbitdht.h"
#define N_PEERS_TO_ADD 10000
#define N_PEERS_TO_PRINT 1000
#define N_PEERS_TO_START 10
int main(int argc, char **argv)
{
/* create some ids */
bdId ownId;
bdRandomId(&ownId);
struct sockaddr_in local;
local.sin_addr.s_addr = 0;
local.sin_port = htons(7812);
std::string bootstrapfile = "dht.log";
bdId bid;
bid.addr = local;
bid.id = ownId.id;
UdpBitDht ubd(local, 0, &bid, bootstrapfile);
while(1)
{
ubd.tick();
sleep(1);
}
return 1;
}

View File

@ -0,0 +1,182 @@
/*
* bitdht/bencode_test.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bitdht/bencode.h"
#include <stdio.h>
int main(int argc, char **argv)
{
char msg[100];
msg[0] = 'd';
msg[1] = '1';
msg[2] = ':';
msg[3] = 't';
msg[4] = 'L';
msg[5] = 'b';
msg[6] = 'U';
msg[7] = 0xd9;
msg[8] = 0xfa;
msg[9] = 0xff;
msg[10] = 0xff;
msg[11] = 0xff;
msg[12] = 0xff;
msg[13] = '\n';
msg[14] = 'H';
msg[15] = '#';
msg[16] = '#';
msg[17] = '#';
msg[18] = '#';
msg[19] = '#';
msg[20] = '#';
msg[21] = '#';
be_node *n = be_decoden(msg, 16);
if (n)
{
be_dump(n);
be_free(n);
}
else
{
fprintf(stderr, "didn't crash!\n");
}
msg[0] = 'd';
msg[1] = '1';
msg[2] = ':';
msg[3] = 'a';
msg[4] = 'L';
msg[5] = 0x8d;
msg[6] = 0xd6;
msg[7] = '\r';
msg[8] = 0x9d;
msg[9] = ';';
msg[10] = 0xff;
msg[11] = 0xff;
msg[12] = 0xff;
msg[13] = 0xff;
msg[14] = 'H';
msg[15] = '#';
msg[16] = '#';
msg[17] = '#';
msg[18] = '#';
msg[19] = '#';
msg[20] = '#';
msg[21] = '#';
n = be_decoden(msg, 14);
if (n)
{
be_dump(n);
be_free(n);
}
else
{
fprintf(stderr, "didn't crash!\n");
}
msg[0] = 'd';
msg[1] = '1';
msg[2] = ':';
msg[3] = 't';
msg[4] = '4';
msg[5] = ':';
msg[6] = 'a';
msg[7] = 'b';
msg[8] = 'c';
msg[9] = 'd';
msg[10] = '1';
msg[11] = ':';
msg[12] = 'y';
msg[13] = '1';
msg[14] = ':';
msg[15] = 'r';
msg[16] = '1';
msg[17] = ':';
msg[18] = 'r';
msg[19] = 'd';
msg[20] = '2';
msg[21] = ':';
msg[22] = 'i';
msg[23] = 'd';
msg[24] = '2';
msg[25] = '0';
msg[26] = ':';
msg[27] = '1';
msg[28] = '2';
msg[29] = '3';
msg[30] = '4';
msg[31] = '5';
msg[32] = '6';
msg[33] = '7';
msg[34] = '8';
msg[35] = '9';
msg[36] = '0';
msg[37] = 'a';
msg[38] = 'b';
msg[39] = 'c';
msg[40] = 'd';
msg[41] = 'e';
msg[42] = 'f';
msg[43] = 'g';
msg[44] = 'h';
msg[45] = 'i';
msg[46] = '.';
msg[47] = '5';
msg[48] = ':';
msg[49] = 'n';
msg[50] = 'o';
msg[51] = 'd';
msg[52] = 'e';
msg[53] = 's';
msg[54] = '2';
msg[55] = '0';
msg[56] = '8';
msg[57] = ':';
msg[58] = '\0';
msg[59] = '\0';
msg[60] = '\0';
n = be_decoden(msg, 58);
if (n)
{
be_dump(n);
be_free(n);
}
else
{
fprintf(stderr, "didn't crash!\n");
}
return 1;
}

View File

@ -0,0 +1,19 @@
#Basic checks
ifndef TEST_TOP_DIR
dummy:
echo "TEST_TOP_DIR is not defined in your makefile"
endif
ifneq ($(OS),Linux)
ifneq ($(OS),MacOSX)
ifndef PTHREADS_DIR
dummy:
echo "you must define PTHREADS_DIR before you can compile"
endif
endif
endif

View File

@ -0,0 +1,118 @@
ifneq ($(OS),Cygwin)
dummy:
echo "ERROR Cygwin configuration file included, but (OS != Cygwin)
endif
############ LINUX CONFIGURATION ########################
# flags for components....
PQI_USE_XPGP = 1
#PQI_USE_PROXY = 1
#PQI_USE_CHANNELS = 1
#USE_FILELOOK = 1
###########################################################################
#### DrBobs Versions.... Please Don't Delete.
### Comment out if needed.
ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW
SRC_ROOT=../../../..
PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2
###################
#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src
#SRC_ROOT=/cygdrive/c/RetroShareBuild/src
#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release
###################
ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3
SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c
UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0
include $(RS_TOP_DIR)/scripts/checks.mk
############ ENFORCE DIRECTORY NAMING ########################
CC = g++
RM = /bin/rm
RANLIB = ranlib
LIBDIR = $(RS_TOP_DIR)/lib
LIBRS = $(LIBDIR)/libretroshare.a
# Unix: Linux/Cygwin
INCLUDE = -I $(RS_TOP_DIR)
ifdef PQI_DEBUG
CFLAGS = -Wall -g $(INCLUDE)
else
CFLAGS = -Wall -O2 $(INCLUDE)
endif
ifdef PQI_USE_XPGP
INCLUDE += -I $(SSL_DIR)/include
endif
ifdef PQI_USE_XPGP
CFLAGS += -DPQI_USE_XPGP
endif
ifdef PQI_USE_PROXY
CFLAGS += -DPQI_USE_PROXY
endif
ifdef PQI_USE_CHANNELS
CFLAGS += -DPQI_USE_CHANNELS
endif
ifdef USE_FILELOOK
CFLAGS += -DUSE_FILELOOK
endif
RSCFLAGS = -Wall -g $(INCLUDE)
#########################################################################
# OS Compile Options
#########################################################################
# For the SSL BIO compilation. (Copied from OpenSSL compilation flags)
BIOCC = gcc
# Cygwin - ?same? as Linux flags
BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM
#########################################################################
# OS specific Linking.
#########################################################################
# for static pthread libs....
WININC += -DPTW32_STATIC_LIB
WININC += -mno-cygwin -mwindows -fno-exceptions
WININC += -DWINDOWS_SYS
WINLIB = -lws2_32 -luuid -lole32 -liphlpapi
WINLIB += -lcrypt32 -lwinmm
CFLAGS += -I$(PTHREADS_DIR) $(WININC)
CFLAGS += -I$(ZLIB_DIR)
LIBS = -L$(LIBDIR) -lretroshare
ifdef PQI_USE_XPGP
LIBS += -L$(SSL_DIR)
endif
LIBS += -lssl -lcrypto
LIBS += -L$(UPNPC_DIR) -lminiupnpc
LIBS += -L$(ZLIB_DIR) -lz
LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d
LIBS += $(WINLIB)
RSCFLAGS += $(WININC)

View File

@ -0,0 +1,41 @@
ifneq ($(OS),Linux)
dummy:
echo "ERROR Linux configuration file included, but (OS != Linux)
endif
############ LINUX CONFIGURATION ########################
include $(TEST_TOP_DIR)/scripts/checks.mk
############ ENFORCE DIRECTORY NAMING ########################
CC = g++
RM = /bin/rm
RANLIB = ranlib
LIBDIR = $(LIB_TOP_DIR)/lib
LIBRS = $(LIBDIR)/libretroshare.a
# Unix: Linux/Cygwin
INCLUDE = -I $(LIB_TOP_DIR)
CFLAGS = -Wall -g $(INCLUDE)
CFLAGS += ${DEFINES} -D BE_DEBUG
#########################################################################
# OS Compile Options
#########################################################################
#########################################################################
# OS specific Linking.
#########################################################################
LIBS = -L$(LIBDIR) -lbitdht
LIBS += -lpthread
#LIBS += $(XLIB) -ldl -lz
#LIBS += -lupnp
#LIBS += -lgpgme
#
#RSLIBS = $(LIBS)

View File

@ -0,0 +1,152 @@
ifneq ($(OS),MacOSX)
dummy:
echo "ERROR MacOSX configuration file included, but (OS != MacOSX)
endif
############ LINUX CONFIGURATION ########################
# FLAGS to decide if we want i386 Build or ppc Build
#
#
# PPC is default
# Could define both for combined compilation...
# except might not work for bio_tou.c file!
#
# MAC_I386_BUILD = 1
# MAC_PPC_BUILD = 1
#MAC_I386_BUILD = 1
#MAC_PPC_BUILD = 1
ifndef MAC_I386_BUILD
MAC_PPC_BUILD = 1
endif
# flags for components....
#PQI_USE_SSLONLY = 1
#PQI_USE_XPGP = 1
#PQI_USE_PROXY = 1
#PQI_USE_CHANNELS = 1
#USE_FILELOOK = 1
SSL_DIR=../../../../../src/openssl-0.9.7g-xpgp-0.1c
UPNPC_DIR=../../../../../src/miniupnpc-1.0
include $(RS_TOP_DIR)/scripts/checks.mk
############ ENFORCE DIRECTORY NAMING ########################
CC = g++
RM = /bin/rm
RANLIB = ranlib
# Dummy ranlib -> can't do it until afterwards with universal binaries.
# RANLIB = ls -l
LIBDIR = $(RS_TOP_DIR)/lib
LIBRS = $(LIBDIR)/libretroshare.a
OPT_DIR = /opt/local
OPT_INCLUDE = $(OPT_DIR)/include
OPT_LIBS = $(OPT_DIR)/lib
INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE)
#CFLAGS = -Wall -O3
CFLAGS = -Wall -g
# Flags for architecture builds.
ifdef MAC_I386_BUILD
CFLAGS += -arch i386
endif
ifdef MAC_PPC_BUILD
CFLAGS += -arch ppc
endif
CFLAGS += $(INCLUDE)
# This Line is for Universal BUILD for 10.4 + 10.5
# (but unlikely to work unless Qt Libraries are build properly)
# CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk
ifdef PQI_USE_XPGP
INCLUDE += -I $(SSL_DIR)/include
CFLAGS += -DPQI_USE_XPGP
endif
ifdef PQI_USE_SSLONLY
CFLAGS += -DPQI_USE_SSLONLY
endif
ifdef PQI_USE_PROXY
CFLAGS += -DPQI_USE_PROXY
endif
ifdef PQI_USE_CHANNELS
CFLAGS += -DPQI_USE_CHANNELS
endif
ifdef USE_FILELOOK
CFLAGS += -DUSE_FILELOOK
endif
# RSCFLAGS = -Wall -O3 $(INCLUDE)
#########################################################################
# OS Compile Options
#########################################################################
# For the SSL BIO compilation. (Copied from OpenSSL compilation flags)
BIOCC = gcc
# Flags for architecture builds.
ifdef MAC_I386_BUILD
BIOCFLAGS = -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common
endif
ifdef MAC_PPC_BUILD
BIOCFLAGS = -arch ppc -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
endif
# MacOSX flags
# BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
# This is for the Universal Build...
# but is unlikely to work... as options are PPC specific....
#
# BIOCFLAGS = -arch ppc -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
#########################################################################
# OS specific Linking.
#########################################################################
LIBS = -Wl,-search_paths_first
# for Univeral BUILD
# LIBS += -arch ppc -arch i386
# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386
LIBS += -L$(LIBDIR) -lretroshare
ifdef PQI_USE_XPGP
LIBS += -L$(SSL_DIR)
endif
LIBS += -lssl -lcrypto -lpthread
LIBS += -L$(OPT_LIBS)
LIBS += -lgpgme -lgpg-error
LIBS += -L$(UPNPC_DIR) -lminiupnpc
LIBS += $(XLIB) -ldl -lz
RSLIBS = $(LIBS)

View File

@ -0,0 +1,138 @@
#ifneq ($(OS),"Win ")
#dummy:
# echo "ERROR OS = $(OS)"
# echo "ERROR MinGW configuration file included, but (OS != Win)
#
#endif
############ LINUX CONFIGURATION ########################
# flags for components....
#PQI_USE_XPGP = 1
#PQI_USE_PROXY = 1
#PQI_USE_CHANNELS = 1
#USE_FILELOOK = 1
###########################################################################
#### DrBobs Versions.... Please Don't Delete.
### Comment out if needed.
SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src
SRC_ROOT_GPG=/local
#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW
#SRC_ROOT=../../../..
PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2
ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3
SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp
UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3
###########################################################################
#### Enable this section for compiling with MSYS/MINGW compile
#SRC_ROOT=/home/linux
#SSL_DIR=$(SRC_ROOT)/OpenSSL
#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8
#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7
#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3
#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0
#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release
include $(RS_TOP_DIR)/scripts/checks.mk
############ ENFORCE DIRECTORY NAMING #######################################
CC = g++
RM = /bin/rm
RANLIB = ranlib
LIBDIR = $(RS_TOP_DIR)/lib
LIBRS = $(LIBDIR)/libretroshare.a
# Unix: Linux/Cygwin
INCLUDE = -I $(RS_TOP_DIR)
ifdef PQI_DEBUG
CFLAGS = -Wall -g $(INCLUDE)
else
CFLAGS = -Wall -O2 $(INCLUDE)
endif
# These aren't used anymore.... really.
ifdef PQI_USE_XPGP
CFLAGS += -DPQI_USE_XPGP
endif
ifdef PQI_USE_PROXY
CFLAGS += -DPQI_USE_PROXY
endif
ifdef PQI_USE_CHANNELS
CFLAGS += -DPQI_USE_CHANNELS
endif
ifdef USE_FILELOOK
CFLAGS += -DUSE_FILELOOK
endif
# SSL / pthreads / Zlib
# included by default for Windows compilation.
INCLUDE += -I $(SSL_DIR)/include
INCLUDE += -I$(PTHREADS_DIR)
INCLUDE += -I$(ZLIB_DIR)
#########################################################################
# OS Compile Options
#########################################################################
# For the SSL BIO compilation. (Copied from OpenSSL compilation flags)
BIOCC = gcc
# Cygwin - ?same? as Linux flags
BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM
BIOCFLAGS += -DWINDOWS_SYS
#########################################################################
# OS specific Linking.
#########################################################################
# for static pthread libs....
#WININC += -DPTW32_STATIC_LIB
#WININC += -mno-cygwin -mwindows -fno-exceptions
WININC += -DWINDOWS_SYS
WINLIB = -lws2_32 -luuid -lole32 -liphlpapi
WINLIB += -lcrypt32 -lwinmm
CFLAGS += -I$(SSL_DIR)/include
CFLAGS += -I$(PTHREADS_DIR)/include
CFLAGS += -I$(ZLIB_DIR)
CFLAGS += -I$(SRC_ROOT_GPG)/include
### Enable this for GPGME and GPG ERROR dirs
#CFLAGS += -I$(GPGME_DIR)/src
#CFLAGS += -I$(GPG_ERROR_DIR)/src
CFLAGS += $(WININC)
LIBS = -L$(LIBDIR) -lretroshare
LIBS += -L$(SSL_DIR)
LIBS += -lssl -lcrypto
LIBS += -L$(UPNPC_DIR) -lminiupnpc
LIBS += -L$(ZLIB_DIR) -lz
LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d
LIBS += $(WINLIB)
#RSCFLAGS = -Wall -g $(INCLUDE)
#RSCFLAGS += $(WININC)

View File

@ -0,0 +1,27 @@
# determine which operating system
#
###########################################################################
#Define OS.
#
OS = Linux
#OS = MacOSX
#OS = Cygwin
#OS = Win # MinGw.
###########################################################################
ifeq ($(OS),Linux)
include $(TEST_TOP_DIR)/scripts/config-linux.mk
else
ifeq ($(OS),MacOSX)
include $(TEST_TOP_DIR)/scripts/config-macosx.mk
else
ifeq ($(OS),Cygwin)
include $(TEST_TOP_DIR)/scripts/config-cygwin.mk
else
include $(TEST_TOP_DIR)/scripts/config-mingw.mk
endif
endif
endif
###########################################################################

View File

@ -0,0 +1,25 @@
testoutputfiles = $(foreach tt,$(1),$(tt).tstout)
%.tstout : %.sh
-sh ./$< > $@ 2>&1
%.tstout : %
-./$< > $@ 2>&1
TESTOUT = $(call testoutputfiles,$(TESTS))
.phony : tests regress retest clobber
tests: $(TESTS)
regress: $(TESTOUT)
@-echo "--------------- SUCCESS (count):"
@-grep -c SUCCESS $(TESTOUT)
@-echo "--------------- FAILURE REPORTS:"
@-grep FAILURE $(TESTOUT) || echo no failures
@-echo "--------------- end"
retest:
-/bin/rm $(TESTOUT)

View File

@ -0,0 +1,19 @@
# defines required / used.
#
# CFLAGS
#
#
.cc.o:
$(CC) $(CFLAGS) -c $<
clean:
-/bin/rm $(EXECOBJ) $(TESTOBJ)
clobber: clean retest
-/bin/rm $(EXEC) $(TESTS)
include $(TEST_TOP_DIR)/scripts/regress.mk

View File

@ -0,0 +1,188 @@
/*
* bitdht/udpbitdht.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "udp/udpbitdht.h"
#include "bitdht/bdpeer.h"
#include "bitdht/bdstore.h"
#include "bitdht/bdmsgs.h"
#include "bitdht/bencode.h"
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* #define DEBUG_UDP_BITDHT 1
*/
//#define DEBUG_UDP_BITDHT 1
/*************************************/
UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string dhtVersion, std::string bootstrapfile, bdDhtFunctions *fns)
:UdpSubReceiver(pub), mFns(fns)
{
/* setup nodeManager */
mBitDhtManager = new bdNodeManager(id, dhtVersion, bootstrapfile, fns);
}
UdpBitDht::~UdpBitDht()
{
return;
}
/*********** External Interface to the World ************/
/***** Functions to Call down to bdNodeManager ****/
/* Request DHT Peer Lookup */
/* Request Keyword Lookup */
void UdpBitDht::addFindNode(bdNodeId *id, uint32_t mode)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
mBitDhtManager->addFindNode(id, mode);
}
void UdpBitDht::removeFindNode(bdNodeId *id)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
mBitDhtManager->removeFindNode(id);
}
void UdpBitDht::findDhtValue(bdNodeId *id, std::string key, uint32_t mode)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
mBitDhtManager->findDhtValue(id, key, mode);
}
/***** Add / Remove Callback Clients *****/
void UdpBitDht::addCallback(BitDhtCallback *cb)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
mBitDhtManager->addCallback(cb);
}
void UdpBitDht::removeCallback(BitDhtCallback *cb)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
mBitDhtManager->removeCallback(cb);
}
int UdpBitDht::getDhtPeerAddress(bdNodeId *id, struct sockaddr_in &from)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
return mBitDhtManager->getDhtPeerAddress(id, from);
}
int UdpBitDht::getDhtValue(bdNodeId *id, std::string key, std::string &value)
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
return mBitDhtManager->getDhtValue(id, key, value);
}
/******************* Internals *************************/
/***** Iteration / Loop Management *****/
/*** Overloaded from UdpSubReceiver ***/
int UdpBitDht::recvPkt(void *data, int size, struct sockaddr_in &from)
{
/* pass onto bitdht */
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
/* check packet suitability */
if (mBitDhtManager->isBitDhtPacket((char *) data, size, from))
{
mBitDhtManager->incomingMsg(&from, (char *) data, size);
return 1;
}
return 0;
}
int UdpBitDht::status(std::ostream &out)
{
out << "UdpBitDht::status()" << std::endl;
return 1;
}
/*** Overloaded from iThread ***/
void UdpBitDht::run()
{
while(1)
{
tick();
sleep(1);
}
}
int UdpBitDht::tick()
{
bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/
/* pass on messages from the node */
int i = 0;
char data[BITDHT_MAX_PKTSIZE];
struct sockaddr_in toAddr;
int size = BITDHT_MAX_PKTSIZE;
/* accept up to 10 msgs / tick() */
while((i < 10) && (mBitDhtManager->outgoingMsg(&toAddr, data, &size)))
{
#ifdef DEBUG_UDP_BITDHT
std::cerr << "UdpBitDht::tick() outgoing msg(" << size << ") to " << toAddr;
std::cerr << std::endl;
#endif
sendPkt(data, size, toAddr, BITDHT_TTL);
// iterate
i++;
size = BITDHT_MAX_PKTSIZE; // reset msg size!
}
mBitDhtManager->iteration();
return 1;
}

View File

@ -0,0 +1,96 @@
#ifndef UDP_BIT_DHT_CLASS_H
#define UDP_BIT_DHT_CLASS_H
/*
* bitdht/udpbitdht.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <iosfwd>
#include <map>
#include <string>
#include "udp/udpstack.h"
#include "bitdht/bdiface.h"
#include "bitdht/bdmanager.h"
/*
* This implements a UdpSubReceiver class to allow the DHT to talk to the network.
* The parser is very strict - and will try to not pick up anyone else's messages.
*
* Mutexes are implemented at this level protecting the whole of the DHT code.
* This class is also a thread - enabling it to do callback etc.
*/
// class BitDhtCallback defined in bdiface.h
class UdpBitDht: public UdpSubReceiver, public bdThread, public BitDhtInterface
{
public:
UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string dhtVersion, std::string bootstrapfile, bdDhtFunctions *fns);
virtual ~UdpBitDht();
/*********** External Interface to the World (BitDhtInterface) ************/
/***** Functions to Call down to bdNodeManager ****/
/* Request DHT Peer Lookup */
/* Request Keyword Lookup */
virtual void addFindNode(bdNodeId *id, uint32_t mode);
virtual void removeFindNode(bdNodeId *id);
virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode);
/***** Add / Remove Callback Clients *****/
virtual void addCallback(BitDhtCallback *cb);
virtual void removeCallback(BitDhtCallback *cb);
/***** Get Results Details *****/
virtual int getDhtPeerAddress(bdNodeId *id, struct sockaddr_in &from);
virtual int getDhtValue(bdNodeId *id, std::string key, std::string &value);
/******************* Internals *************************/
/***** Iteration / Loop Management *****/
/*** Overloaded from UdpSubReceiver ***/
virtual int recvPkt(void *data, int size, struct sockaddr_in &from);
virtual int status(std::ostream &out);
/*** Overloaded from iThread ***/
virtual void run();
/**** do whats to be done ***/
int tick();
private:
bdMutex dhtMtx; /* for all class data (below) */
bdNodeManager *mBitDhtManager;
bdDhtFunctions *mFns;
};
#endif

View File

@ -0,0 +1,124 @@
/*
* bitdht/udpbitdht_nettest.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "udpbitdht.h"
#include "udpstack.h"
#include "bdstddht.h"
#include <string.h>
#include <stdlib.h>
/*******************************************************************
* Test of bencode message creation functions in bdmsgs.cc
*
* Create a couple of each type.
*/
#define MAX_MESSAGE_LEN 10240
int main(int argc, char **argv)
{
/* setup id, and bootstrap file */
if (argc < 2)
{
std::cerr << " Missing port number " << std::endl;
exit(1);
}
int delta = 0;
if (argc < 3)
{
std::cerr << "No Id Delta" << std::endl;
}
else
{
delta = atoi(argv[2]);
}
int port = atoi(argv[1]);
std::cerr << "Using Port: " << port << std::endl;
std::cerr << "Using Delta: " << delta << std::endl;
bdDhtFunctions *fns = new bdStdDht();
bdNodeId id;
memcpy(((char *) id.data), "1234567890abcdefghi", 20);
uint32_t *deltaptr = (uint32_t *) (id.data);
(*deltaptr) += htonl(delta);
std::cerr << "Using NodeId: ";
fns->bdPrintNodeId(std::cerr, &id);
std::cerr << std::endl;
std::string bootstrapfile = "bdboot.txt";
/* setup the udp port */
struct sockaddr_in local;
local.sin_port = htons(port);
UdpStack *udpstack = new UdpStack(local);
/* create bitdht component */
std::string dhtVersion = "dbTEST";
UdpBitDht *bitdht = new UdpBitDht(udpstack, &id, dhtVersion, bootstrapfile, fns);
/* add in the stack */
udpstack->addReceiver(bitdht);
/* register callback display */
bdDebugCallback *cb = new bdDebugCallback();
bitdht->addCallback(cb);
/* startup threads */
//udpstack->start();
bitdht->start();
/* do a couple of random continuous searchs. */
uint32_t mode = BITDHT_QFLAGS_DO_IDLE;
int count = 0;
while(1)
{
sleep(120);
if (++count == 2)
{
/* switch to one-shot searchs */
mode = 0;
}
bdNodeId rndId;
bdStdRandomNodeId(&rndId);
bitdht->addFindNode(&rndId, mode);
}
return 1;
}

View File

@ -0,0 +1,497 @@
/*
* bitdht/udplayer.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "udplayer.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
/*
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
*/
/***
* #define DEBUG_UDP_LAYER 1
***/
#define OPEN_UNIVERSAL_PORT 1
static const int UDP_DEF_TTL = 64;
class udpPacket
{
public:
udpPacket(struct sockaddr_in *addr, void *dta, int dlen)
:raddr(*addr), len(dlen)
{
data = malloc(len);
memcpy(data, dta, len);
}
~udpPacket()
{
if (data)
{
free(data);
data = NULL;
len = 0;
}
}
struct sockaddr_in raddr;
void *data;
int len;
};
std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr)
{
out << "[" << inet_ntoa(addr.sin_addr) << ":";
out << htons(addr.sin_port) << "]";
return out;
}
bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2)
{
if (addr.sin_family != addr2.sin_family)
return false;
if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr)
return false;
if (addr.sin_port != addr2.sin_port)
return false;
return true;
}
bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2)
{
if (addr.sin_family != addr2.sin_family)
return (addr.sin_family < addr2.sin_family);
if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr)
return (addr.sin_addr.s_addr < addr2.sin_addr.s_addr);
if (addr.sin_port != addr2.sin_port)
return (addr.sin_port < addr2.sin_port);
return false;
}
std::string printPkt(void *d, int size)
{
std::ostringstream out;
out << "Packet:" << "**********************";
for(int i = 0; i < size; i++)
{
if (i % 16 == 0)
out << std::endl;
out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i] << " ";
}
out << std::endl << "**********************";
out << std::endl;
return out.str();
}
std::string printPktOffset(unsigned int offset, void *d, unsigned int size)
{
std::ostringstream out;
out << "Packet:" << "**********************";
out << std::endl;
out << "Offset: " << std::hex << offset << " -> " << offset + size;
out << std::endl;
out << "Packet:" << "**********************";
unsigned int j = offset % 16;
if (j != 0)
{
out << std::endl;
out << std::hex << std::setw(6) << (unsigned int) offset - j;
out << ": ";
for(unsigned int i = 0; i < j; i++)
{
out << "xx ";
}
}
for(unsigned int i = offset; i < offset + size; i++)
{
if (i % 16 == 0)
{
out << std::endl;
out << std::hex << std::setw(6) << (unsigned int) i;
out << ": ";
}
out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i-offset] << " ";
}
out << std::endl << "**********************";
out << std::endl;
return out.str();
}
UdpLayer::UdpLayer(UdpReceiver *udpr, struct sockaddr_in &local)
:recv(udpr), laddr(local), errorState(0), ttl(UDP_DEF_TTL)
{
openSocket();
return;
}
int UdpLayer::status(std::ostream &out)
{
out << "UdpLayer::status()" << std::endl;
out << "localaddr: " << laddr << std::endl;
out << "sockfd: " << sockfd << std::endl;
out << std::endl;
return 1;
}
int UdpLayer::reset(struct sockaddr_in &local)
{
std::cerr << "UdpLayer::reset()" << std::endl;
/* stop the old thread */
{
bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl;
stopThread = true;
}
std::cerr << "UdpLayer::reset() joining" << std::endl;
join();
std::cerr << "UdpLayer::reset() closing socket" << std::endl;
closeSocket();
std::cerr << "UdpLayer::reset() resetting variables" << std::endl;
laddr = local;
errorState = 0;
ttl = UDP_DEF_TTL;
std::cerr << "UdpLayer::reset() opening socket" << std::endl;
openSocket();
return 1;
}
int UdpLayer::closeSocket()
{
/* close socket if open */
sockMtx.lock(); /********** LOCK MUTEX *********/
if (sockfd > 0)
{
close(sockfd);
}
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return 1;
}
void UdpLayer::run()
{
return recv_loop();
}
/* higher level interface */
void UdpLayer::recv_loop()
{
int maxsize = 16000;
void *inbuf = malloc(maxsize);
int status;
struct timeval timeout;
while(1)
{
/* select on the socket TODO */
fd_set rset;
for(;;)
{
/* check if we need to stop */
bool toStop = false;
{
bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
toStop = stopThread;
}
if (toStop)
{
std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl;
stop();
}
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
timeout.tv_sec = 0;
timeout.tv_usec = 500000; /* 500 ms timeout */
status = select(sockfd+1, &rset, NULL, NULL, &timeout);
if (status > 0)
{
break; /* data available, go read it */
}
else if (status < 0)
{
std::cerr << "UdpLayer::recv_loop() ";
std::cerr << "Error: " << errno << std::endl;
}
};
int nsize = maxsize;
struct sockaddr_in from;
if (0 < receiveUdpPacket(inbuf, &nsize, from))
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::readPkt() from : " << from << std::endl;
std::cerr << printPkt(inbuf, nsize);
#endif
// send to reciever.
recv -> recvPkt(inbuf, nsize, from);
}
else
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::readPkt() not ready" << from;
std::cerr << std::endl;
#endif
}
}
return;
}
int UdpLayer::sendPkt(const void *data, int size, sockaddr_in &to, int ttl)
{
/* if ttl is different -> set it */
if (ttl != getTTL())
{
setTTL(ttl);
}
/* and send! */
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::sendPkt() to: " << to << std::endl;
std::cerr << printPkt((void *) data, size);
#endif
sendUdpPacket(data, size, to);
return size;
}
/* setup connections */
int UdpLayer::openSocket()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
/* make a socket */
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
#ifdef DEBUG_UDP_LAYER
std::cerr << "UpdStreamer::openSocket()" << std::endl;
#endif
/* bind to address */
#ifdef UDP_LOOPBACK_TESTING
inet_aton("127.0.0.1", &(laddr.sin_addr));
#endif
#ifdef OPEN_UNIVERSAL_PORT
struct sockaddr_in tmpaddr = laddr;
tmpaddr.sin_addr.s_addr = 0;
if (0 != bind(sockfd, (struct sockaddr *) (&tmpaddr), sizeof(tmpaddr)))
#else
if (0 != bind(sockfd, (struct sockaddr *) (&laddr), sizeof(laddr)))
#endif
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "Socket Failed to Bind to : " << laddr << std::endl;
std::cerr << "Error: " << errno << std::endl;
#endif
errorState = EADDRINUSE;
//exit(1);
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return -1;
}
if (-1 == fcntl(sockfd, F_SETFL, O_NONBLOCK))
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "Failed to Make Non-Blocking" << std::endl;
#endif
}
/* Setup socket for broadcast. */
int val = 1;
if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int)))
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "Failed to Make Socket Broadcast" << std::endl;
#endif
}
errorState = 0;
#ifdef DEBUG_UDP_LAYER
std::cerr << "Socket Bound to : " << laddr << std::endl;
#endif
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
std::cerr << "Setting TTL to " << UDP_DEF_TTL << std::endl;
#endif
setTTL(UDP_DEF_TTL);
// start up our thread.
{
bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
stopThread = false;
}
start();
return 1;
}
int UdpLayer::setTTL(int t)
{
sockMtx.lock(); /********** LOCK MUTEX *********/
int err = setsockopt(sockfd, IPPROTO_IP, IP_TTL, &t, sizeof(int));
ttl = t;
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::setTTL(" << t << ") returned: " << err;
std::cerr << std::endl;
#endif
return err;
}
int UdpLayer::getTTL()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
int t = ttl;
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return t;
}
/* monitoring / updates */
int UdpLayer::okay()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
bool nonFatalError = ((errorState == 0) ||
(errorState == EAGAIN) ||
(errorState == EINPROGRESS));
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
if (!nonFatalError)
{
std::cerr << "UdpLayer::NOT okay(): Error: " << errorState << std::endl;
}
#endif
return nonFatalError;
}
int UdpLayer::tick()
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::tick()" << std::endl;
#endif
return 1;
}
/******************* Internals *************************************/
int UdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from)
{
struct sockaddr_in fromaddr;
socklen_t fromsize = sizeof(fromaddr);
int insize = *size;
sockMtx.lock(); /********** LOCK MUTEX *********/
insize = recvfrom(sockfd,data,insize,0,
(struct sockaddr*)&fromaddr,&fromsize);
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
if (0 < insize)
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "receiveUdpPacket() from: " << fromaddr;
std::cerr << " Size: " << insize;
std::cerr << std::endl;
#endif
*size = insize;
from = fromaddr;
return insize;
}
return -1;
}
int UdpLayer::sendUdpPacket(const void *data, int size, struct sockaddr_in &to)
{
/* send out */
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::sendUdpPacket(): size: " << size;
std::cerr << " To: " << to << std::endl;
#endif
struct sockaddr_in toaddr = to;
sockMtx.lock(); /********** LOCK MUTEX *********/
sendto(sockfd, data, size, 0,
(struct sockaddr *) &(toaddr),
sizeof(toaddr));
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return 1;
}

View File

@ -0,0 +1,128 @@
#ifndef BITDHT_UDP_LAYER_H
#define BITDHT_UDP_LAYER_H
/*
* bitdht/udplayer.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <netinet/in.h>
#include "util/bdthreads.h"
#include <iosfwd>
#include <list>
#include <deque>
/****
* #define UDP_LOOPBACK_TESTING 1
***/
std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr);
bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2);
bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2);
std::string printPkt(void *d, int size);
std::string printPktOffset(unsigned int offset, void *d, unsigned int size);
/* UdpLayer ..... is the bottom layer which
* just sends and receives Udp packets.
*/
class UdpReceiver
{
public:
virtual ~UdpReceiver() {}
virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0;
virtual int status(std::ostream &out) = 0;
};
class UdpPublisher
{
public:
virtual ~UdpPublisher() {}
virtual int sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl) = 0;
};
class UdpLayer: public bdThread
{
public:
UdpLayer(UdpReceiver *recv, struct sockaddr_in &local);
virtual ~UdpLayer() { return; }
int reset(struct sockaddr_in &local); /* calls join, close, openSocket */
int status(std::ostream &out);
/* setup connections */
int closeSocket();
int openSocket();
/* RsThread functions */
virtual void run(); /* called once the thread is started */
void recv_loop(); /* uses callback to UdpReceiver */
/* Higher Level Interface */
//int readPkt(void *data, int *size, struct sockaddr_in &from);
int sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl);
/* monitoring / updates */
int okay();
int tick();
/* data */
/* internals */
protected:
virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from);
virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to);
int setTTL(int t);
int getTTL();
/* low level */
private:
UdpReceiver *recv;
struct sockaddr_in laddr; /* local addr */
int errorState;
int sockfd;
int ttl;
bool stopThread;
bdMutex sockMtx;
};
#endif

View File

@ -0,0 +1,215 @@
/*
* bitdht/udpstack.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "udpstack.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <algorithm>
/***
* #define DEBUG_UDP_RECV 1
***/
//#define DEBUG_UDP_RECV 1
UdpStack::UdpStack(struct sockaddr_in &local)
:udpLayer(NULL), laddr(local)
{
openSocket();
return;
}
bool UdpStack::resetAddress(struct sockaddr_in &local)
{
return udpLayer->reset(local);
}
/* higher level interface */
int UdpStack::recvPkt(void *data, int size, struct sockaddr_in &from)
{
/* print packet information */
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from;
std::cerr << std::endl;
#endif
bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/
std::list<UdpReceiver *>::iterator it;
for(it = mReceivers.begin(); it != mReceivers.end(); it++)
{
// See if they want the packet.
if ((*it)->recvPkt(data, size, from))
{
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from;
std::cerr << std::endl;
#endif
break;
}
}
return 1;
}
int UdpStack::sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl)
{
/* print packet information */
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpStack::sendPkt(" << size << ") ttl: " << ttl;
std::cerr << " to: " << to;
std::cerr << std::endl;
#endif
/* send to udpLayer */
return udpLayer->sendPkt(data, size, to, ttl);
}
int UdpStack::status(std::ostream &out)
{
{
bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/
out << "UdpStack::status()" << std::endl;
out << "localaddr: " << laddr << std::endl;
out << "UdpStack::SubReceivers:" << std::endl;
std::list<UdpReceiver *>::iterator it;
int i = 0;
for(it = mReceivers.begin(); it != mReceivers.end(); it++, i++)
{
out << "\tReceiver " << i << " --------------------" << std::endl;
(*it)->status(out);
}
out << "--------------------" << std::endl;
out << std::endl;
}
udpLayer->status(out);
return 1;
}
/* setup connections */
int UdpStack::openSocket()
{
udpLayer = new UdpLayer(this, laddr);
return 1;
}
/* monitoring / updates */
int UdpStack::okay()
{
return udpLayer->okay();
}
int UdpStack::close()
{
/* TODO */
return 1;
}
/* add a TCPonUDP stream */
int UdpStack::addReceiver(UdpReceiver *recv)
{
bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::list<UdpReceiver *>::iterator it;
it = std::find(mReceivers.begin(), mReceivers.end(), recv);
if (it == mReceivers.end())
{
mReceivers.push_back(recv);
return 1;
}
/* otherwise its already there! */
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpStack::addReceiver() Recv already exists!" << std::endl;
std::cerr << "UdpStack::addReceiver() ERROR" << std::endl;
#endif
return 0;
}
int UdpStack::removeReceiver(UdpReceiver *recv)
{
bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::list<UdpReceiver *>::iterator it;
it = std::find(mReceivers.begin(), mReceivers.end(), recv);
if (it != mReceivers.end())
{
mReceivers.erase(it);
return 1;
}
/* otherwise its not there! */
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpStack::removeReceiver() Recv dont exist!" << std::endl;
std::cerr << "UdpStack::removeReceiver() ERROR" << std::endl;
#endif
return 0;
}
/*****************************************************************************************/
UdpSubReceiver::UdpSubReceiver(UdpPublisher *pub)
:mPublisher(pub)
{
return;
}
int UdpSubReceiver::sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl)
{
/* print packet information */
#ifdef DEBUG_UDP_RECV
std::cerr << "UdpSubReceiver::sendPkt(" << size << ") ttl: " << ttl;
std::cerr << " to: " << to;
std::cerr << std::endl;
#endif
/* send to udpLayer */
return mPublisher->sendPkt(data, size, to, ttl);
}

View File

@ -0,0 +1,110 @@
#ifndef BITDHT_UDP_STACK_RECEIVER_H
#define BITDHT_UDP_STACK_RECEIVER_H
/*
* bitdht/udpstack.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <netinet/in.h>
#include "util/bdthreads.h"
#include <iosfwd>
#include <list>
#include <deque>
#include <iosfwd>
#include <map>
#include "udplayer.h"
/* UdpStackReceiver is a Generic Receiver of info from a UdpLayer class.
* it provides a UdpReceiver class, and accepts a stack of UdpReceivers,
* which will be iterated through (in-order) until someone accepts the packet.
*
* It is important to order these Receivers correctly!
*
* This infact becomes the holder of the UdpLayer, and all controls
* go through the StackReceiver.
*/
class UdpSubReceiver: public UdpReceiver
{
public:
UdpSubReceiver(UdpPublisher *pub);
/* calls mPublisher->sendPkt */
virtual int sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl);
/* callback for recved data (overloaded from UdpReceiver) */
//virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0;
UdpPublisher *mPublisher;
};
class UdpStack: public UdpReceiver, public UdpPublisher
{
public:
UdpStack(struct sockaddr_in &local);
virtual ~UdpStack() { return; }
bool resetAddress(struct sockaddr_in &local);
/* add in a receiver */
int addReceiver(UdpReceiver *recv);
int removeReceiver(UdpReceiver *recv);
/* Packet IO */
/* pass-through send packets */
virtual int sendPkt(const void *data, int size, struct sockaddr_in &to, int ttl);
/* callback for recved data (overloaded from UdpReceiver) */
virtual int recvPkt(void *data, int size, struct sockaddr_in &from);
int status(std::ostream &out);
/* setup connections */
int openSocket();
/* monitoring / updates */
int okay();
// int tick();
int close();
private:
UdpLayer *udpLayer;
bdMutex stackMtx; /* for all class data (below) */
struct sockaddr_in laddr; /* local addr */
std::list<UdpReceiver *> mReceivers;
};
#endif

View File

@ -0,0 +1,79 @@
/*
* bitdht/bdthreads.cc
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include "bdthreads.h"
#include <unistd.h> /* for usleep() */
/*******
* #define DEBUG_THREADS 1
*******/
#ifdef DEBUG_THREADS
#include <iostream>
#endif
extern "C" void* bdthread_init(void* p)
{
bdThread *thread = (bdThread *) p;
if (!thread)
{
return 0;
}
thread -> run();
return 0;
}
pthread_t createThread(bdThread &thread)
{
pthread_t tid;
void *data = (void *) (&thread);
thread.mMutex.lock();
{
pthread_create(&tid, 0, &bdthread_init, data);
thread.mTid = tid;
}
thread.mMutex.unlock();
return tid;
}
void bdThread::join() /* waits for the the mTid thread to stop */
{
void *ptr;
pthread_join(mTid, &ptr);
}
void bdThread::stop()
{
pthread_exit(NULL);
}

View File

@ -0,0 +1,81 @@
#ifndef BITDHT_THREADS_H
#define BITDHT_THREADS_H
/*
* bitdht/bdthreads.h
*
* BitDHT: An Flexible DHT library.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "bitdht@lunamutt.com".
*
*/
#include <pthread.h>
#include <inttypes.h>
/* Thread Wrappers */
class bdMutex
{
public:
bdMutex() { pthread_mutex_init(&realMutex, NULL); }
~bdMutex() { pthread_mutex_destroy(&realMutex); }
void lock() { pthread_mutex_lock(&realMutex); }
void unlock() { pthread_mutex_unlock(&realMutex); }
bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); }
private:
pthread_mutex_t realMutex;
};
class bdStackMutex
{
public:
bdStackMutex(bdMutex &mtx): mMtx(mtx) { mMtx.lock(); }
~bdStackMutex() { mMtx.unlock(); }
private:
bdMutex &mMtx;
};
class bdThread;
/* to create a thread! */
pthread_t createThread(bdThread &thread);
class bdThread
{
public:
bdThread() { return; }
virtual ~bdThread() { return; }
virtual void start() { createThread(*this); }
virtual void run() = 0; /* called once the thread is started */
virtual void join(); /* waits for the mTid thread to stop */
virtual void stop(); /* calls pthread_exit() */
pthread_t mTid;
bdMutex mMutex;
};
#endif