]> git.r.bdr.sh - rbdr/mobius/commitdiff
Fix intermittent tracker read panic
authorJeff Halter <redacted>
Wed, 28 Jul 2021 23:42:09 +0000 (16:42 -0700)
committerJeff Halter <redacted>
Wed, 28 Jul 2021 23:42:09 +0000 (16:42 -0700)
hotline/tracker.go

index 97ca1080e4e4abcc1f6856d60a096b6478395a78..d42ff7b52dbd0df0a6423d04db8c7e37f0bb4dfc 100644 (file)
@@ -3,6 +3,7 @@ package hotline
 import (
        "bytes"
        "encoding/binary"
+       "errors"
        "fmt"
        "github.com/jhalter/mobius/concat"
        "net"
@@ -11,10 +12,10 @@ import (
 )
 
 type TrackerRegistration struct {
-       Port        []byte // Server’s listening UDP port number TODO: wat?
+       Port        []byte // Server listening port number
        UserCount   int    // Number of users connected to this particular server
        PassID      []byte // Random number generated by the server
-       Name        string // Server’s name
+       Name        string // Server name
        Description string // Description of the server
 }
 
@@ -61,8 +62,6 @@ const trackerTimeout = 5 * time.Second
 // Version     2       1 or 2  Old protocol (1) or new (2)
 
 // Reply received from the tracker starts with a header:
-//
-
 type TrackerHeader struct {
        Protocol [4]byte // "HTRK" 0x4854524B
        Version  [2]byte // Old protocol (1) or new (2)
@@ -92,10 +91,8 @@ type ServerRecord struct {
 
 func GetListing(addr string) ([]ServerRecord, error) {
        conn, err := net.DialTimeout("tcp", addr, trackerTimeout)
-       if err != nil {
-               return nil, err
-       }
-       //spew.Dump(conn)
+       defer func() { _ = conn.Close() }()
+
        _, err = conn.Write(
                []byte{
                        0x48, 0x54, 0x52, 0x4B, // HTRK
@@ -108,12 +105,12 @@ func GetListing(addr string) ([]ServerRecord, error) {
 
        totalRead := 0
 
-       buf := make([]byte, 4096) // handshakes are always 12 bytes in length
+       buf := make([]byte, 4096)
        var readLen int
        if readLen, err = conn.Read(buf); err != nil {
                return nil, err
        }
-       totalRead += readLen
+       totalRead += readLen  // 1514
 
        var th TrackerHeader
        if err := binary.Read(bytes.NewReader(buf[:6]), binary.BigEndian, &th); err != nil {
@@ -129,47 +126,39 @@ func GetListing(addr string) ([]ServerRecord, error) {
 
        if totalRead < payloadSize {
                for {
-                       //fmt.Printf("totalRead: %v", totalRead)
-                       //fmt.Printf("readLen: %v Payload size: %v, Server count: %x\n", readLen, payloadSize, info.SrvCount)
-
-                       if readLen, err = conn.Read(buf); err != nil {
+                       tmpBuf := make([]byte, 4096)
+                       if readLen, err = conn.Read(tmpBuf); err != nil {
                                return nil, err
                        }
+                       buf = append(buf, tmpBuf[:readLen]...)
                        totalRead += readLen
                        if totalRead >= payloadSize {
                                break
                        }
                }
        }
-       //fmt.Println("passed read")
        totalSrv := int(binary.BigEndian.Uint16(info.SrvCount[:]))
 
-       //fmt.Printf("readLen: %v Payload size: %v, Server count: %x\n", readLen, payloadSize, info.SrvCount)
        srvBuf := buf[14:totalRead]
-
        totalRead += readLen
 
        var servers []ServerRecord
+
        for {
                var srv ServerRecord
                n, _ := srv.Read(srvBuf)
                servers = append(servers, srv)
 
                srvBuf = srvBuf[n:]
-               //      fmt.Printf("srvBuf len: %v\n", len(srvBuf))
+
                if len(servers) == totalSrv {
                        return servers, nil
                }
 
                if len(srvBuf) == 0 {
-                       if readLen, err = conn.Read(buf); err != nil {
-                               return nil, err
-                       }
-                       srvBuf = buf[8:readLen]
+                       return servers, errors.New("tracker sent too few bytes for server count")
                }
        }
-
-       return servers, nil
 }
 
 func (s *ServerRecord) Read(b []byte) (n int, err error) {