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{
Driver: "mock",
},
Private: true,
Private: false,
Freeleech: false,
Announce: Duration{30 * 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
if u == nil {
if u != nil {
userID = u.ID
}
var torrentID uint64
if t == nil {
torrentID = u.ID
if t != nil {
torrentID = t.ID
}
return &Peer{

View file

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

View file

@ -5,6 +5,7 @@
package server
import (
"net"
"net/http"
"net/http/httptest"
"testing"
@ -42,11 +43,25 @@ func TestAnnounce(t *testing.T) {
return
}
err = conn.AddTorrent(&models.Torrent{
torrent := &models.Torrent{
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}),
Seeders: 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
@ -55,7 +70,7 @@ func TestAnnounce(t *testing.T) {
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)
if err != nil {
t.Error(err)
@ -64,7 +79,7 @@ func TestAnnounce(t *testing.T) {
w := httptest.NewRecorder()
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())
}

View file

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