]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Reannounce webtorrent webrtc offers on reconnect
authorJustin M <37273682+DigitalAlchemist@users.noreply.github.com>
Mon, 4 Jan 2021 23:20:51 +0000 (23:20 +0000)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 5 Jan 2021 00:38:16 +0000 (11:38 +1100)
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)

webtorrent/tracker_client.go

index 5af6c7c0df74a522614f47b949d629a749c707c3..47267e0ebe3b3bf3ccc6d53eaeaa049ea6784ab8 100644 (file)
@@ -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)
        }