'
14 | for to in `grep -v '#' ../$SERVERS`; do
15 | echo ' | >'$to' | '
16 | done
17 | echo ''
18 | for from in `grep -v '#' ../$SERVERS`; do
19 | echo ''$from'> | '
20 | for to in `grep -v '#' ../$SERVERS`; do
21 | echo ''
22 | cat $from-$to.html
23 | if [ -e "$from-$to.big.png" ]; then
24 | echo ""
25 | echo " "
26 | echo ""
27 | fi
28 | echo ' | '
29 | done
30 | echo '
'
31 | done
32 | echo ''
33 |
--------------------------------------------------------------------------------
/mfold/net.aussie.sh:
--------------------------------------------------------------------------------
1 | echo eth0 > .netem-on
2 |
3 | sudo tc qdisc add dev eth0 root netem delay 400ms
4 |
--------------------------------------------------------------------------------
/mfold/net.lossy.sh:
--------------------------------------------------------------------------------
1 | echo eth0 > .netem-on
2 |
3 | sudo tc qdisc add dev eth0 root netem delay 100ms loss 5.0%
4 |
--------------------------------------------------------------------------------
/mfold/net.messy.sh:
--------------------------------------------------------------------------------
1 | echo eth0 > .netem-on
2 |
3 | sudo tc qdisc add dev eth0 root netem delay 100ms 20ms 25%
4 |
--------------------------------------------------------------------------------
/mfold/netem.default.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ ! $EMIF ] ; then
4 | exit
5 | fi
6 |
7 | if [ ! $EMLOSS ]; then
8 | EMLOSS=0%
9 | fi
10 |
11 | if [ ! $EMDELAY ]; then
12 | EMDELAY=10ms
13 | fi
14 |
15 | if [ ! $EMBW ]; then
16 | EMBW=10mbit
17 | fi
18 |
19 | if [ ! $EMJTTR ]; then
20 | EMJTTR=0ms
21 | fi
22 |
23 | TC="sudo tc "
24 |
25 | echo ifb0 up
26 | sudo modprobe ifb
27 | sudo ip link set dev ifb0 up
28 |
29 | echo cleanup
30 | $TC qdisc del dev $EMIF ingress
31 | $TC qdisc del dev ifb0 root
32 |
33 | echo adding ingress
34 | $TC qdisc add dev $EMIF ingress || exit 1
35 |
36 | echo redirecting to ifb
37 | $TC filter add dev $EMIF parent ffff: protocol ip prio 1 u32 \
38 | match ip sport $SWFTPORT 0xffff flowid 1:1 action mirred egress redirect dev ifb0 || exit 2
39 | echo adding netem for $EMDELAY - $EMLOSS
40 | $TC qdisc add dev ifb0 root handle 1:0 netem delay $EMDELAY $EMJTTR 25% loss $EMLOSS || exit 3
41 | echo adding tfb for $EMBW
42 | $TC qdisc add dev ifb0 parent 1:1 handle 10: tbf rate $EMBW buffer 102400 latency 40ms || exit 4
43 |
44 |
--------------------------------------------------------------------------------
/mfold/ps.default.sh:
--------------------------------------------------------------------------------
1 | if ps -ef | grep l[e]echer > /dev/null; then
2 | echo `hostname` has a running leecher
3 | return 1
4 | fi
5 |
--------------------------------------------------------------------------------
/mfold/report.css:
--------------------------------------------------------------------------------
1 | table#main table {
2 | background: #ffe;
3 | }
4 |
5 | td.host {
6 | text-align: center;
7 | font: 24pt "Courier";
8 | }
9 |
10 | table.channel {
11 | /* border: 1 dotted #aa5; */
12 | font-size: smaller;
13 | }
14 |
15 | td {
16 | border-top: 1 dotted #aa5;
17 | border-spacing: 0;
18 | }
19 |
20 | pp {
21 | color: #a00;
22 | }
23 |
24 | tr.bytes {
25 | background: #fed;
26 | }
27 |
28 | img.thumb {
29 | width: 160pt;
30 | border-style: none;
31 | }
32 |
33 | table#main tr td {
34 | vertical-align: top;
35 | }
36 |
--------------------------------------------------------------------------------
/mfold/run.default.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This script runs a leecher at some server;
3 | # env variables are set in env.default.sh
4 |
5 | ulimit -c 1024000
6 | cd swift || exit 1
7 | rm -f core
8 | rm -f chunk
9 | sleep $(( $RANDOM % 5 ))
10 | bin/swift-o2 -w -h $HASH -f chunk -t $SEEDER:$SWFTPORT \
11 | -l 0.0.0.0:$RUNPORT -p -D 2>lerr | gzip > lout.gz || exit 2
12 |
--------------------------------------------------------------------------------
/mfold/run.seeder.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ulimit -c 1024000
4 | cd swift || exit 2
5 | if [ ! -e ScottKim_2008P.mp4 ]; then
6 | wget -c http://video.ted.com/talks/podcast/ScottKim_2008P.mp4 || exit 1
7 | fi
8 |
9 | bin/swift-o2 -w -f ScottKim_2008P.mp4 -p -D \
10 | -l 0.0.0.0:$SWFTPORT 2>lerr | gzip > lout.gz || exit 2
11 | exit
12 |
--------------------------------------------------------------------------------
/mfold/status.default.sh:
--------------------------------------------------------------------------------
1 | echo -e $HOST"\t"`tail -1 swift/lerr`
2 |
--------------------------------------------------------------------------------
/send_control.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * send_control.cpp
3 | * congestion control logic for the swift protocol
4 | *
5 | * Created by Victor Grishchenko on 12/10/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 |
10 | #include "swift.h"
11 |
12 | using namespace swift;
13 | using namespace std;
14 |
15 | tint Channel::MIN_DEV = 50*TINT_MSEC;
16 | tint Channel::MAX_SEND_INTERVAL = TINT_SEC*58;
17 | tint Channel::LEDBAT_TARGET = TINT_MSEC*25;
18 | float Channel::LEDBAT_GAIN = 1.0/LEDBAT_TARGET;
19 | tint Channel::LEDBAT_DELAY_BIN = TINT_SEC*30;
20 | tint Channel::MAX_POSSIBLE_RTT = TINT_SEC*10;
21 | const char* Channel::SEND_CONTROL_MODES[] = {"keepalive", "pingpong",
22 | "slowstart", "standard_aimd", "ledbat", "closing"};
23 |
24 |
25 | tint Channel::NextSendTime () {
26 | TimeoutDataOut(); // precaution to know free cwnd
27 | switch (send_control_) {
28 | case KEEP_ALIVE_CONTROL: return KeepAliveNextSendTime();
29 | case PING_PONG_CONTROL: return PingPongNextSendTime();
30 | case SLOW_START_CONTROL: return SlowStartNextSendTime();
31 | case AIMD_CONTROL: return AimdNextSendTime();
32 | case LEDBAT_CONTROL: return LedbatNextSendTime();
33 | case CLOSE_CONTROL: return TINT_NEVER;
34 | default: assert(false);
35 | }
36 | }
37 |
38 | tint Channel::SwitchSendControl (int control_mode) {
39 | dprintf("%s #%u sendctrl switch %s->%s\n",tintstr(),id(),
40 | SEND_CONTROL_MODES[send_control_],SEND_CONTROL_MODES[control_mode]);
41 | switch (control_mode) {
42 | case KEEP_ALIVE_CONTROL:
43 | send_interval_ = rtt_avg_; //max(TINT_SEC/10,rtt_avg_);
44 | dev_avg_ = max(TINT_SEC,rtt_avg_);
45 | data_out_cap_ = bin64_t::ALL;
46 | cwnd_ = 1;
47 | break;
48 | case PING_PONG_CONTROL:
49 | dev_avg_ = max(TINT_SEC,rtt_avg_);
50 | data_out_cap_ = bin64_t::ALL;
51 | cwnd_ = 1;
52 | break;
53 | case SLOW_START_CONTROL:
54 | cwnd_ = 1;
55 | break;
56 | case AIMD_CONTROL:
57 | break;
58 | case LEDBAT_CONTROL:
59 | break;
60 | case CLOSE_CONTROL:
61 | break;
62 | default:
63 | assert(false);
64 | }
65 | send_control_ = control_mode;
66 | return NextSendTime();
67 | }
68 |
69 | tint Channel::KeepAliveNextSendTime () {
70 | if (sent_since_recv_>=3 && last_recv_time_MAX_SEND_INTERVAL)
79 | send_interval_ = MAX_SEND_INTERVAL;
80 | return last_send_time_ + send_interval_;
81 | }
82 |
83 | tint Channel::PingPongNextSendTime () { // FIXME INFINITE LOOP
84 | if (dgrams_sent_>=10)
85 | return SwitchSendControl(KEEP_ALIVE_CONTROL);
86 | if (ack_rcvd_recent_)
87 | return SwitchSendControl(SLOW_START_CONTROL);
88 | if (data_in_.time!=TINT_NEVER)
89 | return NOW;
90 | if (last_recv_time_>last_send_time_)
91 | return NOW;
92 | if (!last_send_time_)
93 | return NOW;
94 | return last_send_time_ + ack_timeout(); // timeout
95 | }
96 |
97 | tint Channel::CwndRateNextSendTime () {
98 | if (data_in_.time!=TINT_NEVER)
99 | return NOW; // TODO: delayed ACKs
100 | //if (last_recv_time_max(rtt_avg_,TINT_SEC)*4)
104 | return SwitchSendControl(KEEP_ALIVE_CONTROL);
105 | if (data_out_.size()1)
142 | cwnd_ += ack_rcvd_recent_/cwnd_;
143 | else
144 | cwnd_ *= 2;
145 | }
146 | ack_rcvd_recent_=0;
147 | return CwndRateNextSendTime();
148 | }
149 |
150 | tint Channel::LedbatNextSendTime () {
151 | tint owd_cur(TINT_NEVER), owd_min(TINT_NEVER);
152 | for(int i=0; i<4; i++) {
153 | if (owd_min>owd_min_bins_[i])
154 | owd_min = owd_min_bins_[i];
155 | if (owd_cur>owd_current_[i])
156 | owd_cur = owd_current_[i];
157 | }
158 | if (ack_not_rcvd_recent_)
159 | BackOffOnLosses(0.8);
160 | ack_rcvd_recent_ = 0;
161 | tint queueing_delay = owd_cur - owd_min;
162 | tint off_target = LEDBAT_TARGET - queueing_delay;
163 | cwnd_ += LEDBAT_GAIN * off_target / cwnd_;
164 | if (cwnd_<1)
165 | cwnd_ = 1;
166 | if (owd_cur==TINT_NEVER || owd_min==TINT_NEVER)
167 | cwnd_ = 1;
168 | dprintf("%s #%u sendctrl ledbat %lli-%lli => %3.2f\n",
169 | tintstr(),id_,owd_cur,owd_min,cwnd_);
170 | return CwndRateNextSendTime();
171 | }
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/sha1.cpp:
--------------------------------------------------------------------------------
1 | // licensed under the GPL v2 as part of the git project http://git-scm.com/
2 | /*
3 | * SHA1 routine optimized to do word accesses rather than byte accesses,
4 | * and to avoid unnecessary copies into the context array.
5 | *
6 | * This was initially based on the Mozilla SHA1 implementation, although
7 | * none of the original Mozilla code remains.
8 | */
9 |
10 | /* this is only to get definitions for memcpy(), ntohl() and htonl() */
11 | //#include "../git-compat-util.h"
12 | #ifdef _WIN32
13 | #include
14 | #else
15 | #include
16 | #endif
17 | #include
18 |
19 | #include "sha1.h"
20 |
21 | #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
22 |
23 | /*
24 | * Force usage of rol or ror by selecting the one with the smaller constant.
25 | * It _can_ generate slightly smaller code (a constant of 1 is special), but
26 | * perhaps more importantly it's possibly faster on any uarch that does a
27 | * rotate with a loop.
28 | */
29 |
30 | #define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
31 | #define SHA_ROL(x,n) SHA_ASM("rol", x, n)
32 | #define SHA_ROR(x,n) SHA_ASM("ror", x, n)
33 |
34 | #else
35 |
36 | #define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
37 | #define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
38 | #define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
39 |
40 | #endif
41 |
42 | /*
43 | * If you have 32 registers or more, the compiler can (and should)
44 | * try to change the array[] accesses into registers. However, on
45 | * machines with less than ~25 registers, that won't really work,
46 | * and at least gcc will make an unholy mess of it.
47 | *
48 | * So to avoid that mess which just slows things down, we force
49 | * the stores to memory to actually happen (we might be better off
50 | * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
51 | * suggested by Artur Skawina - that will also make gcc unable to
52 | * try to do the silly "optimize away loads" part because it won't
53 | * see what the value will be).
54 | *
55 | * Ben Herrenschmidt reports that on PPC, the C version comes close
56 | * to the optimized asm with this (ie on PPC you don't want that
57 | * 'volatile', since there are lots of registers).
58 | *
59 | * On ARM we get the best code generation by forcing a full memory barrier
60 | * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
61 | * the stack frame size simply explode and performance goes down the drain.
62 | */
63 |
64 | #if defined(__i386__) || defined(__x86_64__)
65 | #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
66 | #elif defined(__GNUC__) && defined(__arm__)
67 | #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
68 | #else
69 | #define setW(x, val) (W(x) = (val))
70 | #endif
71 |
72 | /*
73 | * Performance might be improved if the CPU architecture is OK with
74 | * unaligned 32-bit loads and a fast ntohl() is available.
75 | * Otherwise fall back to byte loads and shifts which is portable,
76 | * and is faster on architectures with memory alignment issues.
77 | */
78 |
79 | #if defined(__i386__) || defined(__x86_64__) || \
80 | defined(__ppc__) || defined(__ppc64__) || \
81 | defined(__powerpc__) || defined(__powerpc64__) || \
82 | defined(__s390__) || defined(__s390x__)
83 |
84 | #define get_be32(p) ntohl(*(unsigned int *)(p))
85 | #define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
86 |
87 | #else
88 |
89 | #define get_be32(p) ( \
90 | (*((unsigned char *)(p) + 0) << 24) | \
91 | (*((unsigned char *)(p) + 1) << 16) | \
92 | (*((unsigned char *)(p) + 2) << 8) | \
93 | (*((unsigned char *)(p) + 3) << 0) )
94 | #define put_be32(p, v) do { \
95 | unsigned int __v = (v); \
96 | *((unsigned char *)(p) + 0) = __v >> 24; \
97 | *((unsigned char *)(p) + 1) = __v >> 16; \
98 | *((unsigned char *)(p) + 2) = __v >> 8; \
99 | *((unsigned char *)(p) + 3) = __v >> 0; } while (0)
100 |
101 | #endif
102 |
103 | /* This "rolls" over the 512-bit array */
104 | #define W(x) (array[(x)&15])
105 |
106 | /*
107 | * Where do we get the source from? The first 16 iterations get it from
108 | * the input data, the next mix it from the 512-bit array.
109 | */
110 | #define SHA_SRC(t) get_be32(data + t)
111 | #define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
112 |
113 | #define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
114 | unsigned int TEMP = input(t); setW(t, TEMP); \
115 | E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
116 | B = SHA_ROR(B, 2); } while (0)
117 |
118 | #define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
119 | #define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
120 | #define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
121 | #define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
122 | #define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E )
123 |
124 | static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data)
125 | {
126 | unsigned int A,B,C,D,E;
127 | unsigned int array[16];
128 |
129 | A = ctx->H[0];
130 | B = ctx->H[1];
131 | C = ctx->H[2];
132 | D = ctx->H[3];
133 | E = ctx->H[4];
134 |
135 | /* Round 1 - iterations 0-16 take their input from 'data' */
136 | T_0_15( 0, A, B, C, D, E);
137 | T_0_15( 1, E, A, B, C, D);
138 | T_0_15( 2, D, E, A, B, C);
139 | T_0_15( 3, C, D, E, A, B);
140 | T_0_15( 4, B, C, D, E, A);
141 | T_0_15( 5, A, B, C, D, E);
142 | T_0_15( 6, E, A, B, C, D);
143 | T_0_15( 7, D, E, A, B, C);
144 | T_0_15( 8, C, D, E, A, B);
145 | T_0_15( 9, B, C, D, E, A);
146 | T_0_15(10, A, B, C, D, E);
147 | T_0_15(11, E, A, B, C, D);
148 | T_0_15(12, D, E, A, B, C);
149 | T_0_15(13, C, D, E, A, B);
150 | T_0_15(14, B, C, D, E, A);
151 | T_0_15(15, A, B, C, D, E);
152 |
153 | /* Round 1 - tail. Input from 512-bit mixing array */
154 | T_16_19(16, E, A, B, C, D);
155 | T_16_19(17, D, E, A, B, C);
156 | T_16_19(18, C, D, E, A, B);
157 | T_16_19(19, B, C, D, E, A);
158 |
159 | /* Round 2 */
160 | T_20_39(20, A, B, C, D, E);
161 | T_20_39(21, E, A, B, C, D);
162 | T_20_39(22, D, E, A, B, C);
163 | T_20_39(23, C, D, E, A, B);
164 | T_20_39(24, B, C, D, E, A);
165 | T_20_39(25, A, B, C, D, E);
166 | T_20_39(26, E, A, B, C, D);
167 | T_20_39(27, D, E, A, B, C);
168 | T_20_39(28, C, D, E, A, B);
169 | T_20_39(29, B, C, D, E, A);
170 | T_20_39(30, A, B, C, D, E);
171 | T_20_39(31, E, A, B, C, D);
172 | T_20_39(32, D, E, A, B, C);
173 | T_20_39(33, C, D, E, A, B);
174 | T_20_39(34, B, C, D, E, A);
175 | T_20_39(35, A, B, C, D, E);
176 | T_20_39(36, E, A, B, C, D);
177 | T_20_39(37, D, E, A, B, C);
178 | T_20_39(38, C, D, E, A, B);
179 | T_20_39(39, B, C, D, E, A);
180 |
181 | /* Round 3 */
182 | T_40_59(40, A, B, C, D, E);
183 | T_40_59(41, E, A, B, C, D);
184 | T_40_59(42, D, E, A, B, C);
185 | T_40_59(43, C, D, E, A, B);
186 | T_40_59(44, B, C, D, E, A);
187 | T_40_59(45, A, B, C, D, E);
188 | T_40_59(46, E, A, B, C, D);
189 | T_40_59(47, D, E, A, B, C);
190 | T_40_59(48, C, D, E, A, B);
191 | T_40_59(49, B, C, D, E, A);
192 | T_40_59(50, A, B, C, D, E);
193 | T_40_59(51, E, A, B, C, D);
194 | T_40_59(52, D, E, A, B, C);
195 | T_40_59(53, C, D, E, A, B);
196 | T_40_59(54, B, C, D, E, A);
197 | T_40_59(55, A, B, C, D, E);
198 | T_40_59(56, E, A, B, C, D);
199 | T_40_59(57, D, E, A, B, C);
200 | T_40_59(58, C, D, E, A, B);
201 | T_40_59(59, B, C, D, E, A);
202 |
203 | /* Round 4 */
204 | T_60_79(60, A, B, C, D, E);
205 | T_60_79(61, E, A, B, C, D);
206 | T_60_79(62, D, E, A, B, C);
207 | T_60_79(63, C, D, E, A, B);
208 | T_60_79(64, B, C, D, E, A);
209 | T_60_79(65, A, B, C, D, E);
210 | T_60_79(66, E, A, B, C, D);
211 | T_60_79(67, D, E, A, B, C);
212 | T_60_79(68, C, D, E, A, B);
213 | T_60_79(69, B, C, D, E, A);
214 | T_60_79(70, A, B, C, D, E);
215 | T_60_79(71, E, A, B, C, D);
216 | T_60_79(72, D, E, A, B, C);
217 | T_60_79(73, C, D, E, A, B);
218 | T_60_79(74, B, C, D, E, A);
219 | T_60_79(75, A, B, C, D, E);
220 | T_60_79(76, E, A, B, C, D);
221 | T_60_79(77, D, E, A, B, C);
222 | T_60_79(78, C, D, E, A, B);
223 | T_60_79(79, B, C, D, E, A);
224 |
225 | ctx->H[0] += A;
226 | ctx->H[1] += B;
227 | ctx->H[2] += C;
228 | ctx->H[3] += D;
229 | ctx->H[4] += E;
230 | }
231 |
232 | void blk_SHA1_Init(blk_SHA_CTX *ctx)
233 | {
234 | ctx->size = 0;
235 |
236 | /* Initialize H with the magic constants (see FIPS180 for constants) */
237 | ctx->H[0] = 0x67452301;
238 | ctx->H[1] = 0xefcdab89;
239 | ctx->H[2] = 0x98badcfe;
240 | ctx->H[3] = 0x10325476;
241 | ctx->H[4] = 0xc3d2e1f0;
242 | }
243 |
244 | void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
245 | {
246 | int lenW = ctx->size & 63;
247 |
248 | ctx->size += len;
249 |
250 | /* Read the data into W and process blocks as they get full */
251 | if (lenW) {
252 | int left = 64 - lenW;
253 | if (len < left)
254 | left = len;
255 | memcpy(lenW + (char *)ctx->W, data, left);
256 | lenW = (lenW + left) & 63;
257 | len -= left;
258 | data = ((const char *)data + left);
259 | if (lenW)
260 | return;
261 | blk_SHA1_Block(ctx, ctx->W);
262 | }
263 | while (len >= 64) {
264 | blk_SHA1_Block(ctx, (const unsigned int*)data);
265 | data = ((const char *)data + 64);
266 | len -= 64;
267 | }
268 | if (len)
269 | memcpy(ctx->W, data, len);
270 | }
271 |
272 | void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx)
273 | {
274 | static const unsigned char pad[64] = { 0x80 };
275 | unsigned int padlen[2];
276 | int i;
277 |
278 | /* Pad with a binary 1 (ie 0x80), then zeroes, then length */
279 | padlen[0] = htonl(ctx->size >> 29);
280 | padlen[1] = htonl(ctx->size << 3);
281 |
282 | i = ctx->size & 63;
283 | blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
284 | blk_SHA1_Update(ctx, padlen, 8);
285 |
286 | /* Output hash */
287 | for (i = 0; i < 5; i++)
288 | put_be32(hashout + i*4, ctx->H[i]);
289 | }
290 |
--------------------------------------------------------------------------------
/sha1.h:
--------------------------------------------------------------------------------
1 | // licensed under the GPL v2 as part of the git project http://git-scm.com/
2 | /*
3 | * SHA1 routine optimized to do word accesses rather than byte accesses,
4 | * and to avoid unnecessary copies into the context array.
5 | *
6 | * This was initially based on the Mozilla SHA1 implementation, although
7 | * none of the original Mozilla code remains.
8 | */
9 | #ifndef GIT_SHA1
10 | #define GIT_SHA1
11 |
12 | typedef struct {
13 | unsigned long long size;
14 | unsigned int H[5];
15 | unsigned int W[16];
16 | } blk_SHA_CTX;
17 |
18 | void blk_SHA1_Init(blk_SHA_CTX *ctx);
19 | void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
20 | void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
21 |
22 | #endif
23 |
24 |
--------------------------------------------------------------------------------
/swift.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * swift.cpp
3 | * swift the multiparty transport protocol
4 | *
5 | * Created by Victor Grishchenko on 2/15/10.
6 | * Copyright 2010 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | #include
11 | #include "compat.h"
12 | #include "swift.h"
13 |
14 | using namespace swift;
15 |
16 | #define quit(...) {fprintf(stderr,__VA_ARGS__); exit(1); }
17 | SOCKET InstallHTTPGateway (Address addr);
18 |
19 |
20 | int main (int argc, char** argv) {
21 |
22 | static struct option long_options[] =
23 | {
24 | {"hash", required_argument, 0, 'h'},
25 | {"file", required_argument, 0, 'f'},
26 | {"daemon", no_argument, 0, 'd'},
27 | {"listen", required_argument, 0, 'l'},
28 | {"tracker", required_argument, 0, 't'},
29 | {"debug", no_argument, 0, 'D'},
30 | {"progress",no_argument, 0, 'p'},
31 | {"http", optional_argument, 0, 'g'},
32 | {"wait", optional_argument, 0, 'w'},
33 | {0, 0, 0, 0}
34 | };
35 |
36 | Sha1Hash root_hash;
37 | char* filename = 0;
38 | bool daemonize = false, report_progress = false;
39 | Address bindaddr;
40 | Address tracker;
41 | Address http_gw;
42 | tint wait_time = 0;
43 |
44 | LibraryInit();
45 |
46 | int c;
47 | while ( -1 != (c = getopt_long (argc, argv, ":h:f:dl:t:Dpg::w::", long_options, 0)) ) {
48 |
49 | switch (c) {
50 | case 'h':
51 | if (strlen(optarg)!=40)
52 | quit("SHA1 hash must be 40 hex symbols\n");
53 | root_hash = Sha1Hash(true,optarg); // FIXME ambiguity
54 | if (root_hash==Sha1Hash::ZERO)
55 | quit("SHA1 hash must be 40 hex symbols\n");
56 | break;
57 | case 'f':
58 | filename = strdup(optarg);
59 | break;
60 | case 'd':
61 | daemonize = true;
62 | break;
63 | case 'l':
64 | bindaddr = Address(optarg);
65 | if (bindaddr==Address())
66 | quit("address must be hostname:port, ip:port or just port\n");
67 | wait_time = TINT_NEVER;
68 | break;
69 | case 't':
70 | tracker = Address(optarg);
71 | if (tracker==Address())
72 | quit("address must be hostname:port, ip:port or just port\n");
73 | SetTracker(tracker);
74 | break;
75 | case 'D':
76 | Channel::debug_file = optarg ? fopen(optarg,"a") : stdout;
77 | break;
78 | case 'p':
79 | report_progress = true;
80 | break;
81 | case 'g':
82 | http_gw = optarg ? Address(optarg) : Address(Address::LOCALHOST,8080);
83 | if (wait_time==-1)
84 | wait_time = TINT_NEVER; // seed
85 | break;
86 | case 'w':
87 | if (optarg) {
88 | char unit = 'u';
89 | if (sscanf(optarg,"%lli%c",&wait_time,&unit)!=2)
90 | quit("time format: 1234[umsMHD], e.g. 1M = one minute\n");
91 | switch (unit) {
92 | case 'D': wait_time *= 24;
93 | case 'H': wait_time *= 60;
94 | case 'M': wait_time *= 60;
95 | case 's': wait_time *= 1000;
96 | case 'm': wait_time *= 1000;
97 | case 'u': break;
98 | default: quit("time format: 1234[umsMHD], e.g. 1D = one day\n");
99 | }
100 | } else
101 | wait_time = TINT_NEVER;
102 | break;
103 | }
104 |
105 | } // arguments parsed
106 |
107 |
108 | if (bindaddr!=Address()) { // seeding
109 | if (Listen(bindaddr)<=0)
110 | quit("cant listen to %s\n",bindaddr.str())
111 | } else if (tracker!=Address() || http_gw!=Address()) { // leeching
112 | for (int i=0; i<=10; i++) {
113 | bindaddr = Address((uint32_t)INADDR_ANY,0);
114 | if (Listen(bindaddr)>0)
115 | break;
116 | if (i==10)
117 | quit("cant listen on %s\n",bindaddr.str());
118 | }
119 | }
120 |
121 | if (tracker!=Address())
122 | SetTracker(tracker);
123 |
124 | if (http_gw!=Address())
125 | InstallHTTPGateway(http_gw);
126 |
127 | if (root_hash!=Sha1Hash::ZERO && !filename)
128 | filename = strdup(root_hash.hex().c_str());
129 |
130 | int file = -1;
131 | if (filename) {
132 | file = Open(filename,root_hash);
133 | if (file<=0)
134 | quit("cannot open file %s",filename);
135 | printf("Root hash: %s\n", RootMerkleHash(file).hex().c_str());
136 | }
137 |
138 | if (bindaddr==Address() && file==-1 && http_gw==Address()) {
139 | fprintf(stderr,"Usage:\n");
140 | fprintf(stderr," -h, --hash\troot Merkle hash for the transmission\n");
141 | fprintf(stderr," -f, --file\tname of file to use (root hash by default)\n");
142 | fprintf(stderr," -l, --listen\t[ip:|host:]port to listen to (default: random)\n");
143 | fprintf(stderr," -t, --tracker\t[ip:|host:]port of the tracker (default: none)\n");
144 | fprintf(stderr," -D, --debug\tfile name for debugging logs (default: stdout)\n");
145 | fprintf(stderr," -p, --progress\treport transfer progress\n");
146 | fprintf(stderr," -g, --http\t[ip:|host:]port to bind HTTP gateway to (default localhost:8080)\n");
147 | fprintf(stderr," -w, --wait\tlimit running time, e.g. 1[DHMs] (default: infinite with -l, -g)\n");
148 | return 1;
149 | }
150 |
151 | tint start_time = NOW;
152 |
153 | while ( (file>=0 && !IsComplete(file)) ||
154 | (start_time+wait_time>NOW) ) {
155 | swift::Loop(TINT_SEC);
156 | if (report_progress && file>=0) {
157 | fprintf(stderr,
158 | "%s %lli of %lli (seq %lli) %lli dgram %lli bytes up, "\
159 | "%lli dgram %lli bytes down\n",
160 | IsComplete(file) ? "DONE" : "done",
161 | Complete(file), Size(file), SeqComplete(file),
162 | Datagram::dgrams_up, Datagram::bytes_up,
163 | Datagram::dgrams_down, Datagram::bytes_down );
164 | }
165 | }
166 |
167 | if (file!=-1)
168 | Close(file);
169 |
170 | if (Channel::debug_file)
171 | fclose(Channel::debug_file);
172 |
173 | swift::Shutdown();
174 |
175 | return 0;
176 |
177 | }
178 |
179 |
--------------------------------------------------------------------------------
/tests/SConscript:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | Import("DEBUG")
4 | Import("env")
5 | Import("libs")
6 | Import("libpath")
7 |
8 | cpppath = env["CPPPATH"]
9 | if DEBUG and sys.platform == "win32":
10 | libs = ['swift','gtestd'] + libs # order is important, crypto needs to be last
11 | else:
12 | libs = ['swift','gtest'] + libs # order is important, crypto needs to be last
13 |
14 | if sys.platform == "win32":
15 | cpppath = ".."
16 | libpath += '..;'
17 | if DEBUG:
18 | env.Append(CXXFLAGS="/Zi /Yd /MTd")
19 | else:
20 | cpppath = cpppath + ':..'
21 | libpath += ':..'
22 | if DEBUG:
23 | env.Append(CXXFLAGS="-g")
24 |
25 | print "tests: libpath is",libpath
26 |
27 | env.Program(
28 | target='binstest2',
29 | source=['binstest2.cpp'],
30 | CPPPATH=cpppath,
31 | LIBS=libs,
32 | LIBPATH=libpath )
33 |
34 | env.Program(
35 | target='dgramtest',
36 | source=['dgramtest.cpp'],
37 | CPPPATH=cpppath,
38 | LIBS=libs,
39 | LIBPATH=libpath )
40 |
41 | env.Program(
42 | target='hashtest',
43 | source=['hashtest.cpp'],
44 | CPPPATH=cpppath,
45 | LIBS=libs,
46 | LIBPATH=libpath )
47 |
48 | #env.Program(
49 | # target='ledbattest',
50 | # source=['ledbattest.cpp'],
51 | # CPPPATH=cpppath,
52 | # LIBS=libs,
53 | # LIBPATH=libpath )
54 |
55 |
56 | #if sys.platform != "win32":
57 | # # Arno: Needs getopt
58 | # env.Program(
59 | # target='ledbattest2',
60 | # source=['ledbattest2.cpp'],
61 | # CPPPATH=cpppath,
62 | # LIBS=libs,
63 | # LIBPATH=libpath )
64 |
65 | env.Program(
66 | target='freemap',
67 | source=['freemap.cpp'],
68 | CPPPATH=cpppath,
69 | LIBS=libs,
70 | LIBPATH=libpath )
71 |
72 | env.Program(
73 | target='bin64test',
74 | source=['bin64test.cpp'],
75 | CPPPATH=cpppath,
76 | LIBS=libs,
77 | LIBPATH=libpath )
78 |
79 | env.Program(
80 | target='transfertest',
81 | source=['transfertest.cpp'],
82 | CPPPATH=cpppath,
83 | LIBS=libs,
84 | LIBPATH=libpath )
85 |
86 | env.Program(
87 | target='connecttest',
88 | source=['connecttest.cpp'],
89 | CPPPATH=cpppath,
90 | LIBS=libs,
91 | LIBPATH=libpath )
92 |
93 |
--------------------------------------------------------------------------------
/tests/bin64test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * bintest.cpp
3 | * bin++
4 | *
5 | * Created by Victor Grishchenko on 3/9/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include "bin64.h"
10 | #include
11 |
12 | TEST(Bin64Test,InitGet) {
13 |
14 | EXPECT_EQ(0x1,bin64_t(1,0));
15 | EXPECT_EQ(0xB,bin64_t(2,1));
16 | EXPECT_EQ(0x2,bin64_t(2,1).layer());
17 | EXPECT_EQ(34,bin64_t(34,2345).layer());
18 | EXPECT_EQ(0x7ffffffffULL,bin64_t(34,2345).tail_bits());
19 | EXPECT_EQ(1,bin64_t(2,1).offset());
20 | EXPECT_EQ(2345,bin64_t(34,2345).offset());
21 | EXPECT_EQ(1,bin64_t(0,123).tail_bit());
22 | EXPECT_EQ(1<<16,bin64_t(16,123).tail_bit());
23 |
24 | }
25 |
26 | TEST(Bin64Test,Navigation) {
27 |
28 | bin64_t mid(4,18);
29 | EXPECT_EQ(bin64_t(5,9),mid.parent());
30 | EXPECT_EQ(bin64_t(3,36),mid.left());
31 | EXPECT_EQ(bin64_t(3,37),mid.right());
32 | EXPECT_EQ(bin64_t(5,9),bin64_t(4,19).parent());
33 | bin64_t up32(30,1);
34 | EXPECT_EQ(bin64_t(31,0),up32.parent());
35 |
36 | }
37 |
38 | TEST(Bin64Test,Overflows) {
39 |
40 | EXPECT_FALSE(bin64_t(0,1).within(bin64_t::NONE));
41 | EXPECT_TRUE(bin64_t(0,1).within(bin64_t::ALL));
42 | EXPECT_EQ(0,bin64_t::none().width());
43 | EXPECT_EQ(bin64_t::none(),bin64_t::none().twisted(123));
44 | /*EXPECT_EQ(bin64_t::NONE.parent(),bin64_t::NONE);
45 | EXPECT_EQ(bin64_t::NONE.left(),bin64_t::NONE);
46 | EXPECT_EQ(bin64_t::NONE.right(),bin64_t::NONE);
47 | EXPECT_EQ(bin64_t::NONE,bin64_t(0,2345).left());
48 | EXPECT_EQ(bin64_t::NONE,bin64_t::ALL.parent());
49 | */
50 | }
51 |
52 | TEST(Bin64Test, Advanced) {
53 |
54 | EXPECT_EQ(4,bin64_t(2,3).width());
55 | EXPECT_FALSE(bin64_t(1,1234).is_base());
56 | EXPECT_TRUE(bin64_t(0,12345).is_base());
57 | EXPECT_EQ(bin64_t(0,2),bin64_t(1,1).left_foot());
58 | bin64_t peaks[64];
59 | int peak_count = bin64_t::peaks(7,peaks);
60 | EXPECT_EQ(3,peak_count);
61 | EXPECT_EQ(bin64_t(2,0),peaks[0]);
62 | EXPECT_EQ(bin64_t(1,2),peaks[1]);
63 | EXPECT_EQ(bin64_t(0,6),peaks[2]);
64 |
65 | }
66 |
67 | TEST(Bin64Test, Iteration) {
68 | bin64_t i(1,0);
69 | i = i.next_dfsio(1);
70 | EXPECT_EQ(bin64_t(1,1),i);
71 | i = i.next_dfsio(1);
72 | EXPECT_EQ(bin64_t(2,0),i);
73 | i = i.next_dfsio(1);
74 | EXPECT_EQ(bin64_t(1,2),i);
75 | i = i.next_dfsio(1);
76 | EXPECT_EQ(bin64_t(1,3),i);
77 | i = i.next_dfsio(1);
78 | EXPECT_EQ(bin64_t(2,1),i);
79 | i = i.next_dfsio(1);
80 | EXPECT_EQ(bin64_t(3,0),i);
81 | }
82 |
83 | TEST(Bin64Test, Bits) {
84 | bin64_t all = bin64_t::ALL, none = bin64_t::NONE, big = bin64_t(40,18);
85 | uint32_t a32 = all.to32(), n32 = none.to32(), b32 = big.to32();
86 | EXPECT_EQ(0x7fffffff,a32);
87 | EXPECT_EQ(0xffffffff,n32);
88 | EXPECT_EQ(bin64_t::NONE32,b32);
89 | }
90 |
91 | int main (int argc, char** argv) {
92 |
93 | testing::InitGoogleTest(&argc, argv);
94 | return RUN_ALL_TESTS();
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/tests/binstest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * binstest.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 3/22/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | #include
11 | #include
12 | #include "bin.h"
13 | #include "sbit.h"
14 |
15 | TEST(BinsTest,AddSub) {
16 | bins b;
17 | b|=15;
18 | b-=1;
19 | ASSERT_TRUE(b.contains(2));
20 | ASSERT_TRUE(b.contains(14));
21 | ASSERT_FALSE(b.contains(3));
22 | ASSERT_FALSE(b.contains(22));
23 | ASSERT_TRUE(b.contains(12));
24 | b-=13;
25 | ASSERT_FALSE(b.contains(12));
26 | ASSERT_FALSE(b.contains(14));
27 | ASSERT_FALSE(b.contains(11));
28 | ASSERT_TRUE(b.contains(10));
29 | }
30 |
31 |
32 | TEST(BinsTest,Peaks) {
33 | bin::vec peaks = bin::peaks(11);
34 | ASSERT_EQ(3,peaks.size());
35 | ASSERT_EQ(15,peaks[0]);
36 | ASSERT_EQ(18,peaks[1]);
37 | ASSERT_EQ(19,peaks[2]);
38 | }
39 |
40 | TEST(BinsTest,Performance) {
41 | bins b;
42 | std::set s;
43 | clock_t start, end;
44 | double b_time, s_time;
45 | int b_size, s_size;
46 |
47 | start = clock();
48 | for(int i=1; i<(1<<20); i++)
49 | b |= bin(i);
50 | //b_size = b.bits.size();
51 | end = clock();
52 | b_time = ((double) (end - start)) / CLOCKS_PER_SEC;
53 | //ASSERT_EQ(1,b.bits.size());
54 |
55 | start = clock();
56 | for(int i=1; i<(1<<20); i++)
57 | s.insert(i);
58 | s_size = s.size();
59 | end = clock();
60 | s_time = ((double) (end - start)) / CLOCKS_PER_SEC;
61 |
62 | printf("bins: %f (%i), set: %f (%i)\n",b_time,b_size,s_time,s_size);
63 | }
64 |
65 | int main (int argc, char** argv) {
66 | bin::init();
67 | testing::InitGoogleTest(&argc, argv);
68 | return RUN_ALL_TESTS();
69 | }
70 |
--------------------------------------------------------------------------------
/tests/bintest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * bintest.cpp
3 | * bin++
4 | *
5 | * Created by Victor Grishchenko on 3/9/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include "bin.h"
10 | #include
11 |
12 | TEST(BinTest,Mass) {
13 | EXPECT_EQ(bin(4).length(),3);
14 | EXPECT_EQ(bin(9).length(),6);
15 | EXPECT_EQ(bin(3).mass(),3);
16 | EXPECT_EQ(bin(5).mass(),1);
17 | EXPECT_EQ(bin(6).mass(),3);
18 | EXPECT_EQ(bin(10).mass(),3);
19 | EXPECT_TRUE(bin::all1(1));
20 | EXPECT_TRUE(bin::all1(7));
21 | }
22 |
23 | TEST(BinTest,Instantiation) {
24 | EXPECT_EQ(bin(0,1),2)<<"bin_new @0";
25 | EXPECT_EQ(bin(2,0),7)<<"bin_new @2";
26 | EXPECT_EQ(bin(1,2),10)<<"bin_new @1";
27 | EXPECT_EQ(12,bin(0,7))<<"bin(0,7)";
28 | EXPECT_EQ(9,bin::tailzeros(512));
29 | EXPECT_EQ(0,bin::tailzeros(1));
30 | EXPECT_EQ(5,bin::tailzeros(32+128));
31 | }
32 |
33 | TEST(BinTest,Traversing) {
34 | EXPECT_EQ(6,bin(4).parent());
35 | EXPECT_EQ(bin(30).parent(),31);
36 | EXPECT_EQ(bin(7).parent(),15);
37 | EXPECT_EQ(bin(18).parent(),22);
38 | EXPECT_EQ(bin(30).left(),22);
39 | EXPECT_EQ(bin(14).left(),10);
40 | EXPECT_EQ(bin(22).left(),18);
41 | EXPECT_EQ(bin(30).right(),29);
42 | EXPECT_EQ(bin(14).right(),13);
43 | EXPECT_EQ(bin(22).right(),21);
44 | EXPECT_EQ(bin(15).left_foot(),1)<<"15 left foot";
45 | EXPECT_EQ(bin(15).right_foot(),12)<<"15 right foot";
46 | EXPECT_EQ(bin(22).left_foot(),16)<<"22 left foot";
47 | EXPECT_EQ(bin(22).right_foot(),20)<<"22 right foot";
48 | }
49 |
50 | TEST(BinTest,Advanced) {
51 | EXPECT_EQ(0,bin(1).layer());
52 |
53 | EXPECT_TRUE(bin(31).contains(14));
54 | EXPECT_FALSE(bin(22).contains(14));
55 | EXPECT_TRUE(bin(7).contains(7));
56 | EXPECT_TRUE(bin(11).contains(11));
57 | EXPECT_TRUE(bin(22).contains(20));
58 |
59 | EXPECT_EQ(6,bin(5).commonParent(4)) << "common parent trivial";
60 | EXPECT_EQ(7,bin(2).commonParent(4)) << "common parent trivial";
61 | EXPECT_EQ(14,bin(8).commonParent(11)) << "common parent trick";
62 | EXPECT_EQ(31,bin(14).commonParent(16)) << "common parent complex";
63 | EXPECT_EQ(31,bin(8).commonParent(16)) << "common parent trick 2";
64 | EXPECT_EQ(31,bin(31).commonParent(1)) << "common parent trick 2";
65 | EXPECT_EQ(22,bin(22).commonParent(19)) << "common parent nested";
66 | EXPECT_EQ(22,bin(19).commonParent(22)) << "common parent nested rev";
67 | EXPECT_EQ(63,bin(32).commonParent(12)) << "common parent nested rev";
68 | EXPECT_EQ(31,bin(14).commonParent(18)) << "common parent nested rev";
69 | EXPECT_EQ(12,bin(12).commonParent(12)) << "common parent nested rev";
70 | for(bin i=1; i<=127; i++)
71 | for(bin j=1; j<=127; j++) if (i!=j) {
72 | bin c = i.commonParent(j);
73 | EXPECT_TRUE(c.contains(i));
74 | EXPECT_TRUE(c.contains(j));
75 | bin l=c.left(), r=c.right();
76 | //printf("%i %i => %i (%i,%i)\n",(int)i,(int)j,(int)c,(int)l,(int)r);
77 | EXPECT_FALSE(l.contains(i)&&l.contains(j));
78 | EXPECT_FALSE(r.contains(i)&&r.contains(j));
79 | }
80 | EXPECT_EQ(22,bin(16).parent(2)) << "parent 2";
81 | EXPECT_EQ(31,bin(9).parent(4)) << "parent-snake";
82 | }
83 |
84 | TEST(BinTest,Overflows) {
85 | // TODO
86 | //EXPECT_EQ( 1<<31, bin::ALL.length() );
87 | }
88 |
89 | TEST(BinTest,Division) {
90 | EXPECT_EQ(bin(14).modulo(3),14);
91 | EXPECT_EQ(bin(22).modulo(3),7);
92 | EXPECT_EQ(bin(21).modulo(1),3);
93 | EXPECT_EQ(bin(31).modulo(3),15);
94 | EXPECT_EQ(bin(31).modulo(4),31);
95 | EXPECT_EQ(bin(22).divide(2),4);
96 | EXPECT_EQ(bin(30).divide(2),6);
97 | EXPECT_EQ(bin(31).divide(3),3);
98 | EXPECT_EQ(bin(14).multiply(1),30);
99 | EXPECT_EQ(bin(6).multiply(2),30);
100 | }
101 |
102 | TEST(BinTest, Scope) {
103 | EXPECT_EQ(1,bin(32).scoped(bin(62),4));
104 | EXPECT_EQ(14,bin(29).scoped(bin(30),3));
105 | EXPECT_EQ(15,bin(30).scoped(bin(30),3));
106 | EXPECT_EQ(5,bin(11).scoped(bin(31),3));
107 | EXPECT_EQ(4,bin(22).scoped(bin(31),2));
108 |
109 | EXPECT_EQ(14,bin(2).unscoped(bin(15),1));
110 | EXPECT_EQ(22,bin(4).unscoped(bin(31),2));
111 | }
112 |
113 | TEST(BinTest, Order) {
114 | bin::vec v;
115 | v.push_back(22);
116 | v.push_back(17);
117 | v.push_back(19);
118 | v.push_back(6);
119 | v.push_back(3);
120 | v.push_back(14);
121 | bin::order(&v);
122 | ASSERT_EQ(2,v.size());
123 | EXPECT_EQ(v[1],15);
124 | EXPECT_EQ(v[0],22);
125 | }
126 |
127 | int main (int argc, char** argv) {
128 | bin::init();
129 |
130 | bin p(12234);
131 | printf("%i %i %i %i\n",(int)p,p.layer(),p.offset(),p.offset()<
10 | #include
11 | #include
12 | #include
13 | #include "p2tp.h"
14 |
15 | using namespace std;
16 | using namespace p2tp;
17 |
18 | class SimPeer;
19 |
20 | struct SimPacket {
21 | SimPacket(int from, int to, const SimPacket* toack, bool data) ;
22 | int peerfrom, peerto;
23 | tint datatime;
24 | tint acktime;
25 | tint arrivaltime;
26 | };
27 |
28 | tint now = 0;
29 |
30 | /** very simplified; uplink is the bottleneck */
31 | class SimPeer {
32 | public:
33 | SimPeer (tint tt, tint lt, int qlen) : travtime(tt), latency(lt), queue_length(qlen) {}
34 | int queue_length;
35 | int travtime;
36 | tint freetime;
37 | tint latency;
38 | int unackd;
39 | int rcvd, sent;
40 | queue packet_queue;
41 | queue dropped_queue;
42 | CongestionControl congc;
43 |
44 | void send(SimPacket pck) {
45 | if (packet_queue.size()==queue_length) {
46 | dropped_queue.push(pck);
47 | return;
48 | }
49 | tint start = max(now,freetime);
50 | tint done = pck.datatime ? start+travtime : start;
51 | freetime = done;
52 | pck.arrivaltime = done + latency;
53 | packet_queue.push(pck);
54 | }
55 |
56 | SimPacket recv () {
57 | assert(!packet_queue.empty());
58 | SimPacket ret = packet_queue.front();
59 | packet_queue.pop();
60 | return ret;
61 | }
62 |
63 | tint next_recv_time () const {
64 | return packet_queue.empty() ? NEVER : packet_queue.front().arrivaltime;
65 | }
66 |
67 | void turn () {
68 | SimPacket rp = recv();
69 | SimPacket reply;
70 | now = rp.arrivaltime;
71 | if (rp.acktime) {
72 | congc.RttSample(rp.arrivaltime-rp.acktime);
73 | congc.OnCongestionEvent(CongestionControl::ACK_EV);
74 | unackd--;
75 | rcvd++;
76 | }
77 | if (rp.datatime) {
78 | congc.OnCongestionEvent(CongestionControl::DATA_EV);
79 | reply.acktime = reply.datatime;
80 | }
81 | if (!dropped_queue.empty() && dropped_queue.top().datatimeunackd) {
84 | unackd++;
85 | reply.datatime = now;
86 | sent++;
87 | }
88 | rp.from->send(reply);
89 | }
90 | };
91 |
92 | TEST(P2TP, TailDropTest) {
93 | // two peers exchange packets over 100ms link with tail-drop discipline
94 | // bw 1Mbits => travel time of 1KB is ~10ms
95 | SimPeer a(10*MSEC,100*MSEC,20), b(10*MSEC,100*MSEC,20);
96 | a.send(SimPacket(&b,now,0,0));
97 | while (now<60*60*SEC)
98 | if (a.next_recv_time()
11 | //#include
12 | #include "swift.h"
13 | #include
14 |
15 |
16 | using namespace swift;
17 |
18 |
19 | TEST(Connection,CwndTest) {
20 |
21 | srand ( time(NULL) );
22 |
23 | unlink("doc/sofi-copy.jpg");
24 | struct stat st;
25 | ASSERT_EQ(0,stat("doc/sofi.jpg", &st));
26 | int size = st.st_size;//, sizek = (st.st_size>>10) + (st.st_size%1024?1:0) ;
27 | Channel::SELF_CONN_OK = true;
28 |
29 | int sock1 = swift::Listen(7001);
30 | ASSERT_TRUE(sock1>=0);
31 |
32 | int file = swift::Open("doc/sofi.jpg");
33 | FileTransfer* fileobj = FileTransfer::file(file);
34 | //FileTransfer::instance++;
35 |
36 | swift::SetTracker(Address("127.0.0.1",7001));
37 |
38 | int copy = swift::Open("doc/sofi-copy.jpg",fileobj->root_hash());
39 |
40 | swift::Loop(TINT_SEC);
41 |
42 | int count = 0;
43 | while (swift::SeqComplete(copy)!=size && count++<600)
44 | swift::Loop(TINT_SEC);
45 | ASSERT_EQ(size,swift::SeqComplete(copy));
46 |
47 | swift::Close(file);
48 | swift::Close(copy);
49 |
50 | swift::Shutdown(sock1);
51 |
52 | }
53 |
54 |
55 | int main (int argc, char** argv) {
56 |
57 | swift::LibraryInit();
58 | testing::InitGoogleTest(&argc, argv);
59 | Channel::debug_file = stdout;
60 | int ret = RUN_ALL_TESTS();
61 | return ret;
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/tests/dgramtest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * dgramtest.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 3/13/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | //#include
11 | #include "datagram.h"
12 | #include "swift.h" // Arno: for LibraryInit
13 |
14 | using namespace swift;
15 |
16 | TEST(Datagram, AddressTest) {
17 | Address addr("127.0.0.1:1000");
18 | EXPECT_EQ(INADDR_LOOPBACK,addr.ipv4());
19 | EXPECT_EQ(1000,addr.port());
20 | Address das2("node300.das2.ewi.tudelft.nl:20000");
21 | Address das2b("130.161.211.200:20000");
22 | EXPECT_EQ(das2.ipv4(),das2b.ipv4());
23 | EXPECT_EQ(20000,das2.port());
24 | }
25 |
26 |
27 | TEST(Datagram, BinaryTest) {
28 | SOCKET socket = Datagram::Bind(7001);
29 | ASSERT_TRUE(socket>0);
30 | struct sockaddr_in addr;
31 | addr.sin_family = AF_INET;
32 | addr.sin_port = htons(7001);
33 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
34 | Datagram d(socket,addr); //Address(7001));
35 | const char * text = "text";
36 | const uint8_t num8 = 0xab;
37 | const uint16_t num16 = 0xabcd;
38 | const uint32_t num32 = 0xabcdef01;
39 | const uint64_t num64 = 0xabcdefabcdeffULL;
40 | d.PushString(text);
41 | d.Push8(num8);
42 | d.Push16(num16);
43 | d.Push32(num32);
44 | d.Push64(num64);
45 | char buf[1024];
46 | int i;
47 | for(i=0; i0);
79 | ASSERT_TRUE(sock2>0);
80 | /*struct sockaddr_in addr1, addr2;
81 | addr1.sin_family = AF_INET;
82 | addr1.sin_port = htons(10001);
83 | addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
84 | addr2.sin_family = AF_INET;
85 | addr2.sin_port = htons(10002);
86 | addr2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);*/
87 |
88 | Datagram send(sock1,Address("127.0.0.1:10002"));
89 | send.Push32(1234);
90 | send.Send();
91 |
92 | SOCKET socks[2] = {sock1,sock2};
93 | // Arno: timeout 0 gives undeterministic behaviour on win32
94 | //EXPECT_EQ(sock2,
95 | Datagram::Wait(1000000);
96 | //);
97 | Datagram recv(sock2);
98 | recv.Recv();
99 | uint32_t test = recv.Pull32();
100 | ASSERT_EQ(1234,test);
101 |
102 | Datagram::Close(sock1);
103 | Datagram::Close(sock2);
104 | }
105 |
106 | int main (int argc, char** argv) {
107 |
108 | swift::LibraryInit();
109 |
110 | testing::InitGoogleTest(&argc, argv);
111 | return RUN_ALL_TESTS();
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/tests/freemap.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * binstest.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 3/22/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | #include
11 | #include
12 | #include "bins.h"
13 |
14 | #ifdef _MSC_VER
15 | #define RANDOM rand
16 | #else
17 | #define RANDOM random
18 | #endif
19 |
20 | int bins_stripe_count (binmap_t& b) {
21 | int stripe_count;
22 | uint64_t * stripes = b.get_stripes(stripe_count);
23 | free(stripes);
24 | return stripe_count;
25 | }
26 |
27 | uint8_t rand_norm (uint8_t lim) {
28 | long rnd = RANDOM() & ((1<>= 1;
33 | }
34 | return bits;
35 | }
36 |
37 | TEST(FreemapTest,Freemap) {
38 | binmap_t space;
39 | const bin64_t top(30,0);
40 | space.set(top,binmap_t::EMPTY);
41 | typedef std::pair timebin_t;
42 | typedef std::set ts_t;
43 | ts_t to_free;
44 | for (int t=0; t<1000000; t++) {
45 | if (t<500000 || t>504000) {
46 | uint8_t lr = rand_norm(28);
47 | bin64_t alloc = space.find(top);
48 | while (alloc.layer()>lr)
49 | alloc = alloc.left();
50 | ASSERT_NE(0ULL,~alloc);
51 | EXPECT_EQ(binmap_t::EMPTY, space.get(alloc));
52 | space.set(alloc,binmap_t::FILLED);
53 | long dealloc_time = 1<first<=t) {
61 | bin64_t freebin = to_free.begin()->second;
62 | to_free.erase(to_free.begin());
63 | space.set(freebin,binmap_t::EMPTY);
64 | printf("freed at %lli\n",
65 | (uint64_t)freebin);
66 | }
67 | // log: space taken, gaps, binmap cells, tree cells
68 | int cells = space.size();
69 | int intervals = bins_stripe_count(space);
70 | printf("time %i cells used %i intervals %i blocks %i\n",
71 | t,cells,intervals,(int)to_free.size());
72 | //space.dump("space");
73 | }
74 | for(ts_t::iterator i=to_free.begin(); i!=to_free.end(); i++)
75 | space.set(i->second,binmap_t::EMPTY);
76 | EXPECT_EQ(binmap_t::EMPTY,space.get(top));
77 | }
78 |
79 | int main (int argc, char** argv) {
80 | testing::InitGoogleTest(&argc, argv);
81 | return RUN_ALL_TESTS();
82 | }
83 |
--------------------------------------------------------------------------------
/tests/hashtest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * hashtest.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 3/12/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | #include "bin64.h"
11 | #include
12 | #include "hashtree.h"
13 |
14 | using namespace swift;
15 |
16 | char hash123[] = "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0";
17 | char rooth123[] = "d0bdb8ba28076d84d2b3a0e62521b998e42349a1";
18 |
19 | TEST(Sha1HashTest,Trivial) {
20 | Sha1Hash hash("123\n");
21 | EXPECT_STREQ(hash123,hash.hex().c_str());
22 | }
23 |
24 |
25 | TEST(Sha1HashTest,OfferDataTest) {
26 | Sha1Hash roothash123(true,hash123);
27 | for(bin64_t pos(0,0); pos!=bin64_t::ALL; pos=pos.parent())
28 | roothash123 = Sha1Hash(roothash123,Sha1Hash::ZERO);
29 | unlink("123");
30 | EXPECT_STREQ(rooth123,roothash123.hex().c_str());
31 | HashTree tree("123",roothash123);
32 | tree.OfferHash(bin64_t(0,0),Sha1Hash(true,hash123));
33 | ASSERT_EQ(1,tree.packet_size());
34 | ASSERT_TRUE(tree.OfferData(bin64_t(0,0), "123\n", 4));
35 | unlink("123");
36 | ASSERT_EQ(4,tree.size());
37 | }
38 |
39 |
40 | TEST(Sha1HashTest,SubmitTest) {
41 | FILE* f123 = fopen("123","wb+");
42 | fprintf(f123, "123\n");
43 | fclose(f123);
44 | HashTree ht123("123");
45 | EXPECT_STREQ(hash123,ht123.hash(bin64_t(0,0)).hex().c_str());
46 | EXPECT_STREQ(rooth123,ht123.root_hash().hex().c_str());
47 | EXPECT_EQ(4,ht123.size());
48 | }
49 |
50 |
51 | /*TEST(Sha1HashTest,HashFileTest) {
52 | uint8_t a [1024], b[1024], c[1024];
53 | memset(a,'a',1024);
54 | memset(b,'b',1024);
55 | memset(c,'c',1024);
56 | Sha1Hash aaahash(a,1024), bbbhash(b,1024), ccchash(c,1024);
57 | Sha1Hash abhash(aaahash,bbbhash), c0hash(ccchash,Sha1Hash::ZERO);
58 | Sha1Hash aabbccroot(abhash,c0hash);
59 | for(bin pos=bin(7); pos
2 | #include
3 | #include
4 | #include
5 | #include "datagram.h"
6 | #include "swift.h"
7 | #include
8 |
9 | using namespace swift;
10 | using namespace std;
11 |
12 | /**
13 | TODO
14 | * losses
15 | * smooth rate
16 | * seq 12345 stop
17 | * busy pipe => negative cwnd
18 | */
19 |
20 | TEST(Datagram,LedbatTest) {
21 |
22 | int MAX_REORDERING = 3;
23 | tint TARGET = 25*TINT_MSEC;
24 | float GAIN = 1.0/TARGET;
25 | int seq_off = 0;
26 | float cwnd = 1;
27 | tint DELAY_BIN = TINT_SEC*30;
28 | tint min_delay = TINT_NEVER;
29 | tint rtt_avg = TINT_NEVER>>4, dev_avg = TINT_NEVER>>4;
30 | tint last_bin_time = 0;
31 | tint last_drop_time = 0;
32 | int delay_bin = 0;
33 | deque history, delay_history;
34 | tint min_delay_bins[4] = {TINT_NEVER,TINT_NEVER,
35 | TINT_NEVER,TINT_NEVER};
36 | tint cur_delays[4] = {TINT_NEVER,TINT_NEVER,
37 | TINT_NEVER,TINT_NEVER};
38 | tint last_sec = 0;
39 | int sec_ackd = 0;
40 |
41 | SOCKET send_sock = Datagram::Bind(10001); // bind sending socket
42 | SOCKET ack_sock = Datagram::Bind(10002); // bind receiving socket
43 | struct sockaddr_in send_to, ack_to;
44 | send_to.sin_family = AF_INET;
45 | send_to.sin_port = htons(10002);
46 | send_to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
47 | ack_to.sin_family = AF_INET;
48 | ack_to.sin_port = htons(10001);
49 | ack_to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
50 | uint8_t* garbage = (uint8_t*) malloc(1024);
51 | SOCKET socks[2] = {send_sock,ack_sock};
52 | SOCKET sock2read;
53 | tint wait_time = 100*TINT_MSEC;
54 |
55 | while (sock2read = Datagram::Wait(2,socks,wait_time)) {
56 | tint now = Datagram::Time();
57 | if (sock2read==ack_sock) {
58 | Datagram data(ack_sock); // send an acknowledgement
59 | data.Recv();
60 | int seq = data.Pull32();
61 | Datagram ack(ack_sock,ack_to);
62 | ack.Push32(seq);
63 | ack.Push64(now);
64 | if (4+8!=ack.Send())
65 | fprintf(stderr,"short write\n");
66 | fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq);
67 | //cc->OnDataRecv(bin64_t(0,seq));
68 | // TODO: peer cwnd !!!
69 | continue;
70 | }
71 | if (sock2read==send_sock) { // process an acknowledgement
72 | Datagram ack(send_sock);
73 | ack.Recv();
74 | int seq = ack.Pull32();
75 | tint arrival_time = ack.Pull64();
76 | seq -= seq_off;
77 | if (seq<0)
78 | continue;
79 | if (seq>=history.size())
80 | continue;
81 | if (history[seq]==0)
82 | continue;
83 | tint send_time = history[seq];
84 | history[seq] = 0;
85 | if (seq>MAX_REORDERING*2) { //loss
86 | if (last_drop_time delay)
112 | min_delay_bins[delay_bin] = delay;
113 | if (delay < min_delay)
114 | min_delay = delay;
115 | cur_delays[(seq_off+seq)%4] = delay;
116 | tint current_delay = TINT_NEVER;
117 | for(int i=0; i<4; i++)
118 | if (current_delay > cur_delays[i])
119 | current_delay = cur_delays[i]; // FIXME avg
120 | tint queueing_delay = current_delay - min_delay;
121 | // adjust cwnd
122 | tint off_target = TARGET - queueing_delay;
123 | //cerr<<"\t"<
2 | #include
3 | #ifdef _MSC_VER
4 | #include "compat/stdint.h"
5 | #include
6 | #else
7 | #include
8 | #include
9 | #include
10 | #endif
11 | #include
12 | #include
13 | #include "datagram.h"
14 | #include "swift.h"
15 | #include
16 |
17 | using namespace swift;
18 | using namespace std;
19 |
20 | /**
21 | TODO
22 | * losses
23 | * smooth rate
24 | * seq 12345 stop
25 | * busy pipe => negative cwnd
26 | */
27 |
28 | unsigned long dest_addr;
29 | int send_port = 10001;
30 | int ack_port = 10002;
31 |
32 | TEST(Datagram,LedbatTest) {
33 |
34 | int MAX_REORDERING = 3;
35 | tint TARGET = 25*TINT_MSEC;
36 | float GAIN = 1.0/TARGET;
37 | int seq_off = 0;
38 | float cwnd = 1;
39 | tint DELAY_BIN = TINT_SEC*30;
40 | tint min_delay = TINT_NEVER;
41 | tint rtt_avg = TINT_NEVER>>4, dev_avg = TINT_NEVER>>4;
42 | tint last_bin_time = 0;
43 | tint last_drop_time = 0;
44 | int delay_bin = 0;
45 | deque history, delay_history;
46 | tint min_delay_bins[4] = {TINT_NEVER,TINT_NEVER,
47 | TINT_NEVER,TINT_NEVER};
48 | tint cur_delays[4] = {TINT_NEVER,TINT_NEVER,
49 | TINT_NEVER,TINT_NEVER};
50 | tint last_sec = 0;
51 | int sec_ackd = 0;
52 |
53 | // bind sending socket
54 | SOCKET send_sock = Datagram::Bind(Address(INADDR_ANY,send_port));
55 | // bind receiving socket
56 | SOCKET ack_sock = Datagram::Bind(Address(INADDR_ANY,ack_port));
57 | struct sockaddr_in send_to, ack_to;
58 | memset(&send_to, 0, sizeof(struct sockaddr_in));
59 | memset(&ack_to, 0, sizeof(struct sockaddr_in));
60 | send_to.sin_family = AF_INET;
61 | send_to.sin_port = htons(ack_port);
62 | send_to.sin_addr.s_addr = dest_addr;
63 | ack_to.sin_family = AF_INET;
64 | ack_to.sin_port = htons(send_port);
65 | ack_to.sin_addr.s_addr = dest_addr;
66 | uint8_t* garbage = (uint8_t*) malloc(1024);
67 | SOCKET socks[2] = {send_sock,ack_sock};
68 | SOCKET sock2read;
69 | tint wait_time = 100*TINT_MSEC;
70 |
71 | while (sock2read = Datagram::Wait(2,socks,wait_time)) {
72 | tint now = Datagram::Time();
73 | if (sock2read==ack_sock) {
74 | Datagram data(ack_sock); // send an acknowledgement
75 | data.Recv();
76 | int seq = data.Pull32();
77 | Datagram ack(ack_sock,ack_to);
78 | ack.Push32(seq);
79 | ack.Push64(now);
80 | if (4+8!=ack.Send())
81 | fprintf(stderr,"short write\n");
82 | fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq);
83 | // TODO: peer cwnd !!!
84 | continue;
85 | }
86 | if (sock2read==send_sock) { // process an acknowledgement
87 | Datagram ack(send_sock);
88 | ack.Recv();
89 | int seq = ack.Pull32();
90 | tint arrival_time = ack.Pull64();
91 | seq -= seq_off;
92 | if (seq<0)
93 | continue;
94 | if (seq>=history.size())
95 | continue;
96 | if (history[seq]==0)
97 | continue;
98 | tint send_time = history[seq];
99 | history[seq] = 0;
100 | if (seq>MAX_REORDERING*2) { //loss
101 | if (last_drop_time delay)
127 | min_delay_bins[delay_bin] = delay;
128 | if (delay < min_delay)
129 | min_delay = delay;
130 | cur_delays[(seq_off+seq)%4] = delay;
131 | tint current_delay = TINT_NEVER;
132 | for(int i=0; i<4; i++)
133 | if (current_delay > cur_delays[i])
134 | current_delay = cur_delays[i]; // FIXME avg
135 | tint queueing_delay = current_delay - min_delay;
136 | // adjust cwnd
137 | tint off_target = TARGET - queueing_delay;
138 | //cerr<<"\t"< $STORE/leecher$i.log ) &
15 | TOKILL="$TOKILL $!"
16 | sleep 4;
17 | done
18 |
19 | sleep 10
20 |
21 | for p in $TOKILL; do
22 | kill -9 $p
23 | done
24 |
25 | for i in `seq 1 $PEERCOUNT`; do
26 | cat $STORE/leecher$i.log | grep sent | awk '{print $5}' | \
27 | sort | uniq -c > $STORE/peers$i.txt
28 | peers=`wc -l < $STORE/peers$i.txt`
29 | if [ $peers -ne $PEERCOUNT ]; then
30 | echo Peer $i has $peers peers
31 | fi
32 | done
33 |
--------------------------------------------------------------------------------
/tests/rwtest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * readwrite.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 3/19/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 |
10 | #include
11 | #include "p2tp.h"
12 |
13 | TEST(P2TP, ConnectTest) {
14 | P2File("");
15 | p2tp_init(7001);
16 |
17 | int tf = p2tp_open("test_file",NULL);
18 | int tb = p2tp_open("test_file_copy",p2tp_file_info(tf)->hash_data);
19 | struct sockaddr_in addr;
20 | addr.sin_family = AF_INET;
21 | addr.sin_port = htons(7001);
22 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
23 | p2tp_add_peer(tb,addr,0); // TRICK: will open a channel to the first file
24 | p2tp_loop(P2TP::now()+TINT1SEC/10);
25 |
26 | while (count=copy.read(bytes)) {
27 | read(orig,bytes2,count);
28 | ASSERT_EQ ( 0, memcmp(bytes,bytes2,count) );
29 | }
30 |
31 | p2tp_close(tb);
32 | p2tp_close(tf);
33 |
34 | }
35 |
36 | int main (int argc, char** argv) {
37 | P2TP::init();
38 |
39 | testing::InitGoogleTest(&argc, argv);
40 | return RUN_ALL_TESTS();
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/tests/sbit2test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * sbit2test.cpp
3 | * serp++
4 | *
5 | * Created by Victor Grishchenko on 4/1/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 |
10 | #include "bin.h"
11 | #include "sbit.h"
12 | #include
13 |
14 | TEST(SbitTest,Init) {
15 | bins s;
16 | s.set(1);
17 | EXPECT_TRUE(s.get(1));
18 | EXPECT_FALSE(s.get(2));
19 | EXPECT_FALSE(s.get(3));
20 | s.set(3);
21 | EXPECT_TRUE(s.get(1));
22 | EXPECT_TRUE(s.get(2));
23 | EXPECT_TRUE(s.get(3));
24 | }
25 |
26 |
27 | TEST(SbitTest,Expand) {
28 | bins s;
29 | s.set(1);
30 | s.set(34);
31 | EXPECT_TRUE(s.get(1));
32 | EXPECT_FALSE(s.get(2));
33 | EXPECT_TRUE(s.get(32));
34 | EXPECT_TRUE(s.get(33));
35 | EXPECT_FALSE(s.get(35));
36 | s.set(31);
37 | s.set(62);
38 | EXPECT_TRUE(s.get(3));
39 | EXPECT_TRUE(s.get(63));
40 | }
41 |
42 |
43 | TEST(SbitTest,Chess) {
44 | bins s;
45 | s.set(7);
46 | s.set(22);
47 | EXPECT_FALSE(s.get(14));
48 | EXPECT_FALSE(s.get(30));
49 | EXPECT_FALSE(s.get(29));
50 | s.set(29);
51 | EXPECT_FALSE(s.get(31));
52 | s.set(10);
53 | EXPECT_FALSE(s.get(31));
54 | s.set(11);
55 | EXPECT_FALSE(s.get(31));
56 | s.set(12);
57 | EXPECT_TRUE(s.get(31));
58 | }
59 |
60 |
61 | TEST(SbitTest,Hole) {
62 | bins b;
63 | int h=14;
64 | for(int i=0; i ");
121 | bin::order(&v);
122 | ///for(int i=0; i
12 |
13 | TEST(SierpinskyBitmapTest,Init) {
14 | uint64_t one32 = (1ULL<<32)-1;
15 | uint64_t mask = one32;
16 | uint64_t mask_history[5];
17 | for(int i=0; i<5; i++) {
18 | mask_history[i] = mask;
19 | mask = sbit::join(bin(i+1,0),mask,0);
20 | }
21 | EXPECT_EQ(1,mask)<<"joined OK";
22 | for(int i=5; i; i--) {
23 | uint64pair p = sbit::split(bin(i,0),mask);
24 | mask = p.first;
25 | EXPECT_EQ(mask_history[i-1],mask)<<"mask history check";
26 | }
27 | EXPECT_EQ(one32,mask)<<"join/split cycle";
28 |
29 | EXPECT_EQ(3, sbit::MASKS[0][3])<<"the first two-bit interval, layer 0";
30 | EXPECT_EQ(5, sbit::MASKS[1][3])<<"the first two-bit interval, layer 1";
31 | EXPECT_EQ(0x000000000000000FLLU, sbit::MASKS[0][bin(2,0)])<<"the first four-bit interval @0";
32 | EXPECT_EQ(0xFF00000000000000LLU, sbit::MASKS[0][bin(3,7)])<<"the last eight-bit interval @0";
33 | EXPECT_EQ(0xAAAA000000000000LLU, sbit::MASKS[1][bin(3,7)])<<"the last eight-bit interval @1";
34 | EXPECT_EQ(0x8080808080808080LLU, sbit::MASKS[3][bin(3,7)])<<"the last eight-bit interval @3";
35 | EXPECT_EQ(1<<16, sbit::MASKS[0][bin(0,16)])<< "trivial: bit 16";
36 | EXPECT_EQ(0x100000000LLU, sbit::MASKS[1][bin(0,16)])<< "trivial: bit 16 layer 1";
37 | EXPECT_EQ(2, sbit::MASKS[2][bin(0,16)])<< "layout: bit wrap, 16 @layer 2";
38 | }
39 |
40 | TEST(SierpinskyBitmapTest,GetSetAggregation) {
41 | sbit s;
42 | s.set(3);
43 | EXPECT_EQ(true,s.get(1)) << "trivial set/retr";
44 | EXPECT_EQ(false,s.get(31)) << "trivial 0";
45 | s.set(14);
46 | s.set(30);
47 | EXPECT_EQ(false,s.get(31)) << "trivial 0";
48 | s.set(6);
49 | EXPECT_EQ(true,s.get(31)) << "aggregated set/retr";
50 | s.set(127);
51 | EXPECT_EQ(true,s.get(127)) << "just extension";
52 | EXPECT_EQ(false,s.get(255)) << "just extension";
53 | s.set(254);
54 | EXPECT_EQ(true,s.get(255)) << "aggregated with extension";
55 | }
56 |
57 | TEST(SierpinskyBitmapTest,FishEyeBitmaps) {
58 | sbit s; // 2^8 = 256 bits
59 | s.set(bin(7,0));
60 | s.set(bin(5,4));
61 | s.set(bin(1,128));
62 | s.set(bin(2,80));
63 | feye eye(s, bin(6,2));
64 | // water-ground-air-mountain set/get
65 | EXPECT_EQ( eye.bits[2], sbit::MASK1 ) << "all-1 chunk";
66 | EXPECT_EQ( sbit::MASKS[2][bin(0,16)], eye.bits[3] ) << "all-1 chunk";
67 | EXPECT_EQ( true, eye.get(bin(5,4)) ) << "MOUNTAIN 1-half";
68 | EXPECT_EQ( false, eye.get(bin(5,5)) ) << "MOUNTAIN 0-half";
69 | EXPECT_EQ( true, eye.get(bin(6,1)) ) << "MOUNTAIN all-ones";
70 | EXPECT_EQ( true, eye.get(bin(7,0)) ) << "top-MOUNTAIN 7 layer ones";
71 | EXPECT_EQ( false, eye.get(bin(7,1)) ) << "AIR just a quarter is 1, must be 0";
72 | EXPECT_EQ( true, eye.get(bin(2,80)) ) << "GROUND 4-bit fragment is saved";
73 | EXPECT_EQ( true, eye.get(bin(1,160)) )
74 | << "WATER 2-bit fragment is saved (farther from the focus)";
75 | EXPECT_EQ( false, eye.get(bin(1,128)) )
76 | << "sunk-WATER 2-bit fragment is lost (far from the focus)";
77 | // refocus
78 | feye triv(eye, bin(0,64*3));
79 | EXPECT_EQ(triv.bits[0],eye.bits[1])<<"trivial refocus 1";
80 | EXPECT_EQ(triv.bits[1],eye.bits[0])<<"trivial refocus 2";
81 | EXPECT_EQ(triv.bits[2],eye.bits[2])<<"trivial refocus 3";
82 | feye ref(eye, bin(0,64*8));
83 | EXPECT_EQ (false, ref.get(bin(2,80)) ) << "after refocusing, the 4-bit fragment is lost";
84 | EXPECT_EQ (true, ref.get(bin(7,0)) ) << "but 7l (128bits) fragment is still there";
85 | EXPECT_EQ (sbit::MASKS[3][bin(4,0)]|sbit::MASKS[3][bin(2,4)],ref.bits[4]) << "gather OK";
86 |
87 | }
88 |
89 |
90 | TEST(SierpinskyBitmapTest,BitwiseOps) {
91 | feye l(bin(6,2));
92 | feye r(bin(6,2));
93 | l.set(bin(1,0));
94 | r.set(bin(1,1));
95 | feye orf(l);
96 | orf |= r;
97 | EXPECT_EQ (true, orf.get(bin(2,0))) << "OR adds up correctly";
98 | EXPECT_EQ (false, orf.get(bin(2,1))) << "OR adds up correctly";
99 | feye andf = l&r;
100 | EXPECT_EQ (false, andf.get(bin(2,0)) ) << "AND adds up correctly";
101 | feye eye(bin(18,1));
102 | eye.set(bin::ALL);
103 | EXPECT_EQ(true,eye.get(bin::ALL)) << "bin_ALL";
104 | EXPECT_EQ(true,eye.get(bin(12,34))) << "any in bin_ALL";
105 | EXPECT_EQ(sbit::MASK1,eye.bits[24]) << "bin_ALL: all 1";
106 | }
107 |
108 |
109 | bin bin_random () {
110 | return rand()%bin::ALL;
111 | }
112 |
113 |
114 | TEST (SierpinskyBitmapTest,CryBabyCry) {
115 | for (int i=0; i<10000; i++) {
116 | bin point = bin_random();
117 | bin focus = bin(0,rand()%(1<<30));
118 | feye f(focus);
119 | f.set(point);
120 | bin cp = point.commonParent(focus);
121 | uint8_t cpheight = cp.layer();
122 | uint8_t pointheight = point.layer();
123 | uint8_t topheight = cp==focus? 6 : cpheight-1 ;
124 | bool visible = topheight-6 <= pointheight;
125 | EXPECT_EQ (visible, f.get(point)) <<
126 | "FAIL: another random test: point "<0 && !ref.get(point.left()))
142 | << "FAIL: mystically, left child is 0\n";
143 | /*EXPECT_FALSE (pointheight>0 && !ref.get(bin_rightn(point,pointheight)))
144 | << "FAIL: mystically, the rightmost bit is 0\n";*/
145 | }
146 |
147 | }
148 |
149 | }
150 |
151 |
152 | TEST(FishEyeBitmap, OrTest) {
153 | feye a(bin(0,0)), b(bin(0,256));
154 | a.set(bin(2,64)); // 256-259
155 | feye ach(a,bin(0,256));
156 | EXPECT_TRUE(ach.get(bin(2,64)));
157 | b.set(bin(0,260));
158 | b.set(bin(0,261));
159 | b.set(bin(0,262));
160 | b.set(bin(0,263));
161 | EXPECT_TRUE(b.get(bin(2,65)));
162 | b.refocus(bin(0,257));
163 | EXPECT_TRUE(b.get(bin(2,65)));
164 | b |= a;
165 | EXPECT_TRUE(b.get(bin(2,65).parent()));
166 | }
167 |
168 |
169 | int main (int argc, char** argv) {
170 | bin::init();
171 | sbit::init();
172 |
173 | testing::InitGoogleTest(&argc, argv);
174 | return RUN_ALL_TESTS();
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/tests/transfertest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * transfertest.cpp
3 | * swift
4 | *
5 | * Created by Victor Grishchenko on 10/7/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | //#include
10 | //#include
11 | #include "swift.h"
12 | #include "compat.h"
13 | #include
14 |
15 | using namespace swift;
16 |
17 | const char* BTF = "test_file";
18 |
19 | Sha1Hash A,B,C,D,E,AB,CD,ABCD,E0,E000,ABCDE000,ROOT;
20 |
21 |
22 | TEST(TransferTest,TBHeap) {
23 | tbheap tbh;
24 | ASSERT_TRUE(tbh.is_empty());
25 | tbh.push(tintbin(3,bin64_t::NONE));
26 | tbh.push(tintbin(1,bin64_t::NONE));
27 | ASSERT_EQ(2,tbh.size());
28 | tbh.push(tintbin(2,bin64_t::ALL));
29 | ASSERT_EQ(1,tbh.pop().time);
30 | ASSERT_EQ(bin64_t::ALL,tbh.peek().bin);
31 | ASSERT_EQ(2,tbh.pop().time);
32 | ASSERT_EQ(3,tbh.pop().time);
33 | }
34 |
35 |
36 | TEST(TransferTest,TransferFile) {
37 |
38 | AB = Sha1Hash(A,B);
39 | CD = Sha1Hash(C,D);
40 | ABCD = Sha1Hash(AB,CD);
41 | E0 = Sha1Hash(E,Sha1Hash::ZERO);
42 | E000 = Sha1Hash(E0,Sha1Hash::ZERO);
43 | ABCDE000 = Sha1Hash(ABCD,E000);
44 | ROOT = ABCDE000;
45 | for (bin64_t pos(3,0); pos!=bin64_t::ALL; pos=pos.parent()) {
46 | ROOT = Sha1Hash(ROOT,Sha1Hash::ZERO);
47 | //printf("m %lli %s\n",(uint64_t)pos.parent(),ROOT.hex().c_str());
48 | }
49 |
50 | // now, submit a new file
51 |
52 | FileTransfer* seed_transfer = new FileTransfer(BTF);
53 | HashTree* seed = & seed_transfer->file();
54 | EXPECT_TRUE(A==seed->hash(bin64_t(0,0)));
55 | EXPECT_TRUE(E==seed->hash(bin64_t(0,4)));
56 | EXPECT_TRUE(ABCD==seed->hash(bin64_t(2,0)));
57 | EXPECT_TRUE(ROOT==seed->root_hash());
58 | EXPECT_TRUE(ABCD==seed->peak_hash(0));
59 | EXPECT_TRUE(E==seed->peak_hash(1));
60 | EXPECT_TRUE(ROOT==seed->root_hash());
61 | EXPECT_EQ(4100,seed->size());
62 | EXPECT_EQ(5,seed->packet_size());
63 | EXPECT_EQ(4100,seed->complete());
64 | EXPECT_EQ(4100,seed->seq_complete());
65 | EXPECT_EQ(bin64_t(2,0),seed->peak(0));
66 |
67 | // retrieve it
68 | unlink("copy");
69 | FileTransfer* leech_transfer = new FileTransfer("copy",seed->root_hash());
70 | HashTree* leech = & leech_transfer->file();
71 | leech_transfer->picker().Randomize(0);
72 | // transfer peak hashes
73 | for(int i=0; ipeak_count(); i++)
74 | leech->OfferHash(seed->peak(i),seed->peak_hash(i));
75 | ASSERT_EQ(5<<10,leech->size());
76 | ASSERT_EQ(5,leech->packet_size());
77 | ASSERT_EQ(0,leech->complete());
78 | EXPECT_EQ(bin64_t(2,0),leech->peak(0));
79 | // transfer data and hashes
80 | // ABCD E000
81 | // AB CD E0 0
82 | // AAAA BBBB CCCC DDDD E 0 0 0
83 | // calculated leech->OfferHash(bin64_t(1,0), seed->hashes[bin64_t(1,0)]);
84 | leech->OfferHash(bin64_t(1,1), seed->hash(bin64_t(1,1)));
85 | for (int i=0; i<5; i++) {
86 | if (i==2) { // now: stop, save, start
87 | delete leech_transfer;
88 | leech_transfer = new FileTransfer("copy",seed->root_hash());
89 | leech = & leech_transfer->file();
90 | leech_transfer->picker().Randomize(0);
91 | EXPECT_EQ(2,leech->packets_complete());
92 | EXPECT_EQ(bin64_t(2,0),leech->peak(0));
93 | }
94 | bin64_t next = leech_transfer->picker().Pick(seed->ack_out(),1,TINT_NEVER);
95 | ASSERT_NE(bin64_t::NONE,next);
96 | ASSERT_TRUE(next.base_offset()<5);
97 | uint8_t buf[1024]; //size_t len = seed->storer->ReadData(next,&buf);
98 | size_t len = pread(seed->file_descriptor(),buf,1024,next.base_offset()<<10);
99 | bin64_t sibling = next.sibling();
100 | if (sibling.base_offset()packet_size())
101 | leech->OfferHash(sibling, seed->hash(sibling));
102 | uint8_t memo = *buf;
103 | *buf = 'z';
104 | EXPECT_FALSE(leech->OfferData(next, (char*)buf, len));
105 | fprintf(stderr,"kidding\n");
106 | *buf = memo;
107 | EXPECT_TRUE(leech->OfferData(next, (char*)buf, len));
108 | }
109 | EXPECT_EQ(4100,leech->size());
110 | EXPECT_EQ(5,leech->packet_size());
111 | EXPECT_EQ(4100,leech->complete());
112 | EXPECT_EQ(4100,leech->seq_complete());
113 |
114 | }
115 | /*
116 | FIXME
117 | - always rehashes (even fresh files)
118 | */
119 |
120 | int main (int argc, char** argv) {
121 |
122 | unlink("test_file");
123 | unlink("copy");
124 | unlink("test_file.mhash");
125 | unlink("copy.mhash");
126 |
127 | int f = open(BTF,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
128 | if (f < 0)
129 | {
130 | eprintf("Error opening %s\n",BTF);
131 | return -1;
132 | }
133 | uint8_t buf[1024];
134 | memset(buf,'A',1024);
135 | A = Sha1Hash(buf,1024);
136 | write(f,buf,1024);
137 | memset(buf,'B',1024);
138 | B = Sha1Hash(buf,1024);
139 | write(f,buf,1024);
140 | memset(buf,'C',1024);
141 | C = Sha1Hash(buf,1024);
142 | write(f,buf,1024);
143 | memset(buf,'D',1024);
144 | D = Sha1Hash(buf,1024);
145 | write(f,buf,1024);
146 | memset(buf,'E',4);
147 | E = Sha1Hash(buf,4);
148 | write(f,buf,4);
149 | close(f);
150 |
151 | testing::InitGoogleTest(&argc, argv);
152 | int ret = RUN_ALL_TESTS();
153 |
154 | return ret;
155 | }
156 |
--------------------------------------------------------------------------------
/transfer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * transfer.cpp
3 | * some transfer-scope code
4 | *
5 | * Created by Victor Grishchenko on 10/6/09.
6 | * Copyright 2009 Delft University of Technology. All rights reserved.
7 | *
8 | */
9 | #include
10 | #include
11 | #include
12 | #include "swift.h"
13 |
14 | #include "ext/seq_picker.cpp" // FIXME FIXME FIXME FIXME
15 |
16 | using namespace swift;
17 |
18 | std::vector FileTransfer::files(20);
19 |
20 | #define BINHASHSIZE (sizeof(bin64_t)+sizeof(Sha1Hash))
21 |
22 | // FIXME: separate Bootstrap() and Download(), then Size(), Progress(), SeqProgress()
23 |
24 | FileTransfer::FileTransfer (const char* filename, const Sha1Hash& _root_hash) :
25 | file_(filename,_root_hash), hs_in_offset_(0), cb_installed(0)
26 | {
27 | if (files.size()Randomize(rand()&63);
32 | init_time_ = Datagram::Time();
33 | }
34 |
35 |
36 | void Channel::CloseTransfer (FileTransfer* trans) {
37 | for(int i=0; itransfer_==trans)
39 | delete Channel::channels[i];
40 | }
41 |
42 |
43 | void swift::AddProgressCallback (int transfer,ProgressCallback cb,uint8_t agg) {
44 | FileTransfer* trans = FileTransfer::file(transfer);
45 | if (!trans)
46 | return;
47 | trans->cb_agg[trans->cb_installed] = agg;
48 | trans->callbacks[trans->cb_installed] = cb;
49 | trans->cb_installed++;
50 | }
51 |
52 |
53 | void swift::ExternallyRetrieved (int transfer,bin64_t piece) {
54 | FileTransfer* trans = FileTransfer::file(transfer);
55 | if (!trans)
56 | return;
57 | trans->ack_out().set(piece); // that easy
58 | }
59 |
60 |
61 | void swift::RemoveProgressCallback (int transfer, ProgressCallback cb) {
62 | FileTransfer* trans = FileTransfer::file(transfer);
63 | if (!trans)
64 | return;
65 | for(int i=0; icb_installed; i++)
66 | if (trans->callbacks[i]==cb)
67 | trans->callbacks[i]=trans->callbacks[--trans->cb_installed];
68 | }
69 |
70 |
71 | FileTransfer::~FileTransfer ()
72 | {
73 | Channel::CloseTransfer(this);
74 | files[fd()] = NULL;
75 | delete picker_;
76 | }
77 |
78 |
79 | FileTransfer* FileTransfer::Find (const Sha1Hash& root_hash) {
80 | for(int i=0; iroot_hash()==root_hash)
82 | return files[i];
83 | return NULL;
84 | }
85 |
86 |
87 | int swift:: Find (Sha1Hash hash) {
88 | FileTransfer* t = FileTransfer::Find(hash);
89 | if (t)
90 | return t->fd();
91 | return -1;
92 | }
93 |
94 |
95 |
96 | void FileTransfer::OnPexIn (const Address& addr) {
97 | for(int i=0; itransfer().fd()==this->fd() && c->peer()==addr)
100 | return; // already connected
101 | }
102 | if (hs_in_.size()<20) {
103 | new Channel(this,Datagram::default_socket(),addr);
104 | } else {
105 | pex_in_.push_back(addr);
106 | if (pex_in_.size()>1000)
107 | pex_in_.pop_front();
108 | }
109 | }
110 |
111 |
112 | int FileTransfer::RevealChannel (int& pex_out_) { // FIXME brainfuck
113 | pex_out_ -= hs_in_offset_;
114 | if (pex_out_<0)
115 | pex_out_ = 0;
116 | while (pex_out_transfer().fd()==this->fd()) {
119 | if (c->is_established()) {
120 | pex_out_ += hs_in_offset_ + 1;
121 | return c->id();
122 | } else
123 | pex_out_++;
124 | } else {
125 | hs_in_[pex_out_] = hs_in_[0];
126 | hs_in_.pop_front();
127 | hs_in_offset_++;
128 | }
129 | }
130 | pex_out_ += hs_in_offset_;
131 | return -1;
132 | }
133 |
134 |
--------------------------------------------------------------------------------