]> git.r.bdr.sh - rbdr/mobius/blame - hotline/handshake.go
Fix failing test, replace use of reflect package with assert
[rbdr/mobius] / hotline / handshake.go
CommitLineData
aebc4d36
JH
1package hotline
2
3import (
4 "bytes"
5 "encoding/binary"
6 "errors"
a2ef262a 7 "fmt"
d4c152a4 8 "io"
aebc4d36
JH
9)
10
a2ef262a
JH
11// Hotline handshake process
12//
aebc4d36
JH
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
d9bc63a1
JH
22// Protocol Type 4 TRTP 0x54525450
23// Sub-protocol Type 4 HOTL User defined
aebc4d36
JH
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
d9bc63a1 29// Protocol Type 4 TRTP
aebc4d36 30// Error code 4 Error code returned by the server (0 = no error)
a2ef262a
JH
31
32type 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.
40func (h *handshake) Write(p []byte) (n int, err error) {
41 if len(p) != handshakeSize {
42 return 0, errors.New("invalid handshake size")
d4c152a4
JH
43 }
44
a2ef262a
JH
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.
51func (h *handshake) Valid() bool {
52 return h.Protocol == trtp && h.SubProtocol == hotl
53}
54
55var (
d9bc63a1 56 // trtp represents the Protocol Type "TRTP" in hex
a2ef262a
JH
57 trtp = [4]byte{0x54, 0x52, 0x54, 0x50}
58
d9bc63a1 59 // hotl represents the Sub-protocol Type "HOTL" in hex
a2ef262a
JH
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
67const handshakeSize = 12
68
69// performHandshake performs the handshake process.
70func performHandshake(rw io.ReadWriter) error {
aebc4d36 71 var h handshake
a2ef262a
JH
72
73 // Copy exactly handshakeSize bytes from rw to handshake
74 if _, err := io.CopyN(&h, rw, handshakeSize); err != nil {
fd740bc4 75 return fmt.Errorf("read handshake: %w", err)
a2ef262a 76 }
a2ef262a
JH
77 if !h.Valid() {
78 return errors.New("invalid protocol or sub-protocol in handshake")
aebc4d36
JH
79 }
80
a2ef262a 81 if _, err := rw.Write(handshakeResponse[:]); err != nil {
fd740bc4 82 return fmt.Errorf("send handshake response: %w", err)
aebc4d36
JH
83 }
84
a2ef262a 85 return nil
aebc4d36 86}