]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Add explicit metadata extension types
authorMatt Joiner <anacrolix@gmail.com>
Fri, 18 Jun 2021 05:04:07 +0000 (15:04 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 21 Jun 2021 02:14:06 +0000 (12:14 +1000)
client.go
peer_protocol/extended.go
peer_protocol/metadata.go [new file with mode: 0644]
peer_protocol/protocol.go
peerconn.go
torrent.go

index dc2448076a14fa95783cbef253639e882d3b7c01..032f253a7640333976474ef87c76bb97ae3f3299 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1020,25 +1020,21 @@ func (cl *Client) haveDhtServer() (ret bool) {
 
 // Process incoming ut_metadata message.
 func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *PeerConn) error {
-       var d map[string]int
+       var d pp.ExtendedMetadataRequestMsg
        err := bencode.Unmarshal(payload, &d)
        if _, ok := err.(bencode.ErrUnusedTrailingBytes); ok {
        } else if err != nil {
                return fmt.Errorf("error unmarshalling bencode: %s", err)
        }
-       msgType, ok := d["msg_type"]
-       if !ok {
-               return errors.New("missing msg_type field")
-       }
-       piece := d["piece"]
-       switch msgType {
+       piece := d.Piece
+       switch d.Type {
        case pp.DataMetadataExtensionMsgType:
                c.allStats(add(1, func(cs *ConnStats) *Count { return &cs.MetadataChunksRead }))
                if !c.requestedMetadataPiece(piece) {
                        return fmt.Errorf("got unexpected piece %d", piece)
                }
                c.metadataRequests[piece] = false
-               begin := len(payload) - metadataPieceSize(d["total_size"], piece)
+               begin := len(payload) - d.PieceSize()
                if begin < 0 || begin >= len(payload) {
                        return fmt.Errorf("data has bad offset in payload: %d", begin)
                }
@@ -1055,7 +1051,7 @@ func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *PeerCon
                return err
        case pp.RequestMetadataExtensionMsgType:
                if !t.haveMetadataPiece(piece) {
-                       c.write(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
+                       c.write(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d.Piece, nil))
                        return nil
                }
                start := (1 << 14) * piece
index ae5f124e2bc44124c8101b8630f245ccdb0bf7af..cbefee6a090d1a514fdc83057679769268a4be93 100644 (file)
@@ -1,6 +1,8 @@
 package peer_protocol
 
-import "net"
+import (
+       "net"
+)
 
 // http://www.bittorrent.org/beps/bep_0010.html
 type (
@@ -26,7 +28,6 @@ type (
 const (
        // http://www.bittorrent.org/beps/bep_0011.html
        ExtensionNamePex ExtensionName = "ut_pex"
-       // http://bittorrent.org/beps/bep_0009.html. Note that there's an
-       // LT_metadata, but I've never implemented it.
-       ExtensionNameMetadata = "ut_metadata"
+
+       ExtensionDeleteNumber ExtensionNumber = 0
 )
diff --git a/peer_protocol/metadata.go b/peer_protocol/metadata.go
new file mode 100644 (file)
index 0000000..c480091
--- /dev/null
@@ -0,0 +1,42 @@
+package peer_protocol
+
+import (
+       "github.com/anacrolix/torrent/bencode"
+)
+
+const (
+       // http://bittorrent.org/beps/bep_0009.html. Note that there's an
+       // LT_metadata, but I've never implemented it.
+       ExtensionNameMetadata = "ut_metadata"
+)
+
+type (
+       ExtendedMetadataRequestMsg struct {
+               Piece     int                            `bencode:"piece"`
+               TotalSize int                            `bencode:"total_size"`
+               Type      ExtendedMetadataRequestMsgType `bencode:"msg_type"`
+       }
+
+       ExtendedMetadataRequestMsgType int
+)
+
+func MetadataExtensionRequestMsg(peerMetadataExtensionId ExtensionNumber, piece int) Message {
+       return Message{
+               Type:       Extended,
+               ExtendedID: peerMetadataExtensionId,
+               ExtendedPayload: bencode.MustMarshal(ExtendedMetadataRequestMsg{
+                       Piece: piece,
+                       Type:  RequestMetadataExtensionMsgType,
+               }),
+       }
+}
+
+// Returns the expected piece size for this request message. This is needed to determine the offset
+// into an extension message payload that the request metadata piece data starts.
+func (me ExtendedMetadataRequestMsg) PieceSize() int {
+       ret := me.TotalSize - me.Piece*(1<<14)
+       if ret > 1<<14 {
+               ret = 1 << 14
+       }
+       return ret
+}
index 506e020eeba8b1cc0e738a269b1fdac47e6302d0..2086063f91102a5fc21997167de268e3ea76bd07 100644 (file)
@@ -41,7 +41,7 @@ const (
 const (
        HandshakeExtendedID = 0
 
-       RequestMetadataExtensionMsgType = 0
-       DataMetadataExtensionMsgType    = 1
-       RejectMetadataExtensionMsgType  = 2
+       RequestMetadataExtensionMsgType ExtendedMetadataRequestMsgType = 0
+       DataMetadataExtensionMsgType                                   = 1
+       RejectMetadataExtensionMsgType                                 = 2
 )
index b35564ac83aa47d817904327c9bdb763136ff530..ac2b0ddfb721cd1426ee64ea4e7d1f8412f9631f 100644 (file)
@@ -443,27 +443,14 @@ func (cn *PeerConn) write(msg pp.Message) bool {
 
 func (cn *PeerConn) requestMetadataPiece(index int) {
        eID := cn.PeerExtensionIDs[pp.ExtensionNameMetadata]
-       if eID == 0 {
+       if eID == pp.ExtensionDeleteNumber {
                return
        }
        if index < len(cn.metadataRequests) && cn.metadataRequests[index] {
                return
        }
        cn.logger.WithDefaultLevel(log.Debug).Printf("requesting metadata piece %d", index)
-       cn.write(pp.Message{
-               Type:       pp.Extended,
-               ExtendedID: eID,
-               ExtendedPayload: func() []byte {
-                       b, err := bencode.Marshal(map[string]int{
-                               "msg_type": pp.RequestMetadataExtensionMsgType,
-                               "piece":    index,
-                       })
-                       if err != nil {
-                               panic(err)
-                       }
-                       return b
-               }(),
-       })
+       cn.write(pp.MetadataExtensionRequestMsg(eID, index))
        for index >= len(cn.metadataRequests) {
                cn.metadataRequests = append(cn.metadataRequests, false)
        }
index c4aae8fe4b269547f98d149338f34c55808ae7f3..ab0a96954ffb3d6d2896a38dccf1ebde9159c17a 100644 (file)
@@ -544,19 +544,15 @@ func (t *Torrent) metadataPieceSize(piece int) int {
        return metadataPieceSize(len(t.metadataBytes), piece)
 }
 
-func (t *Torrent) newMetadataExtensionMessage(c *PeerConn, msgType int, piece int, data []byte) pp.Message {
-       d := map[string]int{
-               "msg_type": msgType,
-               "piece":    piece,
-       }
-       if data != nil {
-               d["total_size"] = len(t.metadataBytes)
-       }
-       p := bencode.MustMarshal(d)
+func (t *Torrent) newMetadataExtensionMessage(c *PeerConn, msgType pp.ExtendedMetadataRequestMsgType, piece int, data []byte) pp.Message {
        return pp.Message{
-               Type:            pp.Extended,
-               ExtendedID:      c.PeerExtensionIDs[pp.ExtensionNameMetadata],
-               ExtendedPayload: append(p, data...),
+               Type:       pp.Extended,
+               ExtendedID: c.PeerExtensionIDs[pp.ExtensionNameMetadata],
+               ExtendedPayload: append(bencode.MustMarshal(pp.ExtendedMetadataRequestMsg{
+                       Piece:     piece,
+                       TotalSize: len(t.metadataBytes),
+                       Type:      msgType,
+               }), data...),
        }
 }