@@ -31,7 +31,6 @@ use std::sync::Arc;
31
31
use anyhow:: Context ;
32
32
use once_cell:: sync:: OnceCell ;
33
33
use parking_lot:: Mutex ;
34
- use tokio:: sync:: mpsc:: { channel, Receiver , Sender } ;
35
34
use tokio:: sync:: Mutex as AsyncMutex ;
36
35
use wchar:: * ;
37
36
use widestring:: * ;
@@ -48,6 +47,7 @@ use winapi::um::handleapi::*;
48
47
use winapi:: um:: ioapiset:: * ;
49
48
use winapi:: um:: minwinbase:: * ;
50
49
use winapi:: um:: namespaceapi:: * ;
50
+ use winapi:: um:: processthreadsapi:: * ;
51
51
use winapi:: um:: securitybaseapi:: * ;
52
52
use winapi:: um:: setupapi:: * ;
53
53
use winapi:: um:: synchapi:: * ;
@@ -110,105 +110,21 @@ use self::interface::*;
110
110
mod buffer;
111
111
use self :: buffer:: * ;
112
112
113
- pub struct AsyncTun {
114
- tun : Arc < Tun > ,
115
- channels : AsyncMutex < TunChannels > ,
116
- }
117
-
118
- struct TunChannels {
119
- read_rx : Receiver < io:: Result < ( Box < [ u8 ] > , usize ) > > ,
120
- buffer_tx : Sender < Box < [ u8 ] > > ,
121
- }
122
-
123
- impl Drop for AsyncTun {
124
- fn drop ( & mut self ) {
125
- self . tun . interrupt ( ) ;
126
- }
127
- }
128
-
129
- impl AsyncTun {
130
- pub fn open ( name : & OsStr ) -> anyhow:: Result < AsyncTun > {
131
- let tun = Tun :: open ( name) ?;
132
- Ok ( AsyncTun :: new ( tun) )
133
- }
134
-
135
- fn new ( tun : Tun ) -> AsyncTun {
136
- let tun = Arc :: new ( tun) ;
137
- // read thread -> async fn read.
138
- let ( mut read_tx, read_rx) = channel ( 2 ) ;
139
- // async fn read -> read thread, to reuse buffers.
140
- let ( mut buffer_tx, mut buffer_rx) = channel :: < Box < [ u8 ] > > ( 2 ) ;
141
- buffer_tx. try_send ( vec ! [ 0u8 ; 65536 ] . into ( ) ) . unwrap ( ) ;
142
- buffer_tx. try_send ( vec ! [ 0u8 ; 65536 ] . into ( ) ) . unwrap ( ) ;
143
- // We run this in a separate thread so that the wintun intance can be
144
- // dropped.
145
- //
146
- // We let tokio manage this thread so that the tokio runtime is not
147
- // dropped before the wintun instance.
148
- tokio:: spawn ( {
149
- let tun = tun. clone ( ) ;
150
- async move {
151
- ' outer: loop {
152
- let mut buf = match buffer_rx. recv ( ) . await {
153
- None => break ,
154
- Some ( buf) => buf,
155
- } ;
156
- // We don't want to consume the `buf` when we get an
157
- // `Err`. So loop until we get an `Ok`.
158
- loop {
159
- match tokio:: task:: block_in_place ( || tun. read ( & mut buf[ ..] ) ) {
160
- Err ( e) => {
161
- if read_tx. send ( Err ( e) ) . await . is_err ( ) {
162
- break ' outer;
163
- }
164
- }
165
- Ok ( len) => {
166
- if read_tx. send ( Ok ( ( buf, len) ) ) . await . is_err ( ) {
167
- break ' outer;
168
- }
169
- break ;
170
- }
171
- }
172
- }
173
- }
174
- }
175
- } ) ;
176
- AsyncTun {
177
- tun,
178
- channels : AsyncMutex :: new ( TunChannels { read_rx, buffer_tx } ) ,
179
- }
180
- }
181
-
182
- pub ( crate ) async fn read < ' a > ( & ' a self , buf : & ' a mut [ u8 ] ) -> io:: Result < usize > {
183
- // Don't use `blocking` for operations that may block forever.
184
-
185
- let mut channels = self . channels . lock ( ) . await ;
186
-
187
- let ( p, p_len) = channels. read_rx . recv ( ) . await . unwrap ( ) ?;
188
- let len = std:: cmp:: min ( p_len, buf. len ( ) ) ;
189
- buf[ ..len] . copy_from_slice ( & p[ ..len] ) ;
190
- channels. buffer_tx . send ( p) . await . unwrap ( ) ;
191
- Ok ( len)
192
- }
193
-
194
- pub ( crate ) async fn write < ' a > ( & ' a self , buf : & ' a [ u8 ] ) -> io:: Result < usize > {
195
- self . tun . write ( buf)
196
- }
197
- }
198
-
199
113
/// A handle to a tun interface.
200
- struct Tun {
114
+ pub struct AsyncTun {
201
115
handle : HandleWrapper ,
202
116
name : OsString ,
203
117
rings : TunRegisterRings ,
204
- read_lock : Mutex < ( ) > ,
118
+ // A clone of `rings.send.tail_moved` (created by `DuplicateHandle`) wrapped
119
+ // in `Arc` that can be sent to `spawn_blocking`.
120
+ send_tail_moved_clone : Arc < HandleWrapper > ,
121
+ read_lock : AsyncMutex < ( ) > ,
205
122
write_lock : Mutex < ( ) > ,
206
- cancel_event : HandleWrapper ,
207
123
}
208
124
209
- impl fmt:: Debug for Tun {
125
+ impl fmt:: Debug for AsyncTun {
210
126
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
211
- f. debug_struct ( "Tun " )
127
+ f. debug_struct ( "AsyncTun " )
212
128
. field ( "name" , & self . name )
213
129
. field ( "handle" , & self . handle . 0 )
214
130
. finish ( )
@@ -227,9 +143,9 @@ const TUN_IOCTL_REGISTER_RINGS: u32 = CTL_CODE(
227
143
FILE_READ_DATA | FILE_WRITE_DATA ,
228
144
) ;
229
145
230
- impl Tun {
146
+ impl AsyncTun {
231
147
/// Open a handle to a wintun interface.
232
- pub fn open ( name : & OsStr ) -> anyhow:: Result < Tun > {
148
+ pub fn open ( name : & OsStr ) -> anyhow:: Result < AsyncTun > {
233
149
info ! ( "opening wintun device {}" , name. to_string_lossy( ) ) ;
234
150
let interface = WINTUN_POOL . get_interface ( name) ?;
235
151
if let Some ( interface) = interface {
@@ -251,41 +167,48 @@ impl Tun {
251
167
) )
252
168
. context ( "DeviceIoControl TUN_IOCTL_REGISTER_RINGS" ) ?;
253
169
254
- let cancel_event =
255
- unsafe_h ! ( CreateEventW ( null_mut( ) , 1 , 0 , null_mut( ) ) ) . context ( "CreateEventW" ) ?;
170
+ let send_tail_moved_clone = {
171
+ let mut handle: HANDLE = null_mut ( ) ;
172
+ let self_process = unsafe { GetCurrentProcess ( ) } ;
173
+ unsafe_b ! ( DuplicateHandle (
174
+ self_process,
175
+ rings. send. tail_moved. 0 ,
176
+ self_process,
177
+ & mut handle,
178
+ 0 ,
179
+ 0 ,
180
+ DUPLICATE_SAME_ACCESS ,
181
+ ) )
182
+ . context ( "DuplicateHandle" ) ?;
183
+ Arc :: new ( HandleWrapper ( handle) )
184
+ } ;
256
185
257
186
Ok ( Self {
258
187
handle,
259
188
name : name. into ( ) ,
260
189
rings,
261
- read_lock : Mutex :: new ( ( ) ) ,
190
+ send_tail_moved_clone,
191
+ read_lock : AsyncMutex :: new ( ( ) ) ,
262
192
write_lock : Mutex :: new ( ( ) ) ,
263
- cancel_event,
264
193
} )
265
194
}
266
195
267
196
/// Read a packet from the interface.
268
197
///
269
198
/// Blocking.
270
- pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
271
- let _read_lock_guard = self . read_lock . lock ( ) ;
272
- unsafe { self . rings . read ( buf, self . cancel_event . 0 ) }
199
+ pub async fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
200
+ let _read_lock_guard = self . read_lock . lock ( ) . await ;
201
+ unsafe { self . rings . read ( buf, & self . send_tail_moved_clone ) . await }
273
202
}
274
203
275
204
/// Write a packet to the interface.
276
205
///
277
206
/// Does not block.
278
- pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
207
+ pub async fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
279
208
let _write_lock_guard = self . write_lock . lock ( ) ;
280
209
unsafe { self . rings . write ( buf) }
281
210
}
282
211
283
- /// Interrupt a blocking read operation on this Tun interface.
284
- pub fn interrupt ( & self ) {
285
- debug ! ( "interrupt tun read" ) ;
286
- unsafe_b ! ( SetEvent ( self . cancel_event. 0 ) ) . unwrap ( ) ;
287
- }
288
-
289
212
fn close ( & self ) -> anyhow:: Result < ( ) > {
290
213
info ! ( "closing wintun interface" ) ;
291
214
let it = WINTUN_POOL
@@ -298,10 +221,7 @@ impl Tun {
298
221
}
299
222
}
300
223
301
- unsafe impl Sync for Tun { }
302
- unsafe impl Send for Tun { }
303
-
304
- impl Drop for Tun {
224
+ impl Drop for AsyncTun {
305
225
fn drop ( & mut self ) {
306
226
self . close ( )
307
227
. unwrap_or_else ( |e| warn ! ( "failed to close tun: {:#}" , e) )
@@ -321,7 +241,7 @@ mod tests {
321
241
#[ test]
322
242
fn test_open_and_close ( ) {
323
243
let _ = env_logger:: try_init ( ) ;
324
- let t = Tun :: open ( OsStr :: new ( "tun0" ) ) ;
244
+ let t = AsyncTun :: open ( OsStr :: new ( "tun0" ) ) ;
325
245
println ! ( "Tun::open(): {:?}" , t) ;
326
246
}
327
247
}
0 commit comments