make it compile!

This commit is contained in:
Jimmy Zelinskie
2016-08-05 01:47:04 -04:00
parent b5de90345e
commit 5c99738b7f
17 changed files with 361 additions and 185 deletions

View File

@@ -32,14 +32,9 @@ func ParseAnnounce(r *http.Request, realIPHeader string, allowIPSpoofing bool) (
return nil, err
}
request := &bittorrent.AnnounceRequest{Params: q}
request := &bittorrent.AnnounceRequest{Params: qp}
eventStr, err := qp.String("event")
if err == query.ErrKeyNotFound {
eventStr = ""
} else if err != nil {
return nil, bittorrent.ClientError("failed to parse parameter: event")
}
eventStr, _ := qp.String("event")
request.Event, err = bittorrent.NewEvent(eventStr)
if err != nil {
return nil, bittorrent.ClientError("failed to provide valid client event")
@@ -57,14 +52,14 @@ func ParseAnnounce(r *http.Request, realIPHeader string, allowIPSpoofing bool) (
}
request.InfoHash = infoHashes[0]
peerID, err := qp.String("peer_id")
if err != nil {
peerID, ok := qp.String("peer_id")
if !ok {
return nil, bittorrent.ClientError("failed to parse parameter: peer_id")
}
if len(peerID) != 20 {
return nil, bittorrent.ClientError("failed to provide valid peer_id")
}
request.PeerID = bittorrent.PeerIDFromString(peerID)
request.Peer.ID = bittorrent.PeerIDFromString(peerID)
request.Left, err = qp.Uint64("left")
if err != nil {
@@ -85,24 +80,24 @@ func ParseAnnounce(r *http.Request, realIPHeader string, allowIPSpoofing bool) (
if err != nil {
return nil, bittorrent.ClientError("failed to parse parameter: numwant")
}
request.NumWant = int32(numwant)
request.NumWant = uint32(numwant)
port, err := qp.Uint64("port")
if err != nil {
return nil, bittorrent.ClientError("failed to parse parameter: port")
}
request.Port = uint16(port)
request.Peer.Port = uint16(port)
request.IP, err = requestedIP(q, r, realIPHeader, allowIPSpoofing)
if err != nil {
return nil, bittorrent.ClientError("failed to parse peer IP address: " + err.Error())
request.Peer.IP = requestedIP(r, qp, realIPHeader, allowIPSpoofing)
if request.Peer.IP == nil {
return nil, bittorrent.ClientError("failed to parse peer IP address")
}
return request, nil
}
// ParseScrape parses an bittorrent.ScrapeRequest from an http.Request.
func ParseScrape(r *http.Request) (*bittorent.ScrapeRequest, error) {
func ParseScrape(r *http.Request) (*bittorrent.ScrapeRequest, error) {
qp, err := NewQueryParams(r.URL.RawQuery)
if err != nil {
return nil, err
@@ -115,7 +110,7 @@ func ParseScrape(r *http.Request) (*bittorent.ScrapeRequest, error) {
request := &bittorrent.ScrapeRequest{
InfoHashes: infoHashes,
Params: q,
Params: qp,
}
return request, nil
@@ -126,46 +121,31 @@ func ParseScrape(r *http.Request) (*bittorent.ScrapeRequest, error) {
// If allowIPSpoofing is true, IPs provided via params will be used.
// If realIPHeader is not empty string, the first value of the HTTP Header with
// that name will be used.
func requestedIP(r *http.Request, p bittorent.Params, realIPHeader string, allowIPSpoofing bool) (net.IP, error) {
func requestedIP(r *http.Request, p bittorrent.Params, realIPHeader string, allowIPSpoofing bool) net.IP {
if allowIPSpoofing {
if ipstr, err := p.String("ip"); err == nil {
ip, err := net.ParseIP(str)
if err != nil {
return nil, err
}
return ip, nil
if ipstr, ok := p.String("ip"); ok {
ip := net.ParseIP(ipstr)
return ip
}
if ipstr, err := p.String("ipv4"); err == nil {
ip, err := net.ParseIP(str)
if err != nil {
return nil, err
}
return ip, nil
if ipstr, ok := p.String("ipv4"); ok {
ip := net.ParseIP(ipstr)
return ip
}
if ipstr, err := p.String("ipv6"); err == nil {
ip, err := net.ParseIP(str)
if err != nil {
return nil, err
}
return ip, nil
if ipstr, ok := p.String("ipv6"); ok {
ip := net.ParseIP(ipstr)
return ip
}
}
if realIPHeader != "" {
if ips, ok := r.Header[realIPHeader]; ok && len(ips) > 0 {
ip, err := net.ParseIP(ips[0])
if err != nil {
return nil, err
}
return ip, nil
ip := net.ParseIP(ips[0])
return ip
}
}
return r.RemoteAddr
host, _, _ := net.SplitHostPort(r.RemoteAddr)
return net.ParseIP(host)
}

View File

@@ -40,14 +40,14 @@ type QueryParams struct {
}
// NewQueryParams parses a raw URL query.
func NewQueryParams(query string) (*Query, error) {
func NewQueryParams(query string) (*QueryParams, error) {
var (
keyStart, keyEnd int
valStart, valEnd int
onKey = true
q = &Query{
q = &QueryParams{
query: query,
infoHashes: nil,
params: make(map[string]string),
@@ -111,18 +111,15 @@ func NewQueryParams(query string) (*Query, error) {
// String returns a string parsed from a query. Every key can be returned as a
// string because they are encoded in the URL as strings.
func (q *Query) String(key string) (string, error) {
val, exists := q.params[key]
if !exists {
return "", ErrKeyNotFound
}
return val, nil
func (qp *QueryParams) String(key string) (string, bool) {
value, ok := qp.params[key]
return value, ok
}
// Uint64 returns a uint parsed from a query. After being called, it is safe to
// cast the uint64 to your desired length.
func (q *Query) Uint64(key string) (uint64, error) {
str, exists := q.params[key]
func (qp *QueryParams) Uint64(key string) (uint64, error) {
str, exists := qp.params[key]
if !exists {
return 0, ErrKeyNotFound
}
@@ -136,6 +133,6 @@ func (q *Query) Uint64(key string) (uint64, error) {
}
// InfoHashes returns a list of requested infohashes.
func (q *Query) InfoHashes() []bittorrent.InfoHash {
return q.infoHashes
func (qp *QueryParams) InfoHashes() []bittorrent.InfoHash {
return qp.infoHashes
}

View File

@@ -16,6 +16,19 @@
// described in BEP 3 and BEP 23.
package http
import (
"net"
"net/http"
"time"
"github.com/julienschmidt/httprouter"
"github.com/prometheus/client_golang/prometheus"
"github.com/tylerb/graceful"
"golang.org/x/net/context"
"github.com/jzelinskie/trakr/bittorrent"
)
var promResponseDurationMilliseconds = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "trakr_http_response_duration_milliseconds",
@@ -27,9 +40,14 @@ var promResponseDurationMilliseconds = prometheus.NewHistogramVec(
// recordResponseDuration records the duration of time to respond to a UDP
// Request in milliseconds .
func recordResponseDuration(action, err error, duration time.Duration) {
func recordResponseDuration(action string, err error, duration time.Duration) {
var errString string
if err != nil {
errString = err.Error()
}
promResponseDurationMilliseconds.
WithLabelValues(action, err.Error()).
WithLabelValues(action, errString).
Observe(float64(duration.Nanoseconds()) / float64(time.Millisecond))
}
@@ -53,8 +71,8 @@ type Tracker struct {
}
// NewTracker allocates a new instance of a Tracker.
func NewTracker(funcs bittorrent.TrackerFuncs, cfg Config) {
return &Server{
func NewTracker(funcs bittorrent.TrackerFuncs, cfg Config) *Tracker {
return &Tracker{
TrackerFuncs: funcs,
Config: cfg,
}
@@ -66,11 +84,11 @@ func (t *Tracker) Stop() {
<-t.grace.StopChan()
}
func (t *Tracker) handler() {
func (t *Tracker) handler() http.Handler {
router := httprouter.New()
router.GET("/announce", t.announceRoute)
router.GET("/scrape", t.scrapeRoute)
return server
return router
}
// ListenAndServe listens on the TCP network address t.Addr and blocks serving
@@ -111,18 +129,15 @@ func (t *Tracker) ListenAndServe() error {
panic("http: failed to gracefully run HTTP server: " + err.Error())
}
}
return nil
}
// announceRoute parses and responds to an Announce by using t.TrackerFuncs.
func (t *Tracker) announceRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
var err error
start := time.Now()
defer func() {
var errString string
if err != nil {
errString = err.Error()
}
recordResponseDuration("announce", errString, time.Since(start))
}()
defer recordResponseDuration("announce", err, time.Since(start))
req, err := ParseAnnounce(r, t.RealIPHeader, t.AllowIPSpoofing)
if err != nil {
@@ -130,7 +145,7 @@ func (t *Tracker) announceRoute(w http.ResponseWriter, r *http.Request, _ httpro
return
}
resp, err := t.HandleAnnounce(req)
resp, err := t.HandleAnnounce(context.TODO(), req)
if err != nil {
WriteError(w, err)
return
@@ -145,19 +160,13 @@ func (t *Tracker) announceRoute(w http.ResponseWriter, r *http.Request, _ httpro
if t.AfterAnnounce != nil {
go t.AfterAnnounce(req, resp)
}
recordResponseDuration("announce")
}
// scrapeRoute parses and responds to a Scrape by using t.TrackerFuncs.
func (t *Tracker) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
var err error
start := time.Now()
defer func() {
var errString string
if err != nil {
errString = err.Error()
}
recordResponseDuration("scrape", errString, time.Since(start))
}()
defer recordResponseDuration("scrape", err, time.Since(start))
req, err := ParseScrape(r)
if err != nil {
@@ -165,7 +174,7 @@ func (t *Tracker) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprout
return
}
resp, err := t.HandleScrape(req)
resp, err := t.HandleScrape(context.TODO(), req)
if err != nil {
WriteError(w, err)
return

View File

@@ -18,6 +18,7 @@ import (
"net/http"
"github.com/jzelinskie/trakr/bittorrent"
"github.com/jzelinskie/trakr/bittorrent/http/bencode"
)
// WriteError communicates an error to a BitTorrent client over HTTP.

View File

@@ -18,8 +18,9 @@ import (
"net/http/httptest"
"testing"
"github.com/jzelinskie/trakr/bittorrent"
"github.com/stretchr/testify/assert"
"github.com/jzelinskie/trakr/bittorrent"
)
func TestWriteError(t *testing.T) {