// Ensure that it's an error for a peer to send an invalid have message. func TestPeerInvalidHave(t *testing.T) { cl, err := NewClient(&TestingConfig) require.NoError(t, err) defer cl.Close() ie := metainfo.InfoEx{ Info: metainfo.Info{ PieceLength: 1, Pieces: make([]byte, 20), Files: []metainfo.FileInfo{{Length: 1}}, }, } ie.UpdateBytes() tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{ Info: &ie, InfoHash: ie.Hash(), }) require.NoError(t, err) assert.True(t, _new) defer tt.Drop() cn := &connection{ t: tt, } assert.NoError(t, cn.peerSentHave(0)) assert.Error(t, cn.peerSentHave(1)) }
// We read from a piece which is marked completed, but is missing data. func TestCompletedPieceWrongSize(t *testing.T) { cfg := TestingConfig cfg.DefaultStorage = badStorage{} cl, err := NewClient(&cfg) require.NoError(t, err) defer cl.Close() ie := metainfo.InfoEx{ Info: metainfo.Info{ PieceLength: 15, Pieces: make([]byte, 20), Files: []metainfo.FileInfo{ metainfo.FileInfo{Path: []string{"greeting"}, Length: 13}, }, }, } ie.UpdateBytes() tt, new, err := cl.AddTorrentSpec(&TorrentSpec{ Info: &ie, InfoHash: ie.Hash(), }) require.NoError(t, err) defer tt.Drop() assert.True(t, new) r := tt.NewReader() defer r.Close() b, err := ioutil.ReadAll(r) assert.Len(t, b, 13) assert.NoError(t, err) }
// Called when metadata for a torrent becomes available. func (t *Torrent) setInfoBytes(b []byte) error { if t.haveInfo() { return nil } var ie *metainfo.InfoEx err := bencode.Unmarshal(b, &ie) if err != nil { return fmt.Errorf("error unmarshalling info bytes: %s", err) } if ie.Hash() != t.infoHash { return errors.New("info bytes have wrong hash") } err = validateInfo(&ie.Info) if err != nil { return fmt.Errorf("bad info: %s", err) } defer t.updateWantPeersEvent() t.info = ie t.cl.event.Broadcast() t.gotMetainfo.Set() t.storage, err = t.storageOpener.OpenTorrent(t.info) if err != nil { return fmt.Errorf("error opening torrent storage: %s", err) } t.length = 0 for _, f := range t.info.UpvertedFiles() { t.length += f.Length } t.metadataBytes = b t.metadataCompletedChunks = nil hashes := infoPieceHashes(&t.info.Info) t.pieces = make([]piece, len(hashes)) for i, hash := range hashes { piece := &t.pieces[i] piece.t = t piece.index = i piece.noPendingWrites.L = &piece.pendingWritesMutex missinggo.CopyExact(piece.Hash[:], hash) } for _, conn := range t.conns { if err := conn.setNumPieces(t.numPieces()); err != nil { log.Printf("closing connection: %s", err) conn.Close() } } for i := range t.pieces { t.updatePieceCompletion(i) t.pieces[i].QueuedForHash = true } go func() { for i := range t.pieces { t.verifyPiece(i) } }() return nil }
// Called when metadata for a torrent becomes available. func (t *Torrent) setInfoBytes(b []byte) error { if t.haveInfo() { return nil } var ie *metainfo.InfoEx err := bencode.Unmarshal(b, &ie) if err != nil { return fmt.Errorf("error unmarshalling info bytes: %s", err) } if ie.Hash() != t.infoHash { return errors.New("info bytes have wrong hash") } err = validateInfo(&ie.Info) if err != nil { return fmt.Errorf("bad info: %s", err) } defer t.updateWantPeersEvent() t.info = ie t.displayName = "" // Save a few bytes lol. t.cl.event.Broadcast() t.gotMetainfo.Set() t.storage, err = t.storageOpener.OpenTorrent(t.info) if err != nil { return fmt.Errorf("error opening torrent storage: %s", err) } t.length = 0 for _, f := range t.info.UpvertedFiles() { t.length += f.Length } t.metadataBytes = b t.metadataCompletedChunks = nil t.makePieces() for _, conn := range t.conns { if err := conn.setNumPieces(t.numPieces()); err != nil { log.Printf("closing connection: %s", err) conn.Close() } } for i := range t.pieces { t.updatePieceCompletion(i) t.pieces[i].QueuedForHash = true } go func() { for i := range t.pieces { t.verifyPiece(i) } }() return nil }
func writeTorrentData(ts storage.Torrent, info *metainfo.InfoEx, b []byte) { for i := range iter.N(info.NumPieces()) { n, _ := ts.Piece(info.Piece(i)).WriteAt(b, 0) b = b[n:] } }