Example #1
0
func NewTorrent(torrent string) (metaInfo *bencode.MetaInfo, err os.Error) {
	var input io.ReadCloser
	if strings.HasPrefix(torrent, "http:") {
		// 6g compiler bug prevents us from writing r, _, err :=
		var r *http.Response
		if r, _, err = http.Get(torrent); err != nil {
			return
		}
		input = r.Body
	} else {
		if input, err = os.Open(torrent, os.O_RDONLY, 0666); err != nil {
			return
		}
	}

	// We need to calcuate the sha1 of the Info map, including every value in the
	// map. The easiest way to do this is to read the data using the Decode
	// API, and then pick through it manually.
	var m interface{}
	m, err = bencode.Decode(input)
	input.Close()
	if err != nil {
		err = os.NewError("Couldn't parse torrent file phase 1: " + err.String())
		return
	}

	topMap, ok := m.(map[string]interface{})
	if !ok {
		err = os.NewError("Couldn't parse torrent file phase 2.")
		return
	}

	infoMap, ok := topMap["info"]
	if !ok {
		err = os.NewError("Couldn't parse torrent file. info")
		return
	}
	var b bytes.Buffer
	if err = bencode.Marshal(&b, infoMap); err != nil {
		return
	}
	hash := sha1.New()
	hash.Write(b.Bytes())

	var m2 bencode.MetaInfo
	err = bencode.Unmarshal(&b, &m2.Info)
	if err != nil {
		return
	}
	//log.Println(m2.Info)
	m2.Infohash = string(hash.Sum())
	m2.Announce = getString(topMap, "announce")
	m2.CreationDate = getString(topMap, "creation date")
	m2.Comment = getString(topMap, "comment")
	m2.CreatedBy = getString(topMap, "created by")
	m2.Encoding = getString(topMap, "encoding")
	m2.Announce_list = append(getArrayString(topMap, "announce-list"), m2.Announce)

	metaInfo = &m2
	return
}
Example #2
0
func (t *Tracker) Request(num_peers int) (err os.Error) {
	// Prepare request to make to the tracker
	left := (t.bitfield.Len() - t.bitfield.Count()) * t.pieceLength
	if len(t.status) == 0 && !t.completed {
		if left == 0 {
			t.status = "completed"
		}
	}
	url := fmt.Sprint(t.url,
		"?",
		"info_hash=", http.URLEscape(t.infohash),
		"&peer_id=", http.URLEscape(t.peerId),
		"&port=", http.URLEscape(t.port),
		"&uploaded=", http.URLEscape(strconv.Itoa64(t.uploaded)),
		"&downloaded=", http.URLEscape(strconv.Itoa64(t.downloaded)),
		"&left=", http.URLEscape(strconv.Itoa64(left)),
		"&numwant=", http.URLEscape(strconv.Itoa(num_peers)),
		"&status=", http.URLEscape(t.status),
		"&compact=1")

	if len(t.trackerId) > 0 {
		url += "&tracker_id=" + http.URLEscape(t.trackerId)
	}
	/*
		r, _, err := http.Get(url)
		if err != nil {
			return
		}
		defer r.Body.Close()
		if r.StatusCode >= 400 {
			data, _ := ioutil.ReadAll(r.Body)
			reason := "Bad Request " + string(data)
			log.Println(reason)
			err = os.NewError(reason)
			return
		}
		var tr2 TrackerResponse
		err = bencode.Unmarshal(r.Body, &tr2)
		r.Body.Close()
		if err != nil {
			return
		}
		tr = &tr2
		return
	*/
	response, _, err := http.Get(url)
	if err != nil {
		return
	}
	defer response.Body.Close()

	// Check if request was succesful
	if response.StatusCode != http.StatusOK {
		data, _ := ioutil.ReadAll(response.Body)
		reason := "Bad Request " + string(data)
		err = os.NewError(reason)
		return
	}

	// Create new TrackerResponse and decode the data
	var tr bencode.TrackerResponse
	err = bencode.Unmarshal(response.Body, &tr)
	if err != nil {
		return
	}
	t.interval = tr.Interval
	t.min_interval = tr.Min_interval
	if len(tr.Tracker_id) > 0 {
		t.trackerId = tr.Tracker_id
	}
	// Obtain new peers list
	peers := list.New()

	//log.Println("Tracker -> Decoded", len(tr.Peers), "peers")
	for i := 0; i < len(tr.Peers); i = i + 6 {
		peers.PushFront(fmt.Sprintf("%d.%d.%d.%d:%d", tr.Peers[i+0], tr.Peers[i+1], tr.Peers[i+2], tr.Peers[i+3], binary.BigEndian.Uint16([]byte(tr.Peers[i+4:i+6]))))
		//ip := fmt.Sprintf("%d.%d.%d.%d", peers[i+0], peers[i+1], peers[i+2], peers[i+3])
		//port := int64(binary.BigEndian.Uint16(peers[i+4:i+6]))
		//tracker.Peers = appendPeer(tracker.Peers, Peer{Ip: ip, Port: port})
	}
	/*for _, peer := range tr.Peers {
		peers.PushFront(fmt.Sprintf("%s:%d", peer.Ip, peer.Port))
	}*/
	//log.Println("Tracker -> Received", msgPeers.Len(), "peers")
	// Send the new data to the PeerMgr process
	t.trackerMgr.SavePeers(peers)
	if t.status == "completed" {
		t.completed = true
	}
	t.status = ""
	return
}