fix null ptrs, misuse of bencode
This commit is contained in:
parent
ac45708bfd
commit
834e584f2d
5 changed files with 74 additions and 66 deletions
|
@ -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},
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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()
|
||||
|
||||
log.V(5).Infof(
|
||||
"announce: ip: %s, user: %s, torrent: %s",
|
||||
announce.IP,
|
||||
user.ID,
|
||||
torrent.ID,
|
||||
)
|
||||
if s.conf.Private {
|
||||
|
||||
log.V(5).Infof(
|
||||
"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)
|
||||
bencoder.Encode("peers")
|
||||
bencoder.Encode("l")
|
||||
ipv4s, ipv6s := getPeers(a, u, t, peerCount)
|
||||
|
||||
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)
|
||||
bencoder.Encode("peers")
|
||||
fmt.Fprintf(w, "l")
|
||||
|
||||
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")
|
||||
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
|
||||
fmt.Fprintf(w, "d")
|
||||
bencoder.Encode("ip")
|
||||
bencoder.Encode(peer.IP.String())
|
||||
bencoder.Encode("peer id")
|
||||
bencoder.Encode(peer.ID)
|
||||
bencoder.Encode("port")
|
||||
bencoder.Encode(peer.Port)
|
||||
fmt.Fprintf(w, "e")
|
||||
}
|
||||
|
||||
func minInt(a, b int) int {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue