3232 // headers and must be at least 50ms.
3333 DefaultSendErrorBackoff = time .Second
3434
35+ // how many errors we tolerate before we give up making requests for a
36+ // block, when the error is client-side: 404, 401 etc. It makes no
37+ // sense to retry such requests, therefore 1.
3538 defaultMaxClientErrors = 1
3639)
3740
@@ -114,6 +117,10 @@ func (sender *httpMsgSender) sortURLS() {
114117func (sender * httpMsgSender ) bestURL () (* senderURL , error ) {
115118 sender .sortURLS ()
116119 first := sender .urls [0 ]
120+
121+ // A nil URL and no error signals that we don't need to abort, but
122+ // cannot keep retrying the same. client errors will be reset for next
123+ // block in the wantlist.
117124 if first .clientErrors >= defaultMaxClientErrors {
118125 return nil , nil
119126 }
@@ -126,6 +133,7 @@ func (sender *httpMsgSender) bestURL() (*senderURL, error) {
126133}
127134
128135// resetClientErrors sets all clientErrors on urls to 0.
136+ // It is called every time we move to the next item in a wantlist.
129137func (sender * httpMsgSender ) resetClientErrors () {
130138 for i := range sender .urls {
131139 sender .urls [i ].clientErrors = 0
@@ -188,7 +196,7 @@ func (sender *httpMsgSender) tryURL(ctx context.Context, u *senderURL, entry bsm
188196
189197 ctx , cancel := context .WithTimeout (ctx , sender .opts .SendTimeout )
190198 defer cancel ()
191- req , err := sender .ht .buildRequest (ctx , sender . peer , u .ParsedURL , method , entry .Cid .String ())
199+ req , err := sender .ht .buildRequest (ctx , u .ParsedURL , method , entry .Cid .String ())
192200 if err != nil {
193201 return & senderError {
194202 Type : typeFatal ,
@@ -223,10 +231,6 @@ func (sender *httpMsgSender) tryURL(ctx context.Context, u *senderURL, entry bsm
223231 return serr
224232 }
225233
226- if resp .Proto != "HTTP/2.0" {
227- log .Warnf ("%s://%q is not using HTTP/2 (%s)" , req .URL .Scheme , req .URL .Host , resp .Proto )
228- }
229-
230234 limReader := & io.LimitedReader {
231235 R : resp .Body ,
232236 N : sender .ht .maxBlockSize ,
@@ -301,7 +305,7 @@ func (sender *httpMsgSender) tryURL(ctx context.Context, u *senderURL, entry bsm
301305 return nil
302306 case http .StatusTooManyRequests ,
303307 http .StatusServiceUnavailable :
304- err := fmt .Errorf ("%q -> %d: %s " , req .URL , resp .StatusCode , string (body ))
308+ err := fmt .Errorf ("%q -> %d: %q " , req .URL , resp .StatusCode , string (body ))
305309 log .Error (err )
306310 retryAfter := resp .Header .Get ("Retry-After" )
307311 cooldownUntil , ok := parseRetryAfter (retryAfter )
@@ -320,7 +324,7 @@ func (sender *httpMsgSender) tryURL(ctx context.Context, u *senderURL, entry bsm
320324 // Tolerance for server errors per url is low. If after waiting etc.
321325 // it fails MaxRetries, we will fully disconnect.
322326 default :
323- err := fmt .Errorf ("%q -> %d: %s " , req .URL , resp .StatusCode , string (body ))
327+ err := fmt .Errorf ("%q -> %d: %q " , req .URL , resp .StatusCode , string (body ))
324328 log .Error (err )
325329 sender .ht .cooldownTracker .setByDuration (req .URL .Host , sender .opts .SendErrorBackoff )
326330 return & senderError {
@@ -376,11 +380,17 @@ func (sender *httpMsgSender) SendMsg(ctx context.Context, msg bsmsg.BitSwapMessa
376380 // This allows us to react when cancels arrive to wantlists
377381 // that we are going through.
378382 entryCtxs := make ([]context.Context , len (wantlist ))
383+ entryCancels := make ([]context.CancelFunc , len (wantlist ))
384+ nop := func () {}
379385 for i , entry := range wantlist {
380386 if entry .Cancel {
381387 entryCtxs [i ] = ctx
388+ entryCancels [i ] = nop
382389 }
383- entryCtxs [i ] = sender .ht .requestTracker .requestContext (ctx , entry .Cid )
390+ // The TTL here is just for auto-cleaning the request context
391+ // from the request tracker. It is set in a way that ensure that the request
392+ // has run
393+ entryCtxs [i ], entryCancels [i ] = sender .ht .requestTracker .requestContext (ctx , entry .Cid )
384394 }
385395
386396WANTLIST_LOOP:
@@ -399,8 +409,12 @@ WANTLIST_LOOP:
399409 // we disconnect this peer
400410 // and avoid it for the time being.
401411 if err != nil {
402- defer sender .ht .DisconnectFrom (ctx , sender .peer )
403- break WANTLIST_LOOP
412+ // notify new blocks before disconnecting. As
413+ // disconnecting may trigger cleanups or
414+ // something.
415+ sender .notifyReceivers (bsresp )
416+ sender .ht .DisconnectFrom (ctx , sender .peer )
417+ return nil
404418 }
405419
406420 // we move to next block, no good urls
@@ -452,44 +466,45 @@ WANTLIST_LOOP:
452466 sender .resetClientErrors ()
453467 }
454468
455- lb := len (bsresp .Blocks ())
456- lh := len (bsresp .Haves ())
457- ldh := len (bsresp .DontHaves ())
458- if lb + lh + ldh > 0 {
459- // send what we got ReceiveMessage and return
460- go func (receivers []network.Receiver , p peer.ID , msg bsmsg.BitSwapMessage ) {
461- // TODO: do not hang if closing
462- for i , recv := range receivers {
463- log .Debugf ("ReceiveMessage from %s#%d. Blocks: %d. Haves: %d" , p , i , lb , lh )
464- recv .ReceiveMessage (
465- context .Background (), // todo: which context?
466- p ,
467- msg ,
468- )
469- }
470- }(sender .ht .receivers , sender .peer , bsresp )
471- } else {
472- // If we did not manage to obtain anything, log errors
473- sendErrors (err )
469+ // clean up request tracker
470+ for _ , cancel := range entryCancels {
471+ cancel ()
474472 }
473+ sender .ht .requestTracker .cleanEmptyRequests (wantlist )
474+
475+ go sender .notifyReceivers (bsresp )
476+ // This just logs errors apparently.
477+ sendErrors (err )
475478
476479 // We never return error. Whatever happened, we will be cooling down
477480 // urls etc. but we don't need to disconnect or report that "peer is
478- // down" for the moment.
479- // TODO: improve logic?
481+ // down" for the moment, as we disconnect manually on error.
480482 return nil
481483}
482484
483- // Close closes the message sender, aborting any ongoing operations.
484- func (sender * httpMsgSender ) Close () error {
485- sender .closeOnce .Do (func () {
486- close (sender .closing )
487- })
488- return nil
485+ func (sender * httpMsgSender ) notifyReceivers (bsresp bsmsg.BitSwapMessage ) {
486+ lb := len (bsresp .Blocks ())
487+ lh := len (bsresp .Haves ())
488+ ldh := len (bsresp .DontHaves ())
489+ if lb + lh + ldh == 0 { // nothing to do
490+ return
491+ }
492+
493+ for i , recv := range sender .ht .receivers {
494+ log .Debugf ("ReceiveMessage from %s#%d. Blocks: %d. Haves: %d" , sender .peer , i , lb , lh )
495+ recv .ReceiveMessage (
496+ context .Background (), // todo: which context?
497+ sender .peer ,
498+ bsresp ,
499+ )
500+ }
489501}
490502
491503// Reset resets the sender (currently noop)
492504func (sender * httpMsgSender ) Reset () error {
505+ sender .closeOnce .Do (func () {
506+ close (sender .closing )
507+ })
493508 return nil
494509}
495510
0 commit comments