Example #1
0
func NewTrackerResponse(responseStr string) (*TrackerResponse, error) {
	lex := bencoding.BeginLexing("response", responseStr, bencoding.LexBegin)
	tokens := bencoding.Collect(lex)
	parser := bencoding.Parse(tokens)
	o := parser.Output.(map[string]interface{})

	// TODO: Handle required/optional fields
	response := &TrackerResponse{}

	addStringField("failure reason", &response.FailureReason, o["failure reason"], false)
	if response.FailureReason != "" {
		return response, errors.New("Tracker Request Failure")
	}

	err := addIntField("complete", &response.Complete, o["complete"], true)
	if err != nil {
		return response, err
	}
	err = addIntField("incomplete", &response.Incomplete, o["incomplete"], true)
	if err != nil {
		return response, err
	}
	addIntField("downloaded", &response.Downloaded, o["downloaded"], false)
	err = addIntField("interval", &response.Interval, o["interval"], true)
	if err != nil {
		return response, err
	}
	addIntField("min_interval", &response.MinInterval, o["min interval"], false)

	// TODO: Handle dictionary vs binary peer models
	peers := make([]Peer, 0)
	if _, ok := o["peers"]; !ok {
		return response, errors.New(fmt.Sprint("Missing Required Field: peers"))
	}
	peerBytes := o["peers"].([]byte)
	for i := 0; i < len(peerBytes); i += 6 {
		ip := net.IPv4(peerBytes[i+3], peerBytes[i+2], peerBytes[i+1], peerBytes[i])

		port := binary.BigEndian.Uint16(peerBytes[i+4 : i+6])
		peers = append(peers, Peer{IP: ip, Port: port})
	}
	response.Peers = peers

	return response, nil
}
Example #2
0
func NewMetainfo(filename string) *Metainfo {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}

	torrentStr := string(data)
	lex := bencoding.BeginLexing(".torrent", torrentStr, bencoding.LexBegin)
	tokens := bencoding.Collect(lex)

	rawInfoVal := bencoding.GetBencodedInfo(tokens)

	output := bencoding.Parse(tokens)
	result := output.Output.(map[string]interface{})

	metainfo := &Metainfo{}

	// Required fields
	if result["info"] != nil {
		addInfoFields(metainfo, result["info"].(map[string]interface{}))
		metainfo.Info.Hash = getRightEncodedSHA1(rawInfoVal)
	} else {
		panic("MISSING REQUIRED FIELD: info")
	}

	addStringField("announce", &metainfo.Announce, result["announce"], true)

	// Optional fields
	if result["announce-list"] != nil {
		// TODO: parse announce-list
	}

	if result["creation date"] != nil {
		creationDate := int64(result["creation date"].(int))
		t := time.Unix(creationDate, 0)
		metainfo.CreationDate = t
	}

	addStringField("comment", &metainfo.Comment, result["comment"], false)
	addStringField("created by", &metainfo.CreatedBy, result["created by"], false)
	addStringField("encoding", &metainfo.Encoding, result["encoding"], false)

	return metainfo
}
Example #3
0
func main() {
	// Set up logging to file and stdout
	f, err := os.OpenFile("torro.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Printf("Error opening file: %v", err)
	}
	defer f.Close()
	mw := io.MultiWriter(os.Stdout, f)
	log.SetOutput(mw)

	println("TORRO!\n\n\n")

	// Read command line flags and arguments
	pPrint := flag.String("print", "metainfo", "either tokens, parsed, or metainfo")
	pUPNP := flag.Bool("upnp", false, "open port through UPNP")
	pAnnounce := flag.Bool("announce", false, "send announce request to tracker")
	flag.Parse()

	var filename string
	fmt.Println(flag.Args())
	if len(flag.Args()) > 0 {
		filename = flag.Args()[0]
	} else {
		filename = "testfiles/TheInternetsOwnBoyTheStoryOfAaronSwartz_archive.torrent"
	}

	if *pUPNP {
		fmt.Println("Opening port through UPNP")
		d, _ := upnp.Discover()
		ip, _ := d.ExternalIP()
		_ = d.Forward(55555, "torro")
		defer d.Clear(55555)
		log.Printf("Discovered: %q\n", d)
		log.Printf("External IP: %q\n", ip)
		log.Printf("Location: %q\n", d.Location())
	}

	// Read actual .torrent file
	fmt.Println("Parsing: ", filename)
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}

	// Lex and Parse .torrent file
	torrentStr := string(data)
	lex := bencoding.BeginLexing(".torrent", torrentStr, bencoding.LexBegin)
	tokens := bencoding.Collect(lex)

	output := bencoding.Parse(tokens)
	result := output.Output.(map[string]interface{})

	// Read .torrent metainfo and make request to the announce URL
	metainfo := structure.NewMetainfo(filename)

	c := client.NewTrackerClient()
	req := structure.NewTrackerRequest(metainfo)
	req.PeerID = "-qB3230-u~QGMmUs~yXH"
	req.Port = 55555
	req.Compact = true
	req.NoPeerID = true

	if *pAnnounce {
		res, err := c.MakeAnnounceRequest(req, client.TrackerRequestStarted)
		if err != nil {
			fmt.Println(res.FailureReason)
			panic(err.Error())
		}
		fmt.Println(res)

		log.Println("StartListening")
		port := 55555
		peerId := []byte("-TR2840-nj5ovtkoz2ed")
		s := client.NewBTService(port, peerId)
		s.StartListening()
	}

	switch *pPrint {
	case "tokens":
		PrintTokens(&tokens)
	case "parsed":
		PrintParsedStructure(result)
	case "metainfo":
		PrintMetainfo(metainfo)
	default:
		PrintMetainfo(metainfo)
	}

	//	time.Sleep(time.Second * 60)

}