// Called when metadata for a torrent becomes available. func (t *torrent) setMetadata(md *metainfo.Info, infoBytes []byte, eventLocker sync.Locker) (err error) { err = validateInfo(md) if err != nil { err = fmt.Errorf("bad info: %s", err) return } t.Info = md t.length = 0 for _, f := range t.Info.UpvertedFiles() { t.length += f.Length } t.MetaData = infoBytes t.metadataHave = nil for _, hash := range infoPieceHashes(md) { piece := &piece{} piece.Event.L = eventLocker util.CopyExact(piece.Hash[:], hash) t.Pieces = append(t.Pieces, piece) } for _, conn := range t.Conns { t.initRequestOrdering(conn) if err := conn.setNumPieces(t.numPieces()); err != nil { log.Printf("closing connection: %s", err) conn.Close() } } return }
func torrentFileInfoHash(fileName string) (ih torrent.InfoHash, ok bool) { mi, _ := metainfo.LoadFromFile(fileName) if mi == nil { return } util.CopyExact(ih[:], mi.Info.Hash) ok = true return }
func scanDir(dirName string) (ee map[torrent.InfoHash]entity) { d, err := os.Open(dirName) if err != nil { log.Print(err) return } defer d.Close() names, err := d.Readdirnames(-1) if err != nil { log.Print(err) return } ee = make(map[torrent.InfoHash]entity, len(names)) addEntity := func(e entity) { e0, ok := ee[e.InfoHash] if ok { if e0.MagnetURI == "" || len(e.MagnetURI) < len(e0.MagnetURI) { return } } ee[e.InfoHash] = e } for _, n := range names { fullName := filepath.Join(dirName, n) switch filepath.Ext(n) { case ".torrent": ih, ok := torrentFileInfoHash(fullName) if !ok { break } e := entity{ TorrentFilePath: fullName, } util.CopyExact(&e.InfoHash, ih) addEntity(e) case ".magnet": uris, err := magnetFileURIs(fullName) if err != nil { log.Print(err) break } for _, uri := range uris { m, err := torrent.ParseMagnetURI(uri) if err != nil { log.Printf("error parsing %q in file %q: %s", uri, fullName, err) continue } addEntity(entity{ InfoHash: m.InfoHash, MagnetURI: uri, }) } } } return }
func (cni *NodeInfo) UnmarshalCompact(b []byte) error { if len(b) != 26 { return errors.New("expected 26 bytes") } util.CopyExact(cni.ID[:], b[:20]) cni.Addr = newDHTAddr(&net.UDPAddr{ IP: net.IPv4(b[20], b[21], b[22], b[23]), Port: int(binary.BigEndian.Uint16(b[24:26])), }) return nil }
func TestTorrentInitialState(t *testing.T) { dir, mi := testutil.GreetingTestTorrent() defer os.RemoveAll(dir) tor, err := newTorrent(func() (ih InfoHash) { util.CopyExact(ih[:], mi.Info.Hash) return }()) if err != nil { t.Fatal(err) } tor.chunkSize = 2 err = tor.setMetadata(&mi.Info.Info, mi.Info.Bytes, nil) if err != nil { t.Fatal(err) } if len(tor.Pieces) != 3 { t.Fatal("wrong number of pieces") } p := tor.Pieces[0] tor.pendAllChunkSpecs(0) assert.EqualValues(t, 3, p.numPendingChunks()) assert.EqualValues(t, chunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize)) }
func (t *torrent) hashPiece(piece pp.Integer) (ps pieceSum) { hash := pieceHash.New() t.data.WriteSectionTo(hash, int64(piece)*t.Info.PieceLength, t.Info.PieceLength) util.CopyExact(ps[:], hash.Sum(nil)) return }