Documentation
¶
Overview ¶
Package udptracker implements the tracker protocol based on UDP.
You can use the package to implement a UDP tracker server to track the information that other peers upload or download the file, or to create a UDP tracker client to communicate with the UDP tracker server.
Index ¶
Examples ¶
Constants ¶
const ( ActionConnect = uint32(0) ActionAnnounce = uint32(1) ActionScrape = uint32(2) ActionError = uint32(3) )
Predefine some actions.
BEP 15
const ProtocolID = uint64(0x41727101980)
ProtocolID is magic constant for the udp tracker connection.
BEP 15
Variables ¶
var Dial = net.Dial
Functions ¶
This section is empty.
Types ¶
type AnnounceRequest ¶
type AnnounceRequest struct {
InfoHash metainfo.Hash
PeerID metainfo.Hash
Downloaded int64
Left int64
Uploaded int64
Event uint32
IP net.Addr
Key int32
NumWant int32 // -1 for default
Port uint16
Exts []Extension // BEP 41
}
AnnounceRequest represents the announce request used by UDP tracker.
BEP 15
func (*AnnounceRequest) DecodeFrom ¶
func (r *AnnounceRequest) DecodeFrom(b []byte, w int)
DecodeFrom decodes the request from b.
func (AnnounceRequest) EncodeTo ¶
func (r AnnounceRequest) EncodeTo(buf *bytes.Buffer)
EncodeTo encodes the request to buf.
type AnnounceResponse ¶
type AnnounceResponse struct {
Interval uint32
Leechers uint32
Seeders uint32
Addresses []metainfo.Address
}
AnnounceResponse represents the announce response used by UDP tracker.
BEP 15
func (*AnnounceResponse) DecodeFrom ¶
func (r *AnnounceResponse) DecodeFrom(b []byte, ipv4 bool)
DecodeFrom decodes the response from b.
func (AnnounceResponse) EncodeTo ¶
func (r AnnounceResponse) EncodeTo(buf *bytes.Buffer)
EncodeTo encodes the response to buf.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a tracker client based on UDP.
Notice: the request is synchronized, that's, the last request is not returned, the next request must not be sent.
BEP 15
Example ¶
package main
import (
"context"
"errors"
"fmt"
"log"
"net"
"time"
"github.com/go-i2p/go-i2p-bt/metainfo"
)
type testHandler struct{}
func (testHandler) OnConnect(raddr net.Addr) (err error) { return }
func (testHandler) OnAnnounce(raddr net.Addr, req AnnounceRequest) (
r AnnounceResponse, err error) {
if req.Port != 80 {
err = errors.New("port is not 80")
return
}
if len(req.Exts) > 0 {
for i, ext := range req.Exts {
switch ext.Type {
case URLData:
fmt.Printf("Extensions[%d]: URLData(%s)\n", i, string(ext.Data))
default:
fmt.Printf("Extensions[%d]: %s\n", i, ext.Type.String())
}
}
}
r = AnnounceResponse{
Interval: 1,
Leechers: 2,
Seeders: 3,
Addresses: []metainfo.Address{{IP: &net.IPAddr{IP: net.ParseIP("127.0.0.1")}, Port: 8001}},
}
return
}
func (testHandler) OnScrap(raddr net.Addr, infohashes []metainfo.Hash) (
rs []ScrapeResponse, err error) {
rs = make([]ScrapeResponse, len(infohashes))
for i := range infohashes {
rs[i] = ScrapeResponse{
Seeders: uint32(i)*10 + 1,
Leechers: uint32(i)*10 + 2,
Completed: uint32(i)*10 + 3,
}
}
return
}
func main() {
// Start the UDP tracker server
sconn, err := net.ListenPacket("udp4", "127.0.0.1:8001")
if err != nil {
log.Fatal(err)
}
server := NewServer(sconn, testHandler{})
defer server.Close()
go server.Run()
// Wait for the server to be started
time.Sleep(time.Second)
// Create a client and dial to the UDP tracker server.
client, err := NewClientByDial("udp4", "127.0.0.1:8001")
if err != nil {
log.Fatal(err)
}
// Send the ANNOUNCE request to the UDP tracker server,
// and get the ANNOUNCE response.
exts := []Extension{NewURLData([]byte("data")), NewNop()}
req := &AnnounceRequest{IP: &net.IPAddr{IP: net.ParseIP("127.0.0.1")}, Port: 80, Exts: exts}
resp, err := client.Announce(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Interval: %d\n", resp.Interval)
fmt.Printf("Leechers: %d\n", resp.Leechers)
fmt.Printf("Seeders: %d\n", resp.Seeders)
for i, addr := range resp.Addresses {
fmt.Printf("Address[%d].IP: %s\n", i, addr.IP.String())
fmt.Printf("Address[%d].Port: %d\n", i, addr.Port)
}
// Send the SCRAPE request to the UDP tracker server,
// and get the SCRAPE respsone.
hs := []metainfo.Hash{metainfo.NewRandomHash(), metainfo.NewRandomHash()}
rs, err := client.Scrape(context.Background(), hs)
if err != nil {
log.Fatal(err)
} else if len(rs) != 2 {
log.Fatalf("%+v", rs)
}
for i, r := range rs {
fmt.Printf("%d.Seeders: %d\n", i, r.Seeders)
fmt.Printf("%d.Leechers: %d\n", i, r.Leechers)
fmt.Printf("%d.Completed: %d\n", i, r.Completed)
}
}
Output: Extensions[0]: URLData(data) Extensions[1]: Nop Interval: 1 Leechers: 2 Seeders: 3 Address[0].IP: 127.0.0.1 Address[0].Port: 8001 0.Seeders: 1 0.Leechers: 2 0.Completed: 3 1.Seeders: 11 1.Leechers: 12 1.Completed: 13
func NewClient ¶
func NewClient(conn net.Conn, c ...ClientConfig) *Client
NewClient returns a new Client.
func NewClientByDial ¶
func NewClientByDial(network, address string, c ...ClientConfig) (*Client, error)
NewClientByDial returns a new Client by dialing.
func (*Client) Announce ¶
func (utc *Client) Announce(c context.Context, r *AnnounceRequest) (AnnounceResponse, error)
Announce sends a Announce request to the tracker.
Notice:
- if it does not connect to the UDP tracker server, it will connect to it, then send the ANNOUNCE request.
- If returning an error, you should retry it. See http://www.bittorrent.org/beps/bep_0015.html#time-outs
func (*Client) Scrape ¶
Scrape sends a Scrape request to the tracker.
Notice:
- if it does not connect to the UDP tracker server, it will connect to it, then send the ANNOUNCE request.
- If returning an error, you should retry it. See http://www.bittorrent.org/beps/bep_0015.html#time-outs
type ClientConfig ¶
ClientConfig is used to configure the Client.
type Extension ¶
type Extension struct {
Type ExtensionType
Length uint8
Data []byte
}
Extension represent the extension used by the UDP ANNOUNCE request.
BEP 41
func NewEndOfOptions ¶
func NewEndOfOptions() Extension
NewEndOfOptions returns a new EndOfOptions UDP extension.
func NewURLData ¶
NewURLData returns a new URLData UDP extension.
func (*Extension) DecodeFrom ¶
DecodeFrom decodes the response from b.
type ExtensionType ¶
type ExtensionType uint8
ExtensionType represents the type of UDP extension.
func (ExtensionType) String ¶
func (et ExtensionType) String() string
type ScrapeResponse ¶
ScrapeResponse represents the UDP SCRAPE response.
BEP 15
func (*ScrapeResponse) DecodeFrom ¶
func (r *ScrapeResponse) DecodeFrom(b []byte)
DecodeFrom decodes the response from b.
func (ScrapeResponse) EncodeTo ¶
func (r ScrapeResponse) EncodeTo(buf *bytes.Buffer)
EncodeTo encodes the response to buf.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a tracker server based on UDP.
func NewServer ¶
func NewServer(c net.PacketConn, h ServerHandler, sc ...ServerConfig) *Server
NewServer returns a new Server.
type ServerConfig ¶
type ServerConfig struct {
MaxBufSize int // Default: 2048
ErrorLog func(format string, args ...interface{}) // Default: log.Printf
}
ServerConfig is used to configure the Server.
type ServerHandler ¶
type ServerHandler interface {
// OnConnect is used to check whether to make the connection or not.
OnConnect(raddr net.Addr) (err error)
OnAnnounce(raddr net.Addr, req AnnounceRequest) (AnnounceResponse, error)
OnScrap(raddr net.Addr, infohashes []metainfo.Hash) ([]ScrapeResponse, error)
}
ServerHandler is used to handle the request from the client.