From 834e584f2d78cd06f9749889e2f8644eaf643ce0 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Mon, 30 Jun 2014 14:59:31 -0400 Subject: [PATCH] fix null ptrs, misuse of bencode --- config/config.go | 2 +- models/models.go | 6 +- server/serve_announce.go | 104 ++++++++++++++++------------------ server/serve_announce_test.go | 21 ++++++- server/serve_scrape.go | 7 ++- 5 files changed, 74 insertions(+), 66 deletions(-) diff --git a/config/config.go b/config/config.go index ded01ff..8b0f3b1 100644 --- a/config/config.go +++ b/config/config.go @@ -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}, diff --git a/models/models.go b/models/models.go index 24cf67e..957f36c 100644 --- a/models/models.go +++ b/models/models.go @@ -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{ diff --git a/server/serve_announce.go b/server/serve_announce.go index 45253a5..09d5741 100644 --- a/server/serve_announce.go +++ b/server/serve_announce.go @@ -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 { diff --git a/server/serve_announce_test.go b/server/serve_announce_test.go index b28c25c..4974f7b 100644 --- a/server/serve_announce_test.go +++ b/server/serve_announce_test.go @@ -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()) } diff --git a/server/serve_scrape.go b/server/serve_scrape.go index 78d3857..93ed05b 100644 --- a/server/serve_scrape.go +++ b/server/serve_scrape.go @@ -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") }