Files
Piik/internal/client/loopback/protocol.go
T
AAA cfc323adce feat(media): integrate embedded media services and shared native encoding
Embed STUN and SFU in the shared Go process, reuse native encoding pipelines with independent adaptation, and complete Client lifecycle, settings, diagnostics and packaging fixes. Retain standard Browser senders after measured encoded-reuse limitations.
2026-09-09 06:09:06 +08:00

74 lines
1.8 KiB
Go

package loopback
import (
"bytes"
"encoding/json"
"errors"
"io"
"regexp"
)
const (
ProtocolVersion = 9
ServiceName = "screener-client"
ControlSubprotocol = "screener-client-v9"
MaxControlMessageBytes = 256 << 10
DefaultPortStart = 39721
DefaultPortEnd = 39730
)
var (
requestIDPattern = regexp.MustCompile(`^[A-Za-z0-9_-]{8,256}$`)
errInvalidMessage = errors.New("loopback control message is invalid")
)
type controlMessage struct {
Version int `json:"version"`
ID string `json:"id"`
Type string `json:"type"`
}
func decodeEnvelope(payload []byte) (controlMessage, error) {
var message controlMessage
decoder := json.NewDecoder(bytes.NewReader(payload))
if decoder.Decode(&message) != nil || decoder.Decode(&struct{}{}) != io.EOF ||
message.Version != ProtocolVersion || !requestIDPattern.MatchString(message.ID) ||
message.Type == "" {
return controlMessage{}, errInvalidMessage
}
return message, nil
}
func decodeRequest(payload []byte) (controlMessage, error) {
var message controlMessage
decoder := json.NewDecoder(bytes.NewReader(payload))
decoder.DisallowUnknownFields()
if decoder.Decode(&message) != nil || decoder.Decode(&struct{}{}) != io.EOF ||
message.Version != ProtocolVersion || !requestIDPattern.MatchString(message.ID) {
return controlMessage{}, errInvalidMessage
}
return message, nil
}
func validateHello(message controlMessage) error {
if message.Type != "hello" {
return errInvalidMessage
}
return nil
}
func validatePing(message controlMessage) error {
if message.Type != "ping" {
return errInvalidMessage
}
return nil
}
func encodeMessage(value any) ([]byte, error) {
payload, err := json.Marshal(value)
if err != nil || len(payload) == 0 || len(payload) > MaxControlMessageBytes {
return nil, errInvalidMessage
}
return payload, nil
}