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{
|
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},
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue