3
3
//! This module contains the definition of the raw client that wraps the transport method
4
4
5
5
use std:: borrow:: Borrow ;
6
- use std:: collections:: { BTreeMap , BTreeSet , HashMap , VecDeque } ;
6
+ use std:: collections:: { BTreeMap , HashMap , VecDeque } ;
7
7
use std:: io:: { BufRead , BufReader , Read , Write } ;
8
8
use std:: mem:: drop;
9
9
use std:: net:: { TcpStream , ToSocketAddrs } ;
@@ -539,11 +539,10 @@ impl<S: Read + Write> RawClient<S> {
539
539
540
540
if let Some ( until_message) = until_message {
541
541
// 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.
547
546
if self . waiting_map . lock ( ) ?. get ( & until_message) . is_none ( ) {
548
547
return Err ( Error :: CouldntLockReader ) ;
549
548
}
@@ -762,22 +761,23 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
762
761
fn batch_call ( & self , batch : & Batch ) -> Result < Vec < serde_json:: Value > , Error > {
763
762
let mut raw = Vec :: new ( ) ;
764
763
765
- let mut missing_responses = BTreeSet :: new ( ) ;
764
+ let mut missing_responses = Vec :: new ( ) ;
766
765
let mut answers = BTreeMap :: new ( ) ;
767
766
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
771
768
772
769
for ( method, params) in batch. iter ( ) {
773
770
let req = Request :: new_id (
774
771
self . last_id . fetch_add ( 1 , Ordering :: SeqCst ) ,
775
772
method,
776
773
params. to_vec ( ) ,
777
774
) ;
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) ) ;
779
779
780
- self . waiting_map . lock ( ) ?. insert ( req. id , sender. clone ( ) ) ;
780
+ self . waiting_map . lock ( ) ?. insert ( req. id , sender) ;
781
781
782
782
raw. append ( & mut serde_json:: to_vec ( & req) ?) ;
783
783
raw. extend_from_slice ( b"\n " ) ;
@@ -796,16 +796,16 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
796
796
797
797
self . increment_calls ( ) ;
798
798
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) {
801
801
Ok ( mut resp) => answers. insert ( req_id, resp[ "result" ] . take ( ) ) ,
802
802
Err ( e) => {
803
803
// In case of error our sender could still be left in the map, depending on where
804
804
// the error happened. Just in case, try to remove it here
805
805
warn ! ( "got error for req_id {}: {:?}" , req_id, e) ;
806
806
warn ! ( "removing all waiting req of this batch" ) ;
807
807
let mut guard = self . waiting_map . lock ( ) ?;
808
- for req_id in missing_responses. iter ( ) {
808
+ for ( req_id, _ ) in missing_responses. iter ( ) {
809
809
guard. remove ( req_id) ;
810
810
}
811
811
return Err ( e) ;
0 commit comments