11use bytes:: BytesMut ;
2+ use futures_channel:: { mpsc, oneshot} ;
3+ use futures_util:: { SinkExt , StreamExt , TryStreamExt } ;
24use js_sys:: { ArrayBuffer , Uint8Array } ;
5+ use rsocket_rust:: error:: RSocketError ;
36use rsocket_rust:: frame:: Frame ;
4- use rsocket_rust:: transport:: { BoxResult , ClientTransport , Rx , SafeFuture , Tx } ;
7+ use rsocket_rust:: transport:: { ClientTransport , Rx , Tx , TxOnce } ;
58use rsocket_rust:: utils:: Writeable ;
69use std:: cell:: RefCell ;
10+ use std:: future:: Future ;
11+ use std:: pin:: Pin ;
712use std:: rc:: Rc ;
813use wasm_bindgen:: prelude:: * ;
914use wasm_bindgen:: JsCast ;
10- use web_sys:: { ErrorEvent , FileReader , MessageEvent , ProgressEvent , WebSocket } ;
15+ use wasm_bindgen_futures:: spawn_local;
16+ use web_sys:: { ErrorEvent , Event , FileReader , MessageEvent , ProgressEvent , WebSocket } ;
1117
1218macro_rules! console_log {
1319 ( $( $t: tt) * ) => ( log( & format_args!( $( $t) * ) . to_string( ) ) )
@@ -23,46 +29,83 @@ pub struct WebsocketClientTransport {
2329 url : String ,
2430}
2531
32+ impl WebsocketClientTransport {
33+ #[ inline]
34+ fn wait_for_open ( ws : & WebSocket ) -> impl Future < Output = ( ) > {
35+ let ( sender, receiver) = oneshot:: channel ( ) ;
36+ // The Closure is only called once, so we can use Closure::once
37+ let on_open = Closure :: once ( move |_e : Event | {
38+ // We don't need to send a value, so we just send ()
39+ sender. send ( ( ) ) . unwrap ( ) ;
40+ } ) ;
41+ ws. set_onopen ( Some ( on_open. as_ref ( ) . unchecked_ref ( ) ) ) ;
42+ async move {
43+ // Wait for it to open
44+ receiver. await . unwrap ( ) ;
45+ // Clean up the Closure so we don't leak any memory
46+ drop ( on_open) ;
47+ }
48+ }
49+ }
50+
2651impl ClientTransport for WebsocketClientTransport {
27- fn attach ( self , incoming : Tx < Frame > , mut sending : Rx < Frame > ) -> SafeFuture < BoxResult < ( ) > > {
28- Box :: pin ( async move {
29- let sending = RefCell :: new ( sending) ;
30- // Connect to an echo server
31- let ws = WebSocket :: new ( & self . url ) . unwrap ( ) ;
32-
33- // on message
34- let on_message = Closure :: wrap ( Box :: new ( move |e : MessageEvent | {
35- let data: JsValue = e. data ( ) ;
36- read_binary ( data, incoming. clone ( ) ) ;
37- } ) as Box < dyn FnMut ( MessageEvent ) > ) ;
38- ws. set_onmessage ( Some ( on_message. as_ref ( ) . unchecked_ref ( ) ) ) ;
39- on_message. forget ( ) ;
40-
41- // on error
42- let on_error = Closure :: wrap ( Box :: new ( move |_e : ErrorEvent | {
43- // TODO: handle error
44- } ) as Box < dyn FnMut ( ErrorEvent ) > ) ;
45- ws. set_onerror ( Some ( on_error. as_ref ( ) . unchecked_ref ( ) ) ) ;
46- on_error. forget ( ) ;
47-
48- // on open
49- let cloned_ws = ws. clone ( ) ;
50- let on_open = Closure :: wrap ( Box :: new ( move |_| {
51- let mut sending = sending. borrow_mut ( ) ;
52- while let Ok ( Some ( f) ) = sending. try_next ( ) {
53- let mut bf = BytesMut :: new ( ) ;
54- f. write_to ( & mut bf) ;
55- let mut raw = bf. to_vec ( ) ;
56- cloned_ws. send_with_u8_array ( & mut raw[ ..] ) . unwrap ( ) ;
52+ fn attach (
53+ self ,
54+ incoming : Tx < Frame > ,
55+ mut sending : Rx < Frame > ,
56+ connected : Option < TxOnce < Result < ( ) , RSocketError > > > ,
57+ ) {
58+ spawn_local ( async move {
59+ match WebSocket :: new ( & self . url ) {
60+ Ok ( ws) => {
61+ // on message
62+ let on_message = Closure :: wrap ( Box :: new ( move |e : MessageEvent | {
63+ let data: JsValue = e. data ( ) ;
64+ read_binary ( data, incoming. clone ( ) ) ;
65+ } )
66+ as Box < dyn FnMut ( MessageEvent ) > ) ;
67+ ws. set_onmessage ( Some ( on_message. as_ref ( ) . unchecked_ref ( ) ) ) ;
68+ on_message. forget ( ) ;
69+
70+ // on error
71+ let on_error = Closure :: wrap ( Box :: new ( move |e : ErrorEvent | {
72+ console_log ! ( "websocket error: {}" , e. message( ) ) ;
73+ } )
74+ as Box < dyn FnMut ( ErrorEvent ) > ) ;
75+ ws. set_onerror ( Some ( on_error. as_ref ( ) . unchecked_ref ( ) ) ) ;
76+ on_error. forget ( ) ;
77+
78+ // on_close
79+ let on_close = Closure :: once ( Box :: new ( move |_e : Event | {
80+ console_log ! ( "websocket closed" ) ;
81+ } ) as Box < dyn FnMut ( Event ) > ) ;
82+ ws. set_onclose ( Some ( on_close. as_ref ( ) . unchecked_ref ( ) ) ) ;
83+ on_close. forget ( ) ;
84+
85+ Self :: wait_for_open ( & ws) . await ;
86+
87+ if let Some ( sender) = connected {
88+ sender. send ( Ok ( ( ) ) ) . unwrap ( ) ;
89+ }
90+
91+ while let Some ( v) = sending. next ( ) . await {
92+ let mut bf = BytesMut :: new ( ) ;
93+ v. write_to ( & mut bf) ;
94+ let mut raw = bf. to_vec ( ) ;
95+ ws. send_with_u8_array ( & mut raw[ ..] )
96+ . expect ( "write data into websocket failed." ) ;
97+ }
98+ console_log ! ( "***** attch end *****" ) ;
5799 }
58- } ) as Box < dyn FnMut ( JsValue ) > ) ;
59- ws. set_onopen ( Some ( on_open. as_ref ( ) . unchecked_ref ( ) ) ) ;
60- on_open. forget ( ) ;
61-
62- console_log ! ( "***** attch end *****" ) ;
63-
64- Ok ( ( ) )
65- } )
100+ Err ( e) => {
101+ if let Some ( sender) = connected {
102+ sender
103+ . send ( Err ( RSocketError :: from ( e. as_string ( ) . unwrap ( ) ) ) )
104+ . unwrap ( ) ;
105+ }
106+ }
107+ }
108+ } ) ;
66109 }
67110}
68111
0 commit comments