Speak protocol 3.0 and fall back to 2.0 only when that is the reflector's maximum.
A reflector that has moved to 3.0 will not accept a station that always announces 2.0, and a 2.x reflector still needs one explicit plaintext session. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+72
-5
@@ -4,26 +4,47 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
tcpHeartbeat = 1
|
||||
tcpProtoVer = 5
|
||||
tcpProtoDown = 6
|
||||
tcpAuthChallenge = 10
|
||||
tcpAuthResponse = 11
|
||||
tcpAuthOK = 12
|
||||
tcpError = 13
|
||||
tcpStartEncReq = 14
|
||||
tcpStartEnc = 15
|
||||
tcpCsrReq = 16
|
||||
tcpCsr = 17
|
||||
tcpClientCert = 18
|
||||
tcpCAInfo = 19
|
||||
tcpCABundleReq = 20
|
||||
tcpCABundle = 21
|
||||
tcpServerInfo = 100
|
||||
tcpNodeList = 101
|
||||
tcpNodeJoined = 102
|
||||
tcpNodeLeft = 103
|
||||
tcpTalkerStart = 104
|
||||
tcpTalkerStop = 105
|
||||
tcpSelectTG = 106
|
||||
tcpRequestQSY = 109
|
||||
tcpStateEvent = 110
|
||||
tcpNodeInfo = 111
|
||||
tcpSignal = 112
|
||||
tcpTxStatus = 113
|
||||
tcpStartUDPEnc = 114
|
||||
|
||||
udpHeartbeat = 1
|
||||
udpAudio = 101
|
||||
udpFlush = 102
|
||||
udpHeartbeat = 1
|
||||
udpAudio = 101
|
||||
udpFlush = 102
|
||||
udpAllFlushed = 103
|
||||
|
||||
maxFrame = 32768
|
||||
maxFrame = 32768
|
||||
maxPreauth20 = 64
|
||||
)
|
||||
|
||||
type frame struct {
|
||||
@@ -45,12 +66,16 @@ func writeFrame(w io.Writer, typ uint16, body []byte) error {
|
||||
}
|
||||
|
||||
func readFrame(r io.Reader) (frame, error) {
|
||||
return readFrameMax(r, maxFrame)
|
||||
}
|
||||
|
||||
func readFrameMax(r io.Reader, max uint32) (frame, error) {
|
||||
var hdr [4]byte
|
||||
if _, err := io.ReadFull(r, hdr[:]); err != nil {
|
||||
return frame{}, err
|
||||
}
|
||||
n := binary.BigEndian.Uint32(hdr[:])
|
||||
if n < 2 || n > maxFrame {
|
||||
if n < 2 || n > max {
|
||||
return frame{}, fmt.Errorf("frame length %d", n)
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
@@ -149,6 +174,48 @@ func parseServerInfo(b []byte) (uint16, []string, error) {
|
||||
return id, codecs, nil
|
||||
}
|
||||
|
||||
func versionWire(major, minor uint16) []byte {
|
||||
return appendU16(appendU16(nil, major), minor)
|
||||
}
|
||||
|
||||
func parseVersion(b []byte) (uint16, uint16, error) {
|
||||
major, rest, err := parseU16(b)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
minor, rest, err := parseU16(rest)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
return 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
return major, minor, nil
|
||||
}
|
||||
|
||||
var atMostVersion = regexp.MustCompile(`^Unsupported protocol version \d+\.\d+\. May be at most (\d+)\.(\d+)\.$`)
|
||||
|
||||
// fallback20 reports that the reflector's maximum is at least 2.0 and below 3.0.
|
||||
func fallback20(msg string) bool {
|
||||
m := atMostVersion.FindStringSubmatch(msg)
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
major, err1 := strconv.Atoi(m[1])
|
||||
minor, err2 := strconv.Atoi(m[2])
|
||||
if err1 != nil || err2 != nil {
|
||||
return false
|
||||
}
|
||||
return !versionBelow(major, minor, 2, 0) && versionBelow(major, minor, 3, 0)
|
||||
}
|
||||
|
||||
func versionBelow(major, minor, maj, min int) bool {
|
||||
if major != maj {
|
||||
return major < maj
|
||||
}
|
||||
return minor < min
|
||||
}
|
||||
|
||||
func hasOPUS(codecs []string) bool {
|
||||
for _, c := range codecs {
|
||||
if c == "OPUS" {
|
||||
|
||||
Reference in New Issue
Block a user