2
0
mirror of synced 2025-02-23 22:28:11 +00:00

Fixes and tests for UDP tracker protocol

This commit is contained in:
Matt Joiner 2013-12-14 22:21:45 +11:00
parent 8baadf0af3
commit 5f093c3803
3 changed files with 81 additions and 14 deletions

View File

@ -1,6 +1,7 @@
package tracker
import (
"errors"
"net"
"net/url"
)
@ -34,17 +35,33 @@ type Peer struct {
const (
None AnnounceEvent = iota
Completed
Started
Stopped
)
type Client interface {
Announce(*AnnounceRequest) (AnnounceResponse, error)
Connect() error
}
var schemes = make(map[string]func(*url.URL) Client)
var (
ErrNotConnected = errors.New("not connected")
ErrBadScheme = errors.New("unknown scheme")
schemes = make(map[string]func(*url.URL) Client)
)
func RegisterClientScheme(scheme string, newFunc func(*url.URL) Client) {
schemes[scheme] = newFunc
}
func New(url *url.URL) Client {
return schemes[url.Scheme](url)
func New(url *url.URL) (cl Client, err error) {
newFunc, ok := schemes[url.Scheme]
if !ok {
err = ErrBadScheme
return
}
cl = newFunc(url)
return
}

View File

@ -4,6 +4,7 @@ import (
"bitbucket.org/anacrolix/go.torrent/tracker"
"bytes"
"encoding/binary"
"errors"
"io"
"math/rand"
"net"
@ -57,7 +58,9 @@ func init() {
}
func newClient(url *url.URL) tracker.Client {
return &client{}
return &client{
url: url,
}
}
func newTransactionId() int32 {
@ -80,11 +83,12 @@ type client struct {
connectionIdReceived time.Time
connectionId int64
socket net.Conn
url *url.URL
}
func (c *client) Announce(req *tracker.AnnounceRequest) (res tracker.AnnounceResponse, err error) {
err = c.connect()
if err != nil {
if !c.connected() {
err = tracker.ErrNotConnected
return
}
b, err := c.request(Announce, req)
@ -124,9 +128,11 @@ func (c *client) write(h *RequestHeader, body interface{}) (err error) {
if err != nil {
panic(err)
}
err = binary.Write(buf, binary.BigEndian, body)
if err != nil {
panic(err)
if body != nil {
err = binary.Write(buf, binary.BigEndian, body)
if err != nil {
panic(err)
}
}
n, err := c.socket.Write(buf.Bytes())
if err != nil {
@ -172,9 +178,6 @@ func (c *client) request(action Action, args interface{}) (responseBody *bytes.R
default:
return
}
if h.Action != action {
continue
}
if h.TransactionId != tid {
continue
}
@ -197,11 +200,21 @@ func readBody(r *bytes.Reader, data ...interface{}) (err error) {
return
}
func (c *client) connect() (err error) {
if !c.connectionIdReceived.IsZero() && time.Now().Before(c.connectionIdReceived.Add(time.Minute)) {
func (c *client) connected() bool {
return !c.connectionIdReceived.IsZero() && time.Now().Before(c.connectionIdReceived.Add(time.Minute))
}
func (c *client) Connect() (err error) {
if c.connected() {
return nil
}
c.connectionId = 0x41727101980
if c.socket == nil {
c.socket, err = net.Dial("udp", c.url.Host)
if err != nil {
return
}
}
b, err := c.request(Connect, nil)
if err != nil {
return

View File

@ -1,10 +1,14 @@
package udp_tracker
import (
"bitbucket.org/anacrolix/go.torrent/tracker"
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"io"
"net"
"net/url"
"syscall"
"testing"
)
@ -78,3 +82,36 @@ func TestConvertInt16ToInt(t *testing.T) {
t.FailNow()
}
}
func TestUDPTracker(t *testing.T) {
tr, err := tracker.New(func() *url.URL {
u, err := url.Parse("udp://tracker.openbittorrent.com:80/announce")
if err != nil {
t.Fatal(err)
}
return u
}())
if err != nil {
t.Fatal(err)
}
if err := tr.Connect(); err != nil {
t.Fatal(err)
}
req := tracker.AnnounceRequest{
NumWant: -1,
Event: tracker.Started,
}
rand.Read(req.PeerId[:])
n, err := hex.Decode(req.InfoHash[:], []byte("c833bb2b5e7bcb9c07f4c020b4be430c28ba7cdb"))
if err != nil {
t.Fatal(err)
}
if n != len(req.InfoHash) {
panic("nope")
}
resp, err := tr.Announce(&req)
if err != nil {
t.Fatal(err)
}
t.Log(resp)
}