// HTTPTrackerAnnounce announces using HTTP format func HTTPTrackerAnnounce(query map[string]string, file FileRecord, fileUser FileUserRecord) []byte { // Begin generating response map, with current number of known seeders/leechers res := map[string][]byte{ "complete": bencode.EncInt(file.Seeders()), "incomplete": bencode.EncInt(file.Leechers()), } // If client has not yet completed torrent, ask them to announce more frequently, so they can gather // more peers and quickly report their statistics if fileUser.Completed == false { res["interval"] = bencode.EncInt(RandRange(300, 600)) res["min interval"] = bencode.EncInt(300) } else { // Once a torrent has been completed, report statistics less frequently res["interval"] = bencode.EncInt(RandRange(Static.Config.Interval-600, Static.Config.Interval)) res["min interval"] = bencode.EncInt(Static.Config.Interval / 2) } // Check for numwant parameter, return up to that number of peers // Default is 50 per protocol numwant := 50 if _, ok := query["numwant"]; ok { // Verify numwant is an integer num, err := strconv.Atoi(query["numwant"]) if err == nil { numwant = num } } // Generaate compact peer list of length numwant, exclude this user res["peers"] = bencode.EncBytes(file.PeerList(query["ip"], numwant)) // Bencode entire map and return return bencode.EncDictMap(res) }
// HTTPTrackerScrape reports scrape using HTTP format func HTTPTrackerScrape(query map[string]string, file FileRecord) []byte { // Decode hex string to byte format hash, err := hex.DecodeString(file.InfoHash) if err != nil { hash = []byte("") } return bencode.EncDictMap(map[string][]byte{ "files": bencode.EncBytes(hash), "complete": bencode.EncInt(file.Seeders()), "downloaded": bencode.EncInt(file.Completed()), "incomplete": bencode.EncInt(file.Leechers()), // optional field: name, string }) }