}
// Process incoming ut_metadata message.
-func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) (err error) {
+func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) error {
var d map[string]int
- err = bencode.Unmarshal(payload, &d)
+ err := bencode.Unmarshal(payload, &d)
if err != nil {
- err = fmt.Errorf("error unmarshalling payload: %s: %q", err, payload)
- return
+ return fmt.Errorf("error unmarshalling payload: %s: %q", err, payload)
}
msgType, ok := d["msg_type"]
if !ok {
- err = errors.New("missing msg_type field")
- return
+ return errors.New("missing msg_type field")
}
piece := d["piece"]
switch msgType {
case pp.DataMetadataExtensionMsgType:
if !c.requestedMetadataPiece(piece) {
- err = fmt.Errorf("got unexpected piece %d", piece)
- return
+ return fmt.Errorf("got unexpected piece %d", piece)
}
c.metadataRequests[piece] = false
begin := len(payload) - metadataPieceSize(d["total_size"], piece)
if begin < 0 || begin >= len(payload) {
- err = fmt.Errorf("data has bad offset in payload: %d", begin)
- return
+ return fmt.Errorf("data has bad offset in payload: %d", begin)
}
t.saveMetadataPiece(piece, payload[begin:])
c.UsefulChunksReceived++
c.lastUsefulChunkReceived = time.Now()
- t.maybeMetadataCompleted()
+ return t.maybeCompleteMetadata()
case pp.RequestMetadataExtensionMsgType:
if !t.haveMetadataPiece(piece) {
c.Post(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
- break
+ return nil
}
start := (1 << 14) * piece
c.Post(t.newMetadataExtensionMessage(c, pp.DataMetadataExtensionMsgType, piece, t.metadataBytes[start:start+t.metadataPieceSize(piece)]))
+ return nil
case pp.RejectMetadataExtensionMsgType:
+ return nil
default:
- err = errors.New("unknown msg_type value")
+ return errors.New("unknown msg_type value")
}
- return
}
func (cl *Client) upload(t *Torrent, c *connection) {
}
func (t *Torrent) invalidateMetadata() {
- t.metadataBytes = nil
- t.metadataCompletedChunks = nil
+ for i := range t.metadataCompletedChunks {
+ t.metadataCompletedChunks[i] = false
+ }
t.info = nil
}
}
}
-func (t *Torrent) maybeMetadataCompleted() {
+// Returns an error if the metadata was completed, but couldn't be set for
+// some reason. Blame it on the last peer to contribute.
+func (t *Torrent) maybeCompleteMetadata() error {
if t.haveInfo() {
// Nothing to do.
- return
+ return nil
}
if !t.haveAllMetadataPieces() {
// Don't have enough metadata pieces.
- return
+ return nil
}
- // TODO(anacrolix): If this fails, I think something harsher should be
- // done.
err := t.setInfoBytes(t.metadataBytes)
if err != nil {
- log.Printf("error setting metadata: %s", err)
t.invalidateMetadata()
- return
+ return fmt.Errorf("error setting info bytes: %s", err)
}
if t.cl.config.Debug {
log.Printf("%s: got metadata from peers", t)
}
+ return nil
}
func (t *Torrent) readerPieces() (ret bitmap.Bitmap) {