コード例 #1
0
ファイル: main.go プロジェクト: 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()
}
コード例 #2
0
ファイル: peer.go プロジェクト: jbitor/bittorrent
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...))
}
コード例 #3
0
ファイル: client.go プロジェクト: jbitor/bittorrent
func (c *localNodeClient) Save() (err error) {
	var (
		nodeData []byte
	)

	if c.localNode == nil {
		err = errors.New("Client is closed.")
		return
	}

	nodeData, err = bencoding.Encode(c.localNode)
	if err != nil {
		return
	}

	err = c.openDataFile.Truncate(0)
	if err != nil {
		return
	}

	_, err = c.openDataFile.WriteAt(nodeData, 0)
	if err != nil {
		return
	}

	err = c.openDataFile.Sync()
	if err != nil {
		return
	}

	logger.Info("Saved DHT client state.")

	return
}
コード例 #4
0
ファイル: main.go プロジェクト: jbitor/cli
func cmdJsonToBencoding(args []string) {
	if len(args) != 0 {
		logger.Fatalf("Usage: %v to-bencoding < FOO.bittorrent.json > FOO.torrent", os.Args[0])
		return
	}

	data, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		logger.Fatalf("Error reading stdin: %v", err)
		return
	}

	var decoded *interface{}
	err = json.Unmarshal(data, &decoded)
	if err != nil {
		logger.Fatalf("Error decoding JSON from stdin: %v", err)
		return
	}

	bval, err := bencoding.FromJsonable(*decoded)
	if err != nil {
		logger.Fatalf("Error converting jsonable to bencodable: %v", err)
		return
	}

	encoded, err := bencoding.Encode(bval)
	if err != nil {
		logger.Fatalf("Error bencoding value: %v", err)
		return
	}

	os.Stdout.Write(encoded)
	os.Stdout.Sync()
}
コード例 #5
0
ファイル: rpc.go プロジェクト: jbitor/bittorrent
func (local *localNode) sendQuery(remote *RemoteNode, queryType string, arguments bencoding.Dict) (query *RpcQuery) {
	// XXX(JB): These should probably have a distinct warning logger.
	if remote.Flooded() {
		logger.Info("WARNING: flooding node %v.", remote)
	}

	if remote.Status() == STATUS_BAD {
		logger.Info("WARNING: querying bad node %v.", remote)
	}

	query = new(RpcQuery)
	query.Result = make(chan *bencoding.Dict)
	query.Err = make(chan error)
	query.Remote = remote

	if arguments == nil {
		arguments = bencoding.Dict{}
	}

	arguments["id"] = bencoding.String(local.Id)

	// XXX: assert that these keys are not already present?
	message := bencoding.Dict{
		"y": bencoding.String("q"),
		"q": bencoding.String(queryType),
		"a": arguments,
	}

	transactionId := new([4]byte)
	if _, err := rand.Read(transactionId[:]); err != nil {
		query.Err <- err
		close(query.Result)
		close(query.Err)
		return
	}

	query.TransactionId = string(transactionId[:])

	local.OutstandingQueries[query.TransactionId] = query

	message["t"] = bencoding.String(query.TransactionId)

	encodedMessage, err := bencoding.Encode(message)

	if err != nil {
		query.Err <- err
		close(query.Result)
		close(query.Err)
		return
	}

	remote.LastRequestTo = time.Now()

	go func() {
		// XXX: Does this wait longer than necessary to send the packet?
		local.Connection.WriteTo(encodedMessage, &remote.Address)
	}()

	return query
}
コード例 #6
0
ファイル: peer.go プロジェクト: jbitor/bittorrent
// 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...))
	}
}
コード例 #7
0
ファイル: main.go プロジェクト: jbitor/cli
func main() {
	loggerconfig.Use()

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

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

	infoHash, err := bittorrent.BTIDFromHex(os.Args[1])

	if err != nil {
		logger.Fatalf("Specified string was not a valid hex infohash [%v].", err)
		return
	}

	peers := make([]net.TCPAddr, 0)
	dec := json.NewDecoder(os.Stdin)
	dec.Decode(&peers)
	logger.Info("Loaded peers: %v", peers)

	client := bittorrent.OpenClient()
	swarm := client.Swarm(infoHash)

	for _, peer := range peers {
		swarm.AddPeer(peer)
	}

	logger.Info("getting info")
	info := swarm.Info()
	logger.Info("got info: %v", info)

	torrentFileData, err := bencoding.Encode(bencoding.Dict{
		"info":          info,
		"announce-list": bencoding.List{},
		"nodes":         bencoding.List{},
	})
	if err != nil {
		logger.Fatalf("error encoding torrent file: %v:", err)
	}

	os.Stdout.Write(torrentFileData)
}
コード例 #8
0
ファイル: web.go プロジェクト: jbitor/webclient
// /INFOHASH.torrent
//
func (wc *T) handleTorrentFileRequest(w http.ResponseWriter, r *http.Request, infoHash bittorrent.BTID) {
	logger.Notice("Serving %v.torrent file request", infoHash)

	info := wc.btClient.Swarm(infoHash, wc.dhtClient.GetPeers(infoHash).ReadNewPeers()).Info()

	data, err := bencoding.Encode(bencoding.Dict{
		"info":          info,
		"announce-list": bencoding.List{},
		"nodes":         bencoding.List{},
	})
	if err != nil {
		logger.Error("unable to encode torrent: %v", err)
		return
	}
	w.Header().Set("Content-Type", "application/x-bittorrent")
	// TODO: encode filename & filename* properly
	w.Header().Set("Content-Disposition", "attachment;filename="+string(info["name"].(bencoding.String))+".torrent")
	w.Write(data)
}