@@ -9,10 +9,12 @@ extern crate turnclient;
9
9
extern crate tokio;
10
10
extern crate spin_sleep;
11
11
extern crate tokio_timer;
12
+ extern crate byteorder;
12
13
13
14
use std:: time:: { Duration , Instant } ;
14
15
use std:: net:: SocketAddr ;
15
16
use structopt:: StructOpt ;
17
+ use std:: sync:: Arc ;
16
18
17
19
use futures:: { Async , Future , Poll } ;
18
20
use futures:: { Stream , Sink } ;
@@ -54,7 +56,7 @@ struct Opt {
54
56
55
57
/// Packets per second
56
58
#[ structopt( long="pps" , default_value="5" ) ]
57
- delay_between_packets : u32 ,
59
+ packets_per_second : u32 ,
58
60
59
61
/// Experiment duration, seconds
60
62
#[ structopt( short="d" , long="duration" , default_value="5" ) ]
@@ -74,11 +76,67 @@ enum ServeTurnEventOrShutdown {
74
76
Shutdown ,
75
77
}
76
78
79
+ fn sending_thread (
80
+ udp : Arc < std:: net:: UdpSocket > ,
81
+ packet_size : usize ,
82
+ packets_per_second : u32 ,
83
+ duration_seconds : u64 ,
84
+ destinations : Vec < SocketAddr > ,
85
+ time_base : Instant ,
86
+ ) {
87
+ let sleeper = spin_sleep:: SpinSleeper :: default ( ) ;
88
+ sleeper. sleep_ns ( 500_000_000 ) ; // to allow receiver to warm up
89
+ let start = Instant :: now ( ) ;
90
+ let step = Duration :: from_secs ( 1 ) / packets_per_second;
91
+ let n = packets_per_second * ( duration_seconds as u32 ) ;
92
+
93
+ use byteorder:: { BE , ByteOrder } ;
94
+
95
+ let mut buf = vec ! [ 0 ; packet_size] ;
96
+
97
+ let mut totalctr : u32 = 0 ;
98
+
99
+ for i in 0 ..n {
100
+ let deadline = start + step * i;
101
+ let now = Instant :: now ( ) ;
102
+ let delta = now - time_base;
103
+
104
+ BE :: write_u64 ( & mut buf[ 0 ..8 ] , delta. as_secs ( ) ) ;
105
+ BE :: write_u32 ( & mut buf[ 8 ..12 ] , delta. subsec_nanos ( ) ) ;
106
+
107
+ if now < deadline {
108
+ sleeper. sleep ( deadline - now) ;
109
+ }
110
+
111
+ let udp = & * udp;
112
+ for addr in & destinations {
113
+ BE :: write_u32 ( & mut buf[ 12 ..16 ] , totalctr) ;
114
+ udp. send_to ( & buf[ ..] , addr) . expect ( "UDP send_to failed" ) ;
115
+ totalctr+=1 ;
116
+ }
117
+ }
118
+ }
119
+
120
+ fn receiving_thread (
121
+ udp : Arc < std:: net:: UdpSocket > ,
122
+ duration_seconds : u64 ,
123
+ packet_size : usize ,
124
+ time_base : Instant ,
125
+ ) {
126
+ let mut buf = vec ! [ 0 ; packet_size] ;
127
+ loop {
128
+ let ( _len, _addr) = udp. recv_from ( & mut buf[ ..] ) . expect ( "Failed to receive packet" ) ;
129
+ println ! ( "Received a packet from {}" , _addr) ;
130
+ }
131
+ }
132
+
77
133
fn main ( ) -> Result < ( ) , Error > {
78
134
let opt = Opt :: from_args ( ) ;
79
135
80
136
let local_addr: SocketAddr = "0.0.0.0:0" . parse ( ) . unwrap ( ) ;
81
137
let probing_udp = std:: net:: UdpSocket :: bind ( local_addr) ?;
138
+ let probing_udp = Arc :: new ( probing_udp) ;
139
+ let time_base = Instant :: now ( ) ;
82
140
83
141
// Phase 1: Query my own external address
84
142
let extaddr = stunclient:: StunClient :: new ( opt. server )
@@ -91,6 +149,8 @@ fn main() -> Result<(), Error> {
91
149
let k = opt. num_connections ;
92
150
let duration = opt. duration ;
93
151
let delay_after_stopping_sender = opt. delay_after_stopping_sender ;
152
+ let packet_size = opt. packet_size ;
153
+ let pps = opt. packets_per_second ;
94
154
95
155
let clientstream = futures:: stream:: repeat :: < _ , Error > (
96
156
( opt. server , opt. username , opt. password ) ,
@@ -149,18 +209,39 @@ fn main() -> Result<(), Error> {
149
209
let clienthandles = clienthandles. and_then ( move |x|{
150
210
let ( init_handles, shutdown_handles) : ( Vec < _ > , Vec < _ > ) = x. into_iter ( ) . unzip ( ) ;
151
211
futures:: future:: join_all ( init_handles)
152
- . and_then ( |h| {
153
- eprintln ! ( "Allocated {} TURN clients" , h. len( ) ) ;
154
- futures:: future:: ok ( ( ) )
155
- } )
156
212
. map_err ( |_e|Error :: from ( "Oneshot error" ) )
157
- . and_then ( move |( ) | {
213
+ . and_then ( move |destinations| {
214
+ eprintln ! ( "Allocated {} TURN clients" , destinations. len( ) ) ;
215
+ // Phase 3: Starting sender and receiver
216
+
217
+ let probing_udp2 = probing_udp. clone ( ) ;
218
+ std:: thread:: spawn ( move || {
219
+ sending_thread (
220
+ probing_udp2,
221
+ packet_size,
222
+ pps,
223
+ duration,
224
+ destinations,
225
+ time_base,
226
+ ) ;
227
+ } ) ;
228
+ std:: thread:: spawn ( move || {
229
+ receiving_thread (
230
+ probing_udp,
231
+ duration,
232
+ packet_size,
233
+ time_base,
234
+ ) ;
235
+ } ) ;
236
+
158
237
tokio_timer:: Delay :: new (
159
238
Instant :: now ( ) +
160
239
Duration :: from_secs (
161
240
duration + delay_after_stopping_sender
162
241
)
163
242
) . and_then ( |( ) | {
243
+ // Phase 4: Stopping
244
+
164
245
eprintln ! ( "Stopping TURN clients" ) ;
165
246
for sh in shutdown_handles {
166
247
sh. send ( ( ) ) ;
0 commit comments