33//! This module contains the definition of the raw client that wraps the transport method
44
55use std:: borrow:: Borrow ;
6- use std:: collections:: { BTreeMap , BTreeSet , HashMap , VecDeque } ;
6+ use std:: collections:: { BTreeMap , HashMap , VecDeque } ;
77use std:: io:: { BufRead , BufReader , Read , Write } ;
88use std:: mem:: drop;
99use std:: net:: { TcpStream , ToSocketAddrs } ;
@@ -539,11 +539,10 @@ impl<S: Read + Write> RawClient<S> {
539539
540540 if let Some ( until_message) = until_message {
541541 // If we are trying to start a reader thread but the corresponding sender is
542- // missing from the map, exit immediately. This can happen with batch calls,
543- // since the sender is shared for all the individual queries in a call. We
544- // might have already received a response for that id, but we don't know it
545- // yet. Exiting here forces the calling code to fallback to the sender-receiver
546- // method, and it should find a message there waiting for it.
542+ // missing from the map, exit immediately. We might have already received a
543+ // response for that id, but we don't know it yet. Exiting here forces the
544+ // calling code to fallback to the sender-receiver method, and it should find
545+ // a message there waiting for it.
547546 if self . waiting_map . lock ( ) ?. get ( & until_message) . is_none ( ) {
548547 return Err ( Error :: CouldntLockReader ) ;
549548 }
@@ -762,22 +761,23 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
762761 fn batch_call ( & self , batch : & Batch ) -> Result < Vec < serde_json:: Value > , Error > {
763762 let mut raw = Vec :: new ( ) ;
764763
765- let mut missing_responses = BTreeSet :: new ( ) ;
764+ let mut missing_responses = Vec :: new ( ) ;
766765 let mut answers = BTreeMap :: new ( ) ;
767766
768- // Add our listener to the map before we send the request, Here we will clone the sender
769- // for every request id, so that we only have to monitor one receiver.
770- let ( sender, receiver) = channel ( ) ;
767+ // Add our listener to the map before we send the request
771768
772769 for ( method, params) in batch. iter ( ) {
773770 let req = Request :: new_id (
774771 self . last_id . fetch_add ( 1 , Ordering :: SeqCst ) ,
775772 method,
776773 params. to_vec ( ) ,
777774 ) ;
778- missing_responses. insert ( req. id ) ;
775+ // Add distinct channel to each request so when we remove our request id (and sender) from the waiting_map
776+ // we can be sure that the response gets sent to the correct channel in self.recv
777+ let ( sender, receiver) = channel ( ) ;
778+ missing_responses. push ( ( req. id , receiver) ) ;
779779
780- self . waiting_map . lock ( ) ?. insert ( req. id , sender. clone ( ) ) ;
780+ self . waiting_map . lock ( ) ?. insert ( req. id , sender) ;
781781
782782 raw. append ( & mut serde_json:: to_vec ( & req) ?) ;
783783 raw. extend_from_slice ( b"\n " ) ;
@@ -796,16 +796,16 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
796796
797797 self . increment_calls ( ) ;
798798
799- for req_id in missing_responses. iter ( ) {
800- match self . recv ( & receiver, * req_id) {
799+ for ( req_id, receiver ) in missing_responses. iter ( ) {
800+ match self . recv ( receiver, * req_id) {
801801 Ok ( mut resp) => answers. insert ( req_id, resp[ "result" ] . take ( ) ) ,
802802 Err ( e) => {
803803 // In case of error our sender could still be left in the map, depending on where
804804 // the error happened. Just in case, try to remove it here
805805 warn ! ( "got error for req_id {}: {:?}" , req_id, e) ;
806806 warn ! ( "removing all waiting req of this batch" ) ;
807807 let mut guard = self . waiting_map . lock ( ) ?;
808- for req_id in missing_responses. iter ( ) {
808+ for ( req_id, _ ) in missing_responses. iter ( ) {
809809 guard. remove ( req_id) ;
810810 }
811811 return Err ( e) ;
0 commit comments