+func (ws *webseedPeer) doRequest(r Request) error {
+ webseedRequest := ws.client.NewRequest(ws.intoSpec(r))
+ ws.activeRequests[r] = webseedRequest
+ err := func() error {
+ ws.requesterCond.L.Unlock()
+ defer ws.requesterCond.L.Lock()
+ return ws.requestResultHandler(r, webseedRequest)
+ }()
+ delete(ws.activeRequests, r)
+ return err
+}
+
+func (ws *webseedPeer) requester(i int) {
+ ws.requesterCond.L.Lock()
+ defer ws.requesterCond.L.Unlock()
+start:
+ for !ws.peer.closed.IsSet() {
+ // Restart is set if we don't need to wait for the requestCond before trying again.
+ restart := false
+ ws.peer.requestState.Requests.Iterate(func(x RequestIndex) bool {
+ r := ws.peer.t.requestIndexToRequest(x)
+ if _, ok := ws.activeRequests[r]; ok {
+ return true
+ }
+ err := ws.doRequest(r)
+ ws.requesterCond.L.Unlock()
+ if err != nil && !errors.Is(err, context.Canceled) {
+ log.Printf("requester %v: error doing webseed request %v: %v", i, r, err)
+ }
+ restart = true
+ if errors.Is(err, webseed.ErrTooFast) {
+ time.Sleep(time.Duration(rand.Int63n(int64(10 * time.Second))))
+ }
+ time.Sleep(time.Until(ws.lastUnhandledErr.Add(webseedPeerUnhandledErrorSleep)))
+ ws.requesterCond.L.Lock()
+ return false
+ })
+ if restart {
+ goto start
+ }
+ ws.requesterCond.Wait()
+ }
+}
+