From: Justin M <37273682+DigitalAlchemist@users.noreply.github.com> Date: Mon, 4 Jan 2021 23:20:51 +0000 (+0000) Subject: Reannounce webtorrent webrtc offers on reconnect X-Git-Tag: v1.21.0~11 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=b2ab540f9381100b26c9a9b3a2652a7e4981f3e0;p=btrtrc.git Reannounce webtorrent webrtc offers on reconnect On socket reconnect, reannounce any webrtc offers that might have been half-open before the socket reconnected. This implementation closes any existing half-open offers and republishes them, but does nothing to existing webrtc connections which are still running (these are cleaned up elsewhere and are not owned by this code) --- diff --git a/webtorrent/tracker_client.go b/webtorrent/tracker_client.go index 5af6c7c0..47267e0e 100644 --- a/webtorrent/tracker_client.go +++ b/webtorrent/tracker_client.go @@ -72,14 +72,14 @@ func (tc *TrackerClient) doWebsocket() error { return fmt.Errorf("dialing tracker: %w", err) } defer c.Close() - tc.Logger.WithDefaultLevel(log.Debug).Printf("dialed tracker %q", tc.Url) + tc.Logger.WithDefaultLevel(log.Info).Printf("connected") tc.mu.Lock() tc.wsConn = c tc.cond.Broadcast() tc.mu.Unlock() + tc.announceOffers() err = tc.trackerReadLoop(tc.wsConn) tc.mu.Lock() - tc.closeUnusedOffers() c.Close() tc.mu.Unlock() return err @@ -111,11 +111,36 @@ func (tc *TrackerClient) Close() error { if tc.wsConn != nil { tc.wsConn.Close() } + tc.closeUnusedOffers() tc.mu.Unlock() tc.cond.Broadcast() return nil } +func (tc *TrackerClient) announceOffers() { + + // tc.Announce grabs a lock on tc.outboundOffers. It also handles the case where outboundOffers + // is nil. Take ownership of outboundOffers here. + tc.mu.Lock() + offers := tc.outboundOffers + tc.outboundOffers = nil + tc.mu.Unlock() + + if offers == nil { + return + } + + // Iterate over our locally-owned offers, close any existing "invalid" ones from before the + // socket reconnected, reannounce the infohash, adding it back into the tc.outboundOffers. + tc.Logger.WithDefaultLevel(log.Info).Printf("reannouncing %d infohashes after restart", len(offers)) + for _, offer := range offers { + // TODO: Capture the errors? Are we even in a position to do anything with them? + offer.peerConnection.Close() + // Use goroutine here to allow read loop to start and ensure the buffer drains. + go tc.Announce(tracker.Started, offer.infoHash) + } +} + func (tc *TrackerClient) closeUnusedOffers() { for _, offer := range tc.outboundOffers { offer.peerConnection.Close() @@ -139,6 +164,7 @@ func (tc *TrackerClient) Announce(event tracker.AnnounceEvent, infoHash [20]byte request, err := tc.GetAnnounceRequest(event, infoHash) if err != nil { + pc.Close() return fmt.Errorf("getting announce parameters: %w", err) } @@ -159,6 +185,7 @@ func (tc *TrackerClient) Announce(event tracker.AnnounceEvent, infoHash [20]byte data, err := json.Marshal(req) if err != nil { + pc.Close() return fmt.Errorf("marshalling request: %w", err) }