// ParseAnnounce parses an AnnounceRequest from a UDP request. // // If allowIPSpoofing is true, IPs provided via params will be used. // // If v6 is true the announce will be parsed as an IPv6 announce "the // opentracker way", see // http://opentracker.blog.h3q.com/2007/12/28/the-ipv6-situation/ func ParseAnnounce(r Request, allowIPSpoofing, v6 bool) (*bittorrent.AnnounceRequest, error) { ipEnd := 84 + net.IPv4len if v6 { ipEnd = 84 + net.IPv6len } if len(r.Packet) < ipEnd+10 { return nil, errMalformedPacket } infohash := r.Packet[16:36] peerID := r.Packet[36:56] downloaded := binary.BigEndian.Uint64(r.Packet[56:64]) left := binary.BigEndian.Uint64(r.Packet[64:72]) uploaded := binary.BigEndian.Uint64(r.Packet[72:80]) eventID := int(r.Packet[83]) if eventID >= len(eventIDs) { return nil, errMalformedEvent } ip := r.IP ipbytes := r.Packet[84:ipEnd] if allowIPSpoofing { // Make sure the bytes are copied to a new slice. copy(ip, net.IP(ipbytes)) } if !allowIPSpoofing && r.IP == nil { // We have no IP address to fallback on. return nil, errMalformedIP } numWant := binary.BigEndian.Uint32(r.Packet[ipEnd+4 : ipEnd+8]) port := binary.BigEndian.Uint16(r.Packet[ipEnd+8 : ipEnd+10]) params, err := handleOptionalParameters(r.Packet[ipEnd+10:]) if err != nil { return nil, err } return &bittorrent.AnnounceRequest{ Event: eventIDs[eventID], InfoHash: bittorrent.InfoHashFromBytes(infohash), NumWant: uint32(numWant), Left: left, Downloaded: downloaded, Uploaded: uploaded, Peer: bittorrent.Peer{ ID: bittorrent.PeerIDFromBytes(peerID), IP: ip, Port: port, }, Params: params, }, nil }
// ParseScrape parses a ScrapeRequest from a UDP request. func ParseScrape(r Request) (*bittorrent.ScrapeRequest, error) { // If a scrape isn't at least 36 bytes long, it's malformed. if len(r.Packet) < 36 { return nil, errMalformedPacket } // Skip past the initial headers and check that the bytes left equal the // length of a valid list of infohashes. r.Packet = r.Packet[16:] if len(r.Packet)%20 != 0 { return nil, errMalformedPacket } // Allocate a list of infohashes and append it to the list until we're out. var infohashes []bittorrent.InfoHash for len(r.Packet) >= 20 { infohashes = append(infohashes, bittorrent.InfoHashFromBytes(r.Packet[:20])) r.Packet = r.Packet[20:] } return &bittorrent.ScrapeRequest{ InfoHashes: infohashes, }, nil }