]> git.r.bdr.sh - rbdr/mobius/blob - hotline/handshake.go
Add logging of tracker registration
[rbdr/mobius] / hotline / handshake.go
1 package hotline
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "errors"
7 "fmt"
8 "io"
9 )
10
11 // Hotline handshake process
12 //
13 // After establishing TCP connection, both client and server start the handshake process
14 // in order to confirm that each of them comply with requirements of the other.
15 // The information provided in this initial data exchange identifies protocols,
16 // and their versions, used in the communication. In the case where, after inspection,
17 // the capabilities of one of the subjects do not comply with the requirements of the other,
18 // the connection is dropped.
19 //
20 // The following information is sent to the server:
21 // Description Size Data Note
22 // Protocol Type 4 TRTP 0x54525450
23 // Sub-protocol Type 4 HOTL User defined
24 // VERSION 2 1 Currently 1
25 // Sub-version 2 2 User defined
26 //
27 // The server replies with the following:
28 // Description Size Data Note
29 // Protocol Type 4 TRTP
30 // Error code 4 Error code returned by the server (0 = no error)
31
32 type handshake struct {
33 Protocol [4]byte // Must be 0x54525450 TRTP
34 SubProtocol [4]byte // Must be 0x484F544C HOTL
35 Version [2]byte // Always 1 (?)
36 SubVersion [2]byte // Always 2 (?)
37 }
38
39 // Write implements the io.Writer interface for handshake.
40 func (h *handshake) Write(p []byte) (n int, err error) {
41 if len(p) != handshakeSize {
42 return 0, errors.New("invalid handshake size")
43 }
44
45 _ = binary.Read(bytes.NewBuffer(p), binary.BigEndian, h)
46
47 return len(p), nil
48 }
49
50 // Valid checks if the handshake contains valid protocol and sub-protocol IDs.
51 func (h *handshake) Valid() bool {
52 return h.Protocol == trtp && h.SubProtocol == hotl
53 }
54
55 var (
56 // trtp represents the Protocol Type "TRTP" in hex
57 trtp = [4]byte{0x54, 0x52, 0x54, 0x50}
58
59 // hotl represents the Sub-protocol Type "HOTL" in hex
60 hotl = [4]byte{0x48, 0x4F, 0x54, 0x4C}
61
62 // handshakeResponse represents the server's response after a successful handshake
63 // Response with "TRTP" and no error code
64 handshakeResponse = [8]byte{0x54, 0x52, 0x54, 0x50, 0x00, 0x00, 0x00, 0x00}
65 )
66
67 const handshakeSize = 12
68
69 // performHandshake performs the handshake process.
70 func performHandshake(rw io.ReadWriter) error {
71 var h handshake
72
73 // Copy exactly handshakeSize bytes from rw to handshake
74 if _, err := io.CopyN(&h, rw, handshakeSize); err != nil {
75 return fmt.Errorf("read handshake: %w", err)
76 }
77 if !h.Valid() {
78 return errors.New("invalid protocol or sub-protocol in handshake")
79 }
80
81 if _, err := rw.Write(handshakeResponse[:]); err != nil {
82 return fmt.Errorf("send handshake response: %w", err)
83 }
84
85 return nil
86 }