Example #1
0
func (p *swarmPeer) writeHandshake(peerId BTID, infohash BTID) {
	// BitTorrent Handshake
	header := []byte(peerProtocolHeader)
	extensionFlags := make([]byte, 8)
	extensionFlags[5] |= 0x10 // indicate extension protocol support
	p.conn.Write(header)
	p.conn.Write(extensionFlags)
	p.conn.Write([]byte(infohash))
	p.conn.Write([]byte(peerId))

	// If we had any pieces, we would need to indicate so here, but we don't.
	// writeMessage(w, msgBitfield, piecesBitfield)

	// TODO: move this somewhere else and only fire it after we check their extension flags
	// Write Extension Protcol Handshake

	handshakeBody, err := bencoding.Encode(bencoding.Dict{
		"v": bencoding.String("jbitor 0.0.0"),
		"m": bencoding.Dict{
			"ut_metadata": bencoding.Int(ourUtMetadataId),
			"ut_pex":      bencoding.Int(ourUtPexId),
		},
		"p": bencoding.Int(PORT),
	})

	if err != nil {
		logger.Info("unable to encode extension handshake: %v", err)
		return
	}

	logger.Info("sent extension handshake")
	p.writeMessage(msgExtended, append([]byte{extensionHandshakeId}, handshakeBody...))
}
Example #2
0
// Requests the next piece of metadata we don't yet have from this peer.
// Must only be called if we know the peer supports it.
// Does nothing if we already have all of the pieces they claim.
func (p *swarmPeer) requestNextMetadataPiece() {
	if !p.infoComplete {
		i := len(p.infoPieces)
		requestBody, err := bencoding.Encode(bencoding.Dict{
			"msg_type": bencoding.Int(0), // request piece
			"piece":    bencoding.Int(i),
		})
		if err != nil {
			logger.Error("unable to encode extension metadata request: %v", err)
			return
		}
		logger.Notice("requesting piece %v of metadata!", i)
		p.writeMessage(msgExtended, append([]byte{p.extensions.bep9MetadataExchange.id}, requestBody...))
	}
}
Example #3
0
File: main.go Project: jbitor/cli
func main() {
	loggerconfig.Use()

	if len(os.Args) != 2 {
		logger.Fatalf("Usage: %v PATH", os.Args[0])
		return
	}

	weakrand.Seed(time.Now().UTC().UnixNano())

	path := os.Args[1]

	infoDict, err := bittorrent.GenerateTorrentMetaInfo(bittorrent.CreationOptions{
		Path:           path,
		PieceLength:    PieceLength,
		ForceMultiFile: false,
	})
	if err != nil {
		logger.Fatalf("Error generating torrent: %v", err)
		return
	}

	infoData, err := bencoding.Encode(infoDict)
	if err != nil {
		logger.Fatalf("Error encoding torrent infodict (for hashing): %v", err)
		return
	}

	torrentDict := bencoding.Dict{
		"info": infoDict,
		"nodes": bencoding.List{
			bencoding.List{
				bencoding.String("127.0.0.1"),
				bencoding.Int(6881),
			},
		},
	}

	torrentData, err := bencoding.Encode(torrentDict)

	if err != nil {
		logger.Fatalf("Error encoding torrent data: %v", err)
		return
	}

	hasher := sha1.New()
	hasher.Write(infoData)
	hash := hasher.Sum(nil)
	infoHash := bittorrent.BTID(hash)

	logger.Info("Generated torrent btih=%v.", infoHash)

	os.Stdout.Write(torrentData)
	os.Stdout.Sync()
}
Example #4
0
func (local *localNode) MarshalBencodingDict() (dict bencoding.Dict) {
	dict = bencoding.Dict{}

	if local.Id != "" {
		dict["Id"] = bencoding.String(local.Id)
	}

	dict["Port"] = bencoding.Int(local.Port)

	nodes := make(bencoding.List, len(local.Nodes))

	i := 0
	for _, node := range local.Nodes {
		nodes[i] = node.MarshalBencodingDict()
		i++
	}

	dict["Nodes"] = nodes

	return dict
}
Example #5
0
func GenerateTorrentMetaInfo(options CreationOptions) (TorrentMeta, error) {
	fileInfo, err := os.Stat(options.Path)
	if err != nil {
		return nil, err
	}

	multiFile := fileInfo.IsDir() || options.ForceMultiFile

	pieces := make([]byte, 0)

	fileList := bencoding.List{}

	pieceHasher := newPieceHasher(options.PieceLength)

	if multiFile {
		err := filepath.Walk(options.Path, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			if info.IsDir() {
				return nil
			}

			relPath, err := filepath.Rel(options.Path, path)
			if err != nil {
				return err
			}

			pathList := bencoding.List{}

			for _, component := range filepath.SplitList(relPath) {
				pathList = append(pathList, bencoding.String(component))
			}

			fileDict := TorrentFileMeta{
				"path":   pathList,
				"length": bencoding.Int(info.Size()),
			}

			data, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}

			pieceHasher.Write(data)

			fileList = append(fileList, fileDict)

			return nil
		})

		if err != nil {
			return nil, err
		}
	} else {
		if fileInfo.Size() > 0 {
			file, err := os.Open(options.Path)
			if err != nil {
				return nil, err
			}

			defer file.Close()
			io.Copy(pieceHasher.Writer(), file)
		}
	}

	pieces = pieceHasher.Pieces()

	infoDict := TorrentMeta{
		"name":         bencoding.String(fileInfo.Name()),
		"piece length": bencoding.Int(options.PieceLength),
		"pieces":       bencoding.String(pieces),
	}

	if multiFile {
		infoDict["files"] = fileList
	} else {
		infoDict["length"] = bencoding.Int(fileInfo.Size())
	}

	return infoDict, nil
}