@@ -28,6 +28,10 @@ use std::pin::Pin;
2828use std:: task:: { Context , Poll } ;
2929use tokio:: io:: { AsyncRead , AsyncWrite , ReadBuf } ;
3030
31+ mod bridge;
32+
33+ use self :: bridge:: AsyncStreamBridge ;
34+
3135/// Asynchronously performs a client-side TLS handshake over the provided stream.
3236pub fn connect < S > (
3337 config : ConnectConfiguration ,
@@ -49,91 +53,15 @@ where
4953}
5054
5155fn handshake < S > (
52- f : impl FnOnce ( StreamWrapper < S > ) -> Result < MidHandshakeSslStream < StreamWrapper < S > > , ErrorStack > ,
56+ f : impl FnOnce (
57+ AsyncStreamBridge < S > ,
58+ ) -> Result < MidHandshakeSslStream < AsyncStreamBridge < S > > , ErrorStack > ,
5359 stream : S ,
5460) -> Result < HandshakeFuture < S > , ErrorStack >
5561where
5662 S : AsyncRead + AsyncWrite + Unpin ,
5763{
58- let ongoing_handshake = Some ( f ( StreamWrapper { stream, context : 0 } ) ?) ;
59-
60- Ok ( HandshakeFuture ( ongoing_handshake) )
61- }
62-
63- struct StreamWrapper < S > {
64- stream : S ,
65- context : usize ,
66- }
67-
68- impl < S > StreamWrapper < S > {
69- /// # Safety
70- ///
71- /// Must be called with `context` set to a valid pointer to a live `Context` object, and the
72- /// wrapper must be pinned in memory.
73- unsafe fn parts ( & mut self ) -> ( Pin < & mut S > , & mut Context < ' _ > ) {
74- debug_assert_ne ! ( self . context, 0 ) ;
75- let stream = Pin :: new_unchecked ( & mut self . stream ) ;
76- let context = & mut * ( self . context as * mut _ ) ;
77- ( stream, context)
78- }
79- }
80-
81- impl < S > fmt:: Debug for StreamWrapper < S >
82- where
83- S : fmt:: Debug ,
84- {
85- fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
86- fmt:: Debug :: fmt ( & self . stream , fmt)
87- }
88- }
89-
90- impl < S > StreamWrapper < S >
91- where
92- S : Unpin ,
93- {
94- fn with_context < F , R > ( & mut self , f : F ) -> R
95- where
96- F : FnOnce ( & mut Context < ' _ > , Pin < & mut S > ) -> R ,
97- {
98- unsafe {
99- assert_ne ! ( self . context, 0 ) ;
100- let waker = & mut * ( self . context as * mut _ ) ;
101- f ( waker, Pin :: new ( & mut self . stream ) )
102- }
103- }
104- }
105-
106- impl < S > Read for StreamWrapper < S >
107- where
108- S : AsyncRead + Unpin ,
109- {
110- fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
111- let ( stream, cx) = unsafe { self . parts ( ) } ;
112- let mut buf = ReadBuf :: new ( buf) ;
113- match stream. poll_read ( cx, & mut buf) ? {
114- Poll :: Ready ( ( ) ) => Ok ( buf. filled ( ) . len ( ) ) ,
115- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
116- }
117- }
118- }
119-
120- impl < S > Write for StreamWrapper < S >
121- where
122- S : AsyncWrite + Unpin ,
123- {
124- fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
125- match self . with_context ( |ctx, stream| stream. poll_write ( ctx, buf) ) {
126- Poll :: Ready ( r) => r,
127- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
128- }
129- }
130-
131- fn flush ( & mut self ) -> io:: Result < ( ) > {
132- match self . with_context ( |ctx, stream| stream. poll_flush ( ctx) ) {
133- Poll :: Ready ( r) => r,
134- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
135- }
136- }
64+ Ok ( HandshakeFuture ( Some ( f ( AsyncStreamBridge :: new ( stream) ) ?) ) )
13765}
13866
13967fn cvt < T > ( r : io:: Result < T > ) -> Poll < io:: Result < T > > {
@@ -152,7 +80,7 @@ fn cvt<T>(r: io::Result<T>) -> Poll<io::Result<T>> {
15280/// data. Bytes read from a `SslStream` are decrypted from `S` and bytes written
15381/// to a `SslStream` are encrypted when passing through to `S`.
15482#[ derive( Debug ) ]
155- pub struct SslStream < S > ( ssl:: SslStream < StreamWrapper < S > > ) ;
83+ pub struct SslStream < S > ( ssl:: SslStream < AsyncStreamBridge < S > > ) ;
15684
15785impl < S > SslStream < S > {
15886 /// Returns a shared reference to the `Ssl` object associated with this stream.
@@ -170,14 +98,21 @@ impl<S> SslStream<S> {
17098 & mut self . 0 . get_mut ( ) . stream
17199 }
172100
173- fn with_context < F , R > ( & mut self , ctx : & mut Context < ' _ > , f : F ) -> R
101+ fn run_in_context < F , R > ( & mut self , ctx : & mut Context < ' _ > , f : F ) -> R
174102 where
175- F : FnOnce ( & mut ssl:: SslStream < StreamWrapper < S > > ) -> R ,
103+ F : FnOnce ( & mut ssl:: SslStream < AsyncStreamBridge < S > > ) -> R ,
176104 {
177- self . 0 . get_mut ( ) . context = ctx as * mut _ as usize ;
178- let r = f ( & mut self . 0 ) ;
179- self . 0 . get_mut ( ) . context = 0 ;
180- r
105+ self . 0 . get_mut ( ) . set_waker ( Some ( ctx) ) ;
106+
107+ let result = f ( & mut self . 0 ) ;
108+
109+ // NOTE(nox): This should also be executed when `f` panics,
110+ // but it's not that important as boring segfaults on panics
111+ // and we always set the context prior to doing anything with
112+ // the inner async stream.
113+ self . 0 . get_mut ( ) . set_waker ( None ) ;
114+
115+ result
181116 }
182117}
183118
@@ -193,8 +128,10 @@ where
193128 ///
194129 /// The caller must ensure the pointer is valid.
195130 pub unsafe fn from_raw_parts ( ssl : * mut ffi:: SSL , stream : S ) -> Self {
196- let stream = StreamWrapper { stream, context : 0 } ;
197- SslStream ( ssl:: SslStream :: from_raw_parts ( ssl, stream) )
131+ Self ( ssl:: SslStream :: from_raw_parts (
132+ ssl,
133+ AsyncStreamBridge :: new ( stream) ,
134+ ) )
198135 }
199136}
200137
@@ -207,7 +144,7 @@ where
207144 ctx : & mut Context < ' _ > ,
208145 buf : & mut ReadBuf ,
209146 ) -> Poll < io:: Result < ( ) > > {
210- self . with_context ( ctx, |s| {
147+ self . run_in_context ( ctx, |s| {
211148 // This isn't really "proper", but rust-openssl doesn't currently expose a suitable interface even though
212149 // OpenSSL itself doesn't require the buffer to be initialized. So this is good enough for now.
213150 let slice = unsafe {
@@ -237,15 +174,15 @@ where
237174 ctx : & mut Context ,
238175 buf : & [ u8 ] ,
239176 ) -> Poll < io:: Result < usize > > {
240- self . with_context ( ctx, |s| cvt ( s. write ( buf) ) )
177+ self . run_in_context ( ctx, |s| cvt ( s. write ( buf) ) )
241178 }
242179
243180 fn poll_flush ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < io:: Result < ( ) > > {
244- self . with_context ( ctx, |s| cvt ( s. flush ( ) ) )
181+ self . run_in_context ( ctx, |s| cvt ( s. flush ( ) ) )
245182 }
246183
247184 fn poll_shutdown ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < io:: Result < ( ) > > {
248- match self . with_context ( ctx, |s| s. shutdown ( ) ) {
185+ match self . run_in_context ( ctx, |s| s. shutdown ( ) ) {
249186 Ok ( ShutdownResult :: Sent ) | Ok ( ShutdownResult :: Received ) => { }
250187 Err ( ref e) if e. code ( ) == ErrorCode :: ZERO_RETURN => { }
251188 Err ( ref e) if e. code ( ) == ErrorCode :: WANT_READ || e. code ( ) == ErrorCode :: WANT_WRITE => {
@@ -263,7 +200,7 @@ where
263200}
264201
265202/// The error type returned after a failed handshake.
266- pub struct HandshakeError < S > ( MidHandshakeSslStream < StreamWrapper < S > > ) ;
203+ pub struct HandshakeError < S > ( MidHandshakeSslStream < AsyncStreamBridge < S > > ) ;
267204
268205impl < S > HandshakeError < S > {
269206 /// Returns a shared reference to the `Ssl` object associated with this error.
@@ -332,33 +269,36 @@ where
332269/// Future for an ongoing TLS handshake.
333270///
334271/// See [`connect`] and [`accept`].
335- pub struct HandshakeFuture < S > ( Option < MidHandshakeSslStream < StreamWrapper < S > > > ) ;
272+ pub struct HandshakeFuture < S > ( Option < MidHandshakeSslStream < AsyncStreamBridge < S > > > ) ;
336273
337274impl < S > Future for HandshakeFuture < S >
338275where
339276 S : AsyncRead + AsyncWrite + Unpin ,
340277{
341278 type Output = Result < SslStream < S > , HandshakeError < S > > ;
342279
343- fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
344- let mut s = self . 0 . take ( ) . expect ( "future polled after completion" ) ;
280+ fn poll ( mut self : Pin < & mut Self > , ctx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
281+ let mut mid_handshake = self . 0 . take ( ) . expect ( "future polled after completion" ) ;
345282
346- s . get_mut ( ) . context = cx as * mut _ as usize ;
283+ mid_handshake . get_mut ( ) . set_waker ( Some ( ctx ) ) ;
347284
348- match s . handshake ( ) {
349- Ok ( mut s ) => {
350- s . get_mut ( ) . context = 0 ;
285+ match mid_handshake . handshake ( ) {
286+ Ok ( mut stream ) => {
287+ stream . get_mut ( ) . set_waker ( None ) ;
351288
352- Poll :: Ready ( Ok ( SslStream ( s ) ) )
289+ Poll :: Ready ( Ok ( SslStream ( stream ) ) )
353290 }
354- Err ( mut handshake ) if handshake . error ( ) . would_block ( ) => {
355- handshake . get_mut ( ) . context = 0 ;
291+ Err ( mut mid_handshake ) => {
292+ mid_handshake . get_mut ( ) . set_waker ( None ) ;
356293
357- self . 0 = Some ( handshake) ;
294+ if mid_handshake. error ( ) . would_block ( ) {
295+ self . 0 = Some ( mid_handshake) ;
358296
359- Poll :: Pending
297+ Poll :: Pending
298+ } else {
299+ Poll :: Ready ( Err ( HandshakeError ( mid_handshake) ) )
300+ }
360301 }
361- Err ( e) => Poll :: Ready ( Err ( HandshakeError ( e) ) ) ,
362302 }
363303 }
364304}
0 commit comments