2015-02-20 08:18:44 +01:00
|
|
|
// Copyright 2015 The Chihaya Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by the BSD 2-Clause license,
|
|
|
|
// which can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package udp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
2015-02-20 19:42:14 +01:00
|
|
|
"time"
|
2015-02-20 08:18:44 +01:00
|
|
|
|
|
|
|
"github.com/chihaya/chihaya/tracker/models"
|
|
|
|
)
|
|
|
|
|
2015-02-20 20:08:46 +01:00
|
|
|
// Writer implements the tracker.Writer interface for the UDP protocol.
|
2015-02-20 08:18:44 +01:00
|
|
|
type Writer struct {
|
|
|
|
buf *bytes.Buffer
|
|
|
|
|
2015-02-20 18:35:31 +01:00
|
|
|
connectionID []byte
|
2015-02-20 08:18:44 +01:00
|
|
|
transactionID []byte
|
|
|
|
}
|
|
|
|
|
2015-02-20 20:08:46 +01:00
|
|
|
// WriteError writes the failure reason as a null-terminated string.
|
2015-02-20 08:18:44 +01:00
|
|
|
func (w *Writer) WriteError(err error) error {
|
2015-02-24 03:30:45 +01:00
|
|
|
w.writeHeader(errorActionID)
|
2015-02-20 08:18:44 +01:00
|
|
|
w.buf.WriteString(err.Error())
|
|
|
|
w.buf.WriteRune('\000')
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-02-20 20:08:46 +01:00
|
|
|
// WriteAnnounce encodes an announce response according to the UDP spec.
|
2015-02-20 08:18:44 +01:00
|
|
|
func (w *Writer) WriteAnnounce(res *models.AnnounceResponse) error {
|
2015-02-24 03:30:45 +01:00
|
|
|
w.writeHeader(announceActionID)
|
2015-02-20 19:42:14 +01:00
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(res.Interval/time.Second))
|
2015-02-20 08:18:44 +01:00
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(res.Incomplete))
|
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(res.Complete))
|
|
|
|
|
|
|
|
for _, peer := range res.IPv4Peers {
|
|
|
|
w.buf.Write(peer.IP)
|
|
|
|
binary.Write(w.buf, binary.BigEndian, peer.Port)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-02-21 06:21:14 +01:00
|
|
|
// WriteScrape encodes a scrape response according to the UDP spec.
|
2015-02-20 08:18:44 +01:00
|
|
|
func (w *Writer) WriteScrape(res *models.ScrapeResponse) error {
|
2015-02-24 03:30:45 +01:00
|
|
|
w.writeHeader(scrapeActionID)
|
2015-02-20 18:35:31 +01:00
|
|
|
|
|
|
|
for _, torrent := range res.Files {
|
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(torrent.Seeders.Len()))
|
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(torrent.Snatches))
|
|
|
|
binary.Write(w.buf, binary.BigEndian, uint32(torrent.Leechers.Len()))
|
|
|
|
}
|
|
|
|
|
2015-02-20 08:18:44 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-02-20 20:08:46 +01:00
|
|
|
// writeHeader writes the action and transaction ID to the response.
|
2015-02-20 08:18:44 +01:00
|
|
|
func (w *Writer) writeHeader(action uint32) {
|
|
|
|
binary.Write(w.buf, binary.BigEndian, action)
|
|
|
|
w.buf.Write(w.transactionID)
|
|
|
|
}
|