aboutsummaryrefslogtreecommitdiff
path: root/hotline
diff options
context:
space:
mode:
authorJeff Halter <868228+jhalter@users.noreply.github.com>2025-11-25 10:30:30 -0800
committerJeff Halter <868228+jhalter@users.noreply.github.com>2025-11-25 10:31:39 -0800
commit8ddb9bb228389b198a76d6df21de005da4fad66b (patch)
treee6e1d8de46beaf8e79fc8aa7edfe4c7263799fe9 /hotline
parentab16c7d82c8381a4df80fef4b2fe81e7ff23dad8 (diff)
Add TLS port field to tracker registration protocol
Repurpose the previously unused 2-byte field in the tracker protocol to advertise the server's TLS port. This allows clients to discover which servers support TLS connections. Note: currently only the official, original, 1990's Tracker software sends this server provided 2-byte field to tracker clients. I'm adding this to Mobius in the hope that the modern day trackers might update their behavior to match the original software, which would put these unused 2 bytes to a useful purpose.
Diffstat (limited to 'hotline')
-rw-r--r--hotline/server.go1
-rw-r--r--hotline/tracker.go9
-rw-r--r--hotline/tracker_test.go90
3 files changed, 51 insertions, 49 deletions
diff --git a/hotline/server.go b/hotline/server.go
index 2c25e93..9b74d99 100644
--- a/hotline/server.go
+++ b/hotline/server.go
@@ -368,6 +368,7 @@ func (s *Server) registerWithAllTrackers() {
Description: s.Config.Description,
}
binary.BigEndian.PutUint16(tr.Port[:], uint16(s.Port))
+ binary.BigEndian.PutUint16(tr.TLSPort[:], uint16(s.TLSPort))
tr.Password = parseTrackerPassword(t)
diff --git a/hotline/tracker.go b/hotline/tracker.go
index bfba69d..ee4fc05 100644
--- a/hotline/tracker.go
+++ b/hotline/tracker.go
@@ -15,6 +15,7 @@ import (
type TrackerRegistration struct {
Port [2]byte // Server's listening TCP port number
UserCount int // Number of users connected to this particular server
+ TLSPort [2]byte // TLSPort
PassID [4]byte // Random number generated by the server
Name string // Server Name
Description string // Description of the server
@@ -32,7 +33,7 @@ func (tr *TrackerRegistration) Read(p []byte) (int, error) {
[]byte{0x00, 0x01}, // Magic number, always 1
tr.Port[:],
userCount,
- []byte{0x00, 0x00}, // Magic number, always 0
+ tr.TLSPort[:],
tr.PassID[:],
[]byte{uint8(len(tr.Name))},
[]byte(tr.Name),
@@ -114,7 +115,7 @@ type ServerRecord struct {
IPAddr [4]byte
Port [2]byte
NumUsers [2]byte // Number of users connected to this particular server
- Unused [2]byte
+ TLSPort [2]byte
NameSize byte // Length of Name string
Name []byte // Server Name
DescriptionSize byte
@@ -182,7 +183,7 @@ func GetListing(conn io.ReadWriteCloser) ([]ServerRecord, error) {
func readServerRecord(reader *bufio.Reader) (ServerRecord, error) {
var srv ServerRecord
- // Read fixed header: IP (4) + Port (2) + NumUsers (2) + Unused (2) = 10 bytes
+ // Read fixed header: IP (4) + Port (2) + NumUsers (2) + TLSPort (2) = 10 bytes
header := make([]byte, 10)
if _, err := io.ReadFull(reader, header); err != nil {
return srv, fmt.Errorf("failed to read server header: %w", err)
@@ -191,7 +192,7 @@ func readServerRecord(reader *bufio.Reader) (ServerRecord, error) {
copy(srv.IPAddr[:], header[0:4])
copy(srv.Port[:], header[4:6])
copy(srv.NumUsers[:], header[6:8])
- copy(srv.Unused[:], header[8:10])
+ copy(srv.TLSPort[:], header[8:10])
// Read name size
nameSizeByte, err := reader.ReadByte()
diff --git a/hotline/tracker_test.go b/hotline/tracker_test.go
index 8295582..242deb1 100644
--- a/hotline/tracker_test.go
+++ b/hotline/tracker_test.go
@@ -104,7 +104,7 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 1, // IP address
0x1F, 0x90, // Port 8080
0x00, 0x10, // NumUsers 16
- 0x00, 0x00, // Unused
+ 0x00, 0x00, // TLSPort
0x04, // NameSize
'S', 'e', 'r', 'v', // Name
0x0B, // DescriptionSize
@@ -113,7 +113,7 @@ func TestGetListing(t *testing.T) {
10, 0, 0, 1, // IP address
0x1F, 0x91, // Port 8081
0x00, 0x05, // NumUsers 5
- 0x00, 0x00, // Unused
+ 0x00, 0x00, // TLSPort
0x04, // NameSize
'S', 'e', 'r', 'v', // Name
0x0B, // DescriptionSize
@@ -127,7 +127,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 1},
Port: [2]byte{0x1F, 0x90},
NumUsers: [2]byte{0x00, 0x10},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 4,
Name: []byte("Serv"),
DescriptionSize: 11,
@@ -137,7 +137,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{10, 0, 0, 1},
Port: [2]byte{0x1F, 0x91},
NumUsers: [2]byte{0x00, 0x05},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 4,
Name: []byte("Serv"),
DescriptionSize: 11,
@@ -217,19 +217,19 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 1, // IP address
0x1F, 0x90, // Port 8080
0x00, 0x0A, // NumUsers 10
- 0x00, 0x00, // Unused
- 0x07, // NameSize
+ 0x00, 0x00, // TLSPort
+ 0x07, // NameSize
'S', 'e', 'r', 'v', 'e', 'r', '1', // Name
- 0x0C, // DescriptionSize
+ 0x0C, // DescriptionSize
'F', 'i', 'r', 's', 't', ' ', 'b', 'a', 't', 'c', 'h', '1', // Description
// ServerRecord 2
192, 168, 1, 2, // IP address
0x1F, 0x91, // Port 8081
0x00, 0x14, // NumUsers 20
- 0x00, 0x00, // Unused
- 0x07, // NameSize
+ 0x00, 0x00, // TLSPort
+ 0x07, // NameSize
'S', 'e', 'r', 'v', 'e', 'r', '2', // Name
- 0x0C, // DescriptionSize
+ 0x0C, // DescriptionSize
'F', 'i', 'r', 's', 't', ' ', 'b', 'a', 't', 'c', 'h', '2', // Description
// Second ServerInfoHeader (next batch)
0x00, 0x01, // MsgType (1)
@@ -240,10 +240,10 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 3, // IP address
0x1F, 0x92, // Port 8082
0x00, 0x1E, // NumUsers 30
- 0x00, 0x00, // Unused
- 0x07, // NameSize
+ 0x00, 0x00, // TLSPort
+ 0x07, // NameSize
'S', 'e', 'r', 'v', 'e', 'r', '3', // Name
- 0x0D, // DescriptionSize
+ 0x0D, // DescriptionSize
'S', 'e', 'c', 'o', 'n', 'd', ' ', 'b', 'a', 't', 'c', 'h', '1', // Description
}),
writeBuffer: &bytes.Buffer{},
@@ -254,7 +254,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 1},
Port: [2]byte{0x1F, 0x90},
NumUsers: [2]byte{0x00, 0x0A},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 7,
Name: []byte("Server1"),
DescriptionSize: 12,
@@ -264,7 +264,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 2},
Port: [2]byte{0x1F, 0x91},
NumUsers: [2]byte{0x00, 0x14},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 7,
Name: []byte("Server2"),
DescriptionSize: 12,
@@ -274,7 +274,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 3},
Port: [2]byte{0x1F, 0x92},
NumUsers: [2]byte{0x00, 0x1E},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 7,
Name: []byte("Server3"),
DescriptionSize: 13,
@@ -298,20 +298,20 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 1, // IP
0x15, 0x7c, // Port 5500
0x00, 0x01, // NumUsers 1
- 0x00, 0x00, // Unused
- 0x01, // NameSize
- 'A', // Name
- 0x01, // DescriptionSize
- '1', // Description
+ 0x00, 0x00, // TLSPort
+ 0x01, // NameSize
+ 'A', // Name
+ 0x01, // DescriptionSize
+ '1', // Description
// ServerRecord 2
192, 168, 1, 2, // IP
0x15, 0x7c, // Port 5500
0x00, 0x02, // NumUsers 2
- 0x00, 0x00, // Unused
- 0x01, // NameSize
- 'B', // Name
- 0x01, // DescriptionSize
- '2', // Description
+ 0x00, 0x00, // TLSPort
+ 0x01, // NameSize
+ 'B', // Name
+ 0x01, // DescriptionSize
+ '2', // Description
// Second ServerInfoHeader
0x00, 0x01, // MsgType (1)
0x00, 0x0A, // MsgDataSize
@@ -321,11 +321,11 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 3, // IP
0x15, 0x7c, // Port 5500
0x00, 0x03, // NumUsers 3
- 0x00, 0x00, // Unused
- 0x01, // NameSize
- 'C', // Name
- 0x01, // DescriptionSize
- '3', // Description
+ 0x00, 0x00, // TLSPort
+ 0x01, // NameSize
+ 'C', // Name
+ 0x01, // DescriptionSize
+ '3', // Description
// Third ServerInfoHeader
0x00, 0x01, // MsgType (1)
0x00, 0x0A, // MsgDataSize
@@ -335,11 +335,11 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 4, // IP
0x15, 0x7c, // Port 5500
0x00, 0x04, // NumUsers 4
- 0x00, 0x00, // Unused
- 0x01, // NameSize
- 'D', // Name
- 0x01, // DescriptionSize
- '4', // Description
+ 0x00, 0x00, // TLSPort
+ 0x01, // NameSize
+ 'D', // Name
+ 0x01, // DescriptionSize
+ '4', // Description
}),
writeBuffer: &bytes.Buffer{},
},
@@ -349,7 +349,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 1},
Port: [2]byte{0x15, 0x7c},
NumUsers: [2]byte{0x00, 0x01},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 1,
Name: []byte("A"),
DescriptionSize: 1,
@@ -359,7 +359,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 2},
Port: [2]byte{0x15, 0x7c},
NumUsers: [2]byte{0x00, 0x02},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 1,
Name: []byte("B"),
DescriptionSize: 1,
@@ -369,7 +369,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 3},
Port: [2]byte{0x15, 0x7c},
NumUsers: [2]byte{0x00, 0x03},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 1,
Name: []byte("C"),
DescriptionSize: 1,
@@ -379,7 +379,7 @@ func TestGetListing(t *testing.T) {
IPAddr: [4]byte{192, 168, 1, 4},
Port: [2]byte{0x15, 0x7c},
NumUsers: [2]byte{0x00, 0x04},
- Unused: [2]byte{0x00, 0x00},
+ TLSPort: [2]byte{0x00, 0x00},
NameSize: 1,
Name: []byte("D"),
DescriptionSize: 1,
@@ -403,11 +403,11 @@ func TestGetListing(t *testing.T) {
192, 168, 1, 1, // IP
0x15, 0x7c, // Port 5500
0x00, 0x01, // NumUsers 1
- 0x00, 0x00, // Unused
- 0x01, // NameSize
- 'A', // Name
- 0x01, // DescriptionSize
- '1', // Description
+ 0x00, 0x00, // TLSPort
+ 0x01, // NameSize
+ 'A', // Name
+ 0x01, // DescriptionSize
+ '1', // Description
// Incomplete second ServerInfoHeader
0x00, 0x01, // MsgType only
}),