@@ -27,6 +27,10 @@ use std::pin::Pin;
2727use std:: task:: { Context , Poll } ;
2828use tokio:: io:: { AsyncRead , AsyncWrite , ReadBuf } ;
2929
30+ mod bridge;
31+
32+ use self :: bridge:: AsyncStreamBridge ;
33+
3034/// Asynchronously performs a client-side TLS handshake over the provided stream.
3135pub async fn connect < S > (
3236 config : ConnectConfiguration ,
@@ -48,94 +52,18 @@ where
4852}
4953
5054async fn handshake < S > (
51- f : impl FnOnce ( StreamWrapper < S > ) -> Result < MidHandshakeSslStream < StreamWrapper < S > > , ErrorStack > ,
55+ f : impl FnOnce (
56+ AsyncStreamBridge < S > ,
57+ ) -> Result < MidHandshakeSslStream < AsyncStreamBridge < S > > , ErrorStack > ,
5258 stream : S ,
5359) -> Result < SslStream < S > , HandshakeError < S > >
5460where
5561 S : AsyncRead + AsyncWrite + Unpin ,
5662{
57- let ongoing_handshake = Some (
58- f ( StreamWrapper { stream, context : 0 } )
59- . map_err ( |err| HandshakeError ( ssl:: HandshakeError :: SetupFailure ( err) ) ) ?,
60- ) ;
61-
62- HandshakeFuture ( ongoing_handshake) . await
63- }
64-
65- struct StreamWrapper < S > {
66- stream : S ,
67- context : usize ,
68- }
69-
70- impl < S > StreamWrapper < S > {
71- /// # Safety
72- ///
73- /// Must be called with `context` set to a valid pointer to a live `Context` object, and the
74- /// wrapper must be pinned in memory.
75- unsafe fn parts ( & mut self ) -> ( Pin < & mut S > , & mut Context < ' _ > ) {
76- debug_assert_ne ! ( self . context, 0 ) ;
77- let stream = Pin :: new_unchecked ( & mut self . stream ) ;
78- let context = & mut * ( self . context as * mut _ ) ;
79- ( stream, context)
80- }
81- }
82-
83- impl < S > fmt:: Debug for StreamWrapper < S >
84- where
85- S : fmt:: Debug ,
86- {
87- fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
88- fmt:: Debug :: fmt ( & self . stream , fmt)
89- }
90- }
91-
92- impl < S > StreamWrapper < S >
93- where
94- S : Unpin ,
95- {
96- fn with_context < F , R > ( & mut self , f : F ) -> R
97- where
98- F : FnOnce ( & mut Context < ' _ > , Pin < & mut S > ) -> R ,
99- {
100- unsafe {
101- assert_ne ! ( self . context, 0 ) ;
102- let waker = & mut * ( self . context as * mut _ ) ;
103- f ( waker, Pin :: new ( & mut self . stream ) )
104- }
105- }
106- }
107-
108- impl < S > Read for StreamWrapper < S >
109- where
110- S : AsyncRead + Unpin ,
111- {
112- fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
113- let ( stream, cx) = unsafe { self . parts ( ) } ;
114- let mut buf = ReadBuf :: new ( buf) ;
115- match stream. poll_read ( cx, & mut buf) ? {
116- Poll :: Ready ( ( ) ) => Ok ( buf. filled ( ) . len ( ) ) ,
117- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
118- }
119- }
120- }
63+ let mid_handshake = f ( AsyncStreamBridge :: new ( stream) )
64+ . map_err ( |err| HandshakeError ( ssl:: HandshakeError :: SetupFailure ( err) ) ) ?;
12165
122- impl < S > Write for StreamWrapper < S >
123- where
124- S : AsyncWrite + Unpin ,
125- {
126- fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
127- match self . with_context ( |ctx, stream| stream. poll_write ( ctx, buf) ) {
128- Poll :: Ready ( r) => r,
129- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
130- }
131- }
132-
133- fn flush ( & mut self ) -> io:: Result < ( ) > {
134- match self . with_context ( |ctx, stream| stream. poll_flush ( ctx) ) {
135- Poll :: Ready ( r) => r,
136- Poll :: Pending => Err ( io:: Error :: from ( io:: ErrorKind :: WouldBlock ) ) ,
137- }
138- }
66+ HandshakeFuture ( Some ( mid_handshake) ) . await
13967}
14068
14169fn cvt < T > ( r : io:: Result < T > ) -> Poll < io:: Result < T > > {
@@ -154,7 +82,7 @@ fn cvt<T>(r: io::Result<T>) -> Poll<io::Result<T>> {
15482/// data. Bytes read from a `SslStream` are decrypted from `S` and bytes written
15583/// to a `SslStream` are encrypted when passing through to `S`.
15684#[ derive( Debug ) ]
157- pub struct SslStream < S > ( ssl:: SslStream < StreamWrapper < S > > ) ;
85+ pub struct SslStream < S > ( ssl:: SslStream < AsyncStreamBridge < S > > ) ;
15886
15987impl < S > SslStream < S > {
16088 /// Returns a shared reference to the `Ssl` object associated with this stream.
@@ -172,14 +100,21 @@ impl<S> SslStream<S> {
172100 & mut self . 0 . get_mut ( ) . stream
173101 }
174102
175- fn with_context < F , R > ( & mut self , ctx : & mut Context < ' _ > , f : F ) -> R
103+ fn run_in_context < F , R > ( & mut self , ctx : & mut Context < ' _ > , f : F ) -> R
176104 where
177- F : FnOnce ( & mut ssl:: SslStream < StreamWrapper < S > > ) -> R ,
105+ F : FnOnce ( & mut ssl:: SslStream < AsyncStreamBridge < S > > ) -> R ,
178106 {
179- self . 0 . get_mut ( ) . context = ctx as * mut _ as usize ;
180- let r = f ( & mut self . 0 ) ;
181- self . 0 . get_mut ( ) . context = 0 ;
182- r
107+ self . 0 . get_mut ( ) . set_waker ( Some ( ctx) ) ;
108+
109+ let result = f ( & mut self . 0 ) ;
110+
111+ // NOTE(nox): This should also be executed when `f` panics,
112+ // but it's not that important as boring segfaults on panics
113+ // and we always set the context prior to doing anything with
114+ // the inner async stream.
115+ self . 0 . get_mut ( ) . set_waker ( None ) ;
116+
117+ result
183118 }
184119}
185120
@@ -195,8 +130,10 @@ where
195130 ///
196131 /// The caller must ensure the pointer is valid.
197132 pub unsafe fn from_raw_parts ( ssl : * mut ffi:: SSL , stream : S ) -> Self {
198- let stream = StreamWrapper { stream, context : 0 } ;
199- SslStream ( ssl:: SslStream :: from_raw_parts ( ssl, stream) )
133+ Self ( ssl:: SslStream :: from_raw_parts (
134+ ssl,
135+ AsyncStreamBridge :: new ( stream) ,
136+ ) )
200137 }
201138}
202139
@@ -209,7 +146,7 @@ where
209146 ctx : & mut Context < ' _ > ,
210147 buf : & mut ReadBuf ,
211148 ) -> Poll < io:: Result < ( ) > > {
212- self . with_context ( ctx, |s| {
149+ self . run_in_context ( ctx, |s| {
213150 // This isn't really "proper", but rust-openssl doesn't currently expose a suitable interface even though
214151 // OpenSSL itself doesn't require the buffer to be initialized. So this is good enough for now.
215152 let slice = unsafe {
@@ -239,15 +176,15 @@ where
239176 ctx : & mut Context ,
240177 buf : & [ u8 ] ,
241178 ) -> Poll < io:: Result < usize > > {
242- self . with_context ( ctx, |s| cvt ( s. write ( buf) ) )
179+ self . run_in_context ( ctx, |s| cvt ( s. write ( buf) ) )
243180 }
244181
245182 fn poll_flush ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < io:: Result < ( ) > > {
246- self . with_context ( ctx, |s| cvt ( s. flush ( ) ) )
183+ self . run_in_context ( ctx, |s| cvt ( s. flush ( ) ) )
247184 }
248185
249186 fn poll_shutdown ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < io:: Result < ( ) > > {
250- match self . with_context ( ctx, |s| s. shutdown ( ) ) {
187+ match self . run_in_context ( ctx, |s| s. shutdown ( ) ) {
251188 Ok ( ShutdownResult :: Sent ) | Ok ( ShutdownResult :: Received ) => { }
252189 Err ( ref e) if e. code ( ) == ErrorCode :: ZERO_RETURN => { }
253190 Err ( ref e) if e. code ( ) == ErrorCode :: WANT_READ || e. code ( ) == ErrorCode :: WANT_WRITE => {
@@ -265,7 +202,7 @@ where
265202}
266203
267204/// The error type returned after a failed handshake.
268- pub struct HandshakeError < S > ( ssl:: HandshakeError < StreamWrapper < S > > ) ;
205+ pub struct HandshakeError < S > ( ssl:: HandshakeError < AsyncStreamBridge < S > > ) ;
269206
270207impl < S > HandshakeError < S > {
271208 /// Returns a shared reference to the `Ssl` object associated with this error.
@@ -333,33 +270,43 @@ where
333270 }
334271}
335272
336- struct HandshakeFuture < S > ( Option < MidHandshakeSslStream < StreamWrapper < S > > > ) ;
273+ /// Future for an ongoing TLS handshake.
274+ ///
275+ /// See [`connect`] and [`accept`].
276+ pub struct HandshakeFuture < S > ( Option < MidHandshakeSslStream < AsyncStreamBridge < S > > > ) ;
337277
338278impl < S > Future for HandshakeFuture < S >
339279where
340280 S : AsyncRead + AsyncWrite + Unpin ,
341281{
342282 type Output = Result < SslStream < S > , HandshakeError < S > > ;
343283
344- fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
345- let mut s = self . 0 . take ( ) . expect ( "future polled after completion" ) ;
284+ fn poll ( mut self : Pin < & mut Self > , ctx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
285+ let mut mid_handshake = self . 0 . take ( ) . expect ( "future polled after completion" ) ;
346286
347- s . get_mut ( ) . context = cx as * mut _ as usize ;
287+ mid_handshake . get_mut ( ) . set_waker ( Some ( ctx ) ) ;
348288
349- match s . handshake ( ) {
350- Ok ( mut s ) => {
351- s . get_mut ( ) . context = 0 ;
289+ match mid_handshake . handshake ( ) {
290+ Ok ( mut stream ) => {
291+ stream . get_mut ( ) . set_waker ( None ) ;
352292
353- Poll :: Ready ( Ok ( SslStream ( s ) ) )
293+ Poll :: Ready ( Ok ( SslStream ( stream ) ) )
354294 }
355- Err ( ssl:: HandshakeError :: WouldBlock ( mut s ) ) => {
356- s . get_mut ( ) . context = 0 ;
295+ Err ( ssl:: HandshakeError :: WouldBlock ( mut mid_handshake ) ) => {
296+ mid_handshake . get_mut ( ) . set_waker ( None ) ;
357297
358- self . 0 = Some ( s ) ;
298+ self . 0 = Some ( mid_handshake ) ;
359299
360300 Poll :: Pending
361301 }
362- Err ( e) => Poll :: Ready ( Err ( HandshakeError ( e) ) ) ,
302+ Err ( ssl:: HandshakeError :: Failure ( mut mid_handshake) ) => {
303+ mid_handshake. get_mut ( ) . set_waker ( None ) ;
304+
305+ Poll :: Ready ( Err ( HandshakeError ( ssl:: HandshakeError :: Failure (
306+ mid_handshake,
307+ ) ) ) )
308+ }
309+ Err ( err @ ssl:: HandshakeError :: SetupFailure ( _) ) => Poll :: Ready ( Err ( HandshakeError ( err) ) ) ,
363310 }
364311 }
365312}
0 commit comments