fix null ptrs, misuse of bencode

This commit is contained in:
Jimmy Zelinskie 2014-06-30 14:59:31 -04:00
parent ac45708bfd
commit 834e584f2d
5 changed files with 74 additions and 66 deletions

View file

@ -74,7 +74,7 @@ func New() *Config {
Backend: DriverConfig{ Backend: DriverConfig{
Driver: "mock", Driver: "mock",
}, },
Private: true, Private: false,
Freeleech: false, Freeleech: false,
Announce: Duration{30 * time.Minute}, Announce: Duration{30 * time.Minute},
MinAnnounce: Duration{15 * time.Minute}, MinAnnounce: Duration{15 * time.Minute},

View file

@ -49,13 +49,13 @@ func NewPeer(a *Announce, u *User, t *Torrent) *Peer {
} }
var userID uint64 var userID uint64
if u == nil { if u != nil {
userID = u.ID userID = u.ID
} }
var torrentID uint64 var torrentID uint64
if t == nil { if t != nil {
torrentID = u.ID torrentID = t.ID
} }
return &Peer{ return &Peer{

View file

@ -5,9 +5,9 @@
package server package server
import ( import (
"fmt"
"io" "io"
"net/http" "net/http"
"strconv"
log "github.com/golang/glog" log "github.com/golang/glog"
@ -73,12 +73,21 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
w.(http.Flusher).Flush() w.(http.Flusher).Flush()
log.V(5).Infof( if s.conf.Private {
"announce: ip: %s, user: %s, torrent: %s",
announce.IP, log.V(5).Infof(
user.ID, "announce: ip: %s user: %s torrent: %s",
torrent.ID, announce.IP,
) user.ID,
torrent.ID,
)
} else {
log.V(5).Infof(
"announce: ip: %s torrent: %s",
announce.IP,
torrent.ID,
)
}
} }
func updateTorrent(c tracker.Conn, a *models.Announce, p *models.Peer, t *models.Torrent) (created bool, err error) { func updateTorrent(c tracker.Conn, a *models.Announce, p *models.Peer, t *models.Torrent) (created bool, err error) {
@ -173,7 +182,7 @@ func writeAnnounceResponse(w io.Writer, a *models.Announce, u *models.User, t *m
} }
bencoder := bencode.NewEncoder(w) bencoder := bencode.NewEncoder(w)
bencoder.Encode("d") fmt.Fprintf(w, "d")
bencoder.Encode("complete") bencoder.Encode("complete")
bencoder.Encode(seedCount) bencoder.Encode(seedCount)
bencoder.Encode("incomplete") bencoder.Encode("incomplete")
@ -191,18 +200,16 @@ func writeAnnounceResponse(w io.Writer, a *models.Announce, u *models.User, t *m
} }
} }
bencoder.Encode("e") fmt.Fprintf(w, "e")
} }
func writePeersCompact(w io.Writer, a *models.Announce, u *models.User, t *models.Torrent, peerCount int) { func writePeersCompact(w io.Writer, a *models.Announce, u *models.User, t *models.Torrent, peerCount int) {
ipv4s, ipv6s := getPeers(a, u, t, peerCount) ipv4s, ipv6s := getPeers(a, u, t, peerCount)
bencoder := bencode.NewEncoder(w)
if len(ipv4s) > 0 { if len(ipv4s) > 0 {
// 6 is the number of bytes that represents 1 compact IPv4 address. // 6 is the number of bytes that represents 1 compact IPv4 address.
bencoder.Encode("peers") fmt.Fprintf(w, "peers%d:", len(ipv4s)*6)
bencoder.Encode(strconv.Itoa(len(ipv4s) * 6))
bencoder.Encode(":")
for _, peer := range ipv4s { for _, peer := range ipv4s {
if ip := peer.IP.To4(); ip != nil { if ip := peer.IP.To4(); ip != nil {
w.Write(ip) w.Write(ip)
@ -213,8 +220,8 @@ func writePeersCompact(w io.Writer, a *models.Announce, u *models.User, t *model
if len(ipv6s) > 0 { if len(ipv6s) > 0 {
// 18 is the number of bytes that represents 1 compact IPv6 address. // 18 is the number of bytes that represents 1 compact IPv6 address.
bencoder.Encode("peers6") fmt.Fprintf(w, "peers6%d:", len(ipv6s)*18)
bencoder.Encode(strconv.Itoa(len(ipv6s) * 18))
for _, peer := range ipv6s { for _, peer := range ipv6s {
if ip := peer.IP.To16(); ip != nil { if ip := peer.IP.To16(); ip != nil {
w.Write(ip) w.Write(ip)
@ -227,29 +234,29 @@ func writePeersCompact(w io.Writer, a *models.Announce, u *models.User, t *model
func getPeers(a *models.Announce, u *models.User, t *models.Torrent, peerCount int) (ipv4s, ipv6s []*models.Peer) { func getPeers(a *models.Announce, u *models.User, t *models.Torrent, peerCount int) (ipv4s, ipv6s []*models.Peer) {
if a.Left == 0 { if a.Left == 0 {
// If they're seeding, give them only leechers. // If they're seeding, give them only leechers.
splitPeers(&ipv4s, &ipv6s, u, t.Leechers, peerCount) splitPeers(&ipv4s, &ipv6s, a, u, t.Leechers, peerCount)
} else { } else {
// If they're leeching, prioritize giving them seeders. // If they're leeching, prioritize giving them seeders.
count := splitPeers(&ipv4s, &ipv6s, u, t.Seeders, peerCount) count := splitPeers(&ipv4s, &ipv6s, a, u, t.Seeders, peerCount)
splitPeers(&ipv4s, &ipv6s, u, t.Leechers, peerCount-count) splitPeers(&ipv4s, &ipv6s, a, u, t.Leechers, peerCount-count)
} }
return return
} }
func splitPeers(ipv4s, ipv6s *[]*models.Peer, u *models.User, peers map[string]models.Peer, peerCount int) (count int) { func splitPeers(ipv4s, ipv6s *[]*models.Peer, a *models.Announce, u *models.User, peers map[string]models.Peer, peerCount int) (count int) {
for _, peer := range peers { for _, peer := range peers {
if count >= peerCount { if count >= peerCount {
break break
} }
if peer.UserID == u.ID { if a.Config.Private && peer.UserID == u.ID {
continue continue
} }
if ip := peer.IP.To4(); ip != nil { if ip := peer.IP.To4(); len(ip) == 4 {
*ipv4s = append(*ipv4s, &peer) *ipv4s = append(*ipv4s, &peer)
} else { } else if ip := peer.IP.To16(); len(ip) == 16 {
*ipv6s = append(*ipv6s, &peer) *ipv6s = append(*ipv6s, &peer)
} }
@ -261,46 +268,31 @@ func splitPeers(ipv4s, ipv6s *[]*models.Peer, u *models.User, peers map[string]m
func writePeersList(w io.Writer, a *models.Announce, u *models.User, t *models.Torrent, peerCount int) { func writePeersList(w io.Writer, a *models.Announce, u *models.User, t *models.Torrent, peerCount int) {
bencoder := bencode.NewEncoder(w) bencoder := bencode.NewEncoder(w)
bencoder.Encode("peers") ipv4s, ipv6s := getPeers(a, u, t, peerCount)
bencoder.Encode("l")
if a.Left == 0 { bencoder.Encode("peers")
// If they're seeding, give them only leechers fmt.Fprintf(w, "l")
writePeerDicts(w, u, t.Leechers, peerCount)
} else { for _, peer := range ipv4s {
// If they're leeching, prioritize giving them seeders writePeerDict(w, peer)
count := writePeerDicts(w, u, t.Seeders, peerCount) }
writePeerDicts(w, u, t.Leechers, peerCount-count) for _, peer := range ipv6s {
writePeerDict(w, peer)
} }
bencoder.Encode("e") fmt.Fprintf(w, "e")
} }
func writePeerDicts(w io.Writer, u *models.User, peers map[string]models.Peer, peerCount int) (count int) { func writePeerDict(w io.Writer, peer *models.Peer) {
bencoder := bencode.NewEncoder(w) bencoder := bencode.NewEncoder(w)
fmt.Fprintf(w, "d")
for _, peer := range peers { bencoder.Encode("ip")
if count >= peerCount { bencoder.Encode(peer.IP.String())
break bencoder.Encode("peer id")
} bencoder.Encode(peer.ID)
bencoder.Encode("port")
if peer.UserID == u.ID { bencoder.Encode(peer.Port)
continue fmt.Fprintf(w, "e")
}
bencoder.Encode("d")
bencoder.Encode("ip")
bencoder.Encode(peer.IP)
bencoder.Encode("peer id")
bencoder.Encode(peer.ID)
bencoder.Encode("port")
bencoder.Encode(peer.Port)
bencoder.Encode("e")
count++
}
return count
} }
func minInt(a, b int) int { func minInt(a, b int) int {

View file

@ -5,6 +5,7 @@
package server package server
import ( import (
"net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@ -42,11 +43,25 @@ func TestAnnounce(t *testing.T) {
return return
} }
err = conn.AddTorrent(&models.Torrent{ torrent := &models.Torrent{
ID: 1, ID: 1,
Infohash: string([]byte{0x89, 0xd4, 0xbc, 0x52, 0x11, 0x16, 0xca, 0x1d, 0x42, 0xa2, 0xf3, 0x0d, 0x1f, 0x27, 0x4d, 0x94, 0xe4, 0x68, 0x1d, 0xaf}), Infohash: string([]byte{0x89, 0xd4, 0xbc, 0x52, 0x11, 0x16, 0xca, 0x1d, 0x42, 0xa2, 0xf3, 0x0d, 0x1f, 0x27, 0x4d, 0x94, 0xe4, 0x68, 0x1d, 0xaf}),
Seeders: make(map[string]models.Peer), Seeders: make(map[string]models.Peer),
Leechers: make(map[string]models.Peer), Leechers: make(map[string]models.Peer),
}
err = conn.AddTorrent(torrent)
if err != nil {
return
}
err = conn.AddLeecher(torrent, &models.Peer{
ID: "-TR2820-l71jtqkl898b",
UserID: 1,
TorrentID: torrent.ID,
IP: net.ParseIP("127.0.0.1"),
Port: 34000,
Left: 0,
}) })
return return
@ -55,7 +70,7 @@ func TestAnnounce(t *testing.T) {
t.Error(err) t.Error(err)
} }
url := "http://localhost:34000/yby47f04riwpndba456rqxtmifenq5h6/announce?info_hash=%89%d4%bcR%11%16%ca%1dB%a2%f3%0d%1f%27M%94%e4h%1d%af&peer_id=-TR2820-l71jtqkl898b&port=51413&uploaded=0&downloaded=0&left=0&numwant=0&key=3c8e3319&compact=1&supportcrypto=1&event=stopped" url := "http://localhost:6881/yby47f04riwpndba456rqxtmifenq5h6/announce?info_hash=%89%d4%bcR%11%16%ca%1dB%a2%f3%0d%1f%27M%94%e4h%1d%af&peer_id=-TR2820-l71jtqkl898b&port=51413&uploaded=0&downloaded=0&left=0&numwant=1&key=3c8e3319&compact=0&supportcrypto=1"
r, err := http.NewRequest("GET", url, nil) r, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -64,7 +79,7 @@ func TestAnnounce(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
s.serveAnnounce(w, r) s.serveAnnounce(w, r)
if w.Body.String() != "1:d8:completei0e10:incompletei0e8:intervali1800e12:min intervali900e1:e" { if w.Body.String() != "d8:completei1e10:incompletei1e8:intervali1800e12:min intervali900e5:peersld2:ip9:127.0.0.17:peer id20:-TR2820-l71jtqkl898b4:porti34000eeee" {
t.Errorf("improper response from server:\n%s", w.Body.String()) t.Errorf("improper response from server:\n%s", w.Body.String())
} }

View file

@ -5,6 +5,7 @@
package server package server
import ( import (
"fmt"
"io" "io"
"net/http" "net/http"
"strings" "strings"
@ -70,13 +71,13 @@ func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request) {
func writeTorrentStatus(w io.Writer, t *models.Torrent) { func writeTorrentStatus(w io.Writer, t *models.Torrent) {
bencoder := bencode.NewEncoder(w) bencoder := bencode.NewEncoder(w)
bencoder.Encode("t.Infohash") bencoder.Encode(t.Infohash)
bencoder.Encode("d") fmt.Fprintf(w, "d")
bencoder.Encode("complete") bencoder.Encode("complete")
bencoder.Encode(len(t.Seeders)) bencoder.Encode(len(t.Seeders))
bencoder.Encode("downloaded") bencoder.Encode("downloaded")
bencoder.Encode(t.Snatches) bencoder.Encode(t.Snatches)
bencoder.Encode("incomplete") bencoder.Encode("incomplete")
bencoder.Encode(len(t.Leechers)) bencoder.Encode(len(t.Leechers))
bencoder.Encode("e") fmt.Fprintf(w, "e")
} }