Files
go2rtc/pkg/hap/helpers.go
2025-09-19 15:27:58 +03:00

123 lines
2.9 KiB
Go

package hap
import (
"crypto/ed25519"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"strings"
)
const (
TXTConfigNumber = "c#" // Current configuration number (ex. 1, 2, 3)
TXTDeviceID = "id" // Device ID of the accessory (ex. 77:75:87:A0:7D:F4)
TXTModel = "md" // Model name of the accessory (ex. MJCTD02YL)
TXTProtoVersion = "pv" // Protocol version string (ex. 1.1)
TXTStateNumber = "s#" // Current state number (ex. 1)
TXTCategory = "ci" // Accessory Category Identifier (ex. 2, 5, 17)
TXTSetupHash = "sh" // Setup hash (ex. Y9w9hQ==)
// TXTFeatureFlags
// - 0001b - Supports Apple Authentication Coprocessor
// - 0010b - Supports Software Authentication
TXTFeatureFlags = "ff" // Pairing Feature flags (ex. 0, 1, 2)
// TXTStatusFlags
// - 0001b - Accessory has not been paired with any controllers
// - 0100b - A problem has been detected on the accessory
TXTStatusFlags = "sf" // Status flags (ex. 0, 1)
StatusPaired = "0"
StatusNotPaired = "1"
CategoryBridge = "2"
CategoryCamera = "17"
CategoryDoorbell = "18"
StateM1 = 1
StateM2 = 2
StateM3 = 3
StateM4 = 4
StateM5 = 5
StateM6 = 6
MethodPair = 0
MethodPairMFi = 1 // if device has MFI cert
MethodVerifyPair = 2
MethodAddPairing = 3
MethodDeletePairing = 4
MethodListPairings = 5
PermissionUser = 0
PermissionAdmin = 1
)
const DeviceAID = 1 // TODO: fix someday
type JSONAccessories struct {
Value []*Accessory `json:"accessories"`
}
type JSONCharacters struct {
Value []JSONCharacter `json:"characteristics"`
}
type JSONCharacter struct {
AID uint8 `json:"aid"`
IID uint64 `json:"iid"`
Status any `json:"status,omitempty"`
Value any `json:"value,omitempty"`
Event any `json:"ev,omitempty"`
}
// 4.2.1.2 Invalid Setup Codes
const insecurePINs = "00000000 11111111 22222222 33333333 44444444 55555555 66666666 77777777 88888888 99999999 12345678 87654321"
func SanitizePin(pin string) (string, error) {
s := strings.ReplaceAll(pin, "-", "")
if len(s) != 8 {
return "", errors.New("hap: wrong PIN format: " + pin)
}
if strings.Contains(insecurePINs, s) {
return "", errors.New("hap: insecure PIN: " + pin)
}
// 123-45-678
return s[:3] + "-" + s[3:5] + "-" + s[5:], nil
}
func GenerateKey() []byte {
_, key, _ := ed25519.GenerateKey(nil)
return key
}
func GenerateUUID() string {
//12345678-9012-3456-7890-123456789012
data := make([]byte, 16)
_, _ = rand.Read(data)
s := hex.EncodeToString(data)
return s[:8] + "-" + s[8:12] + "-" + s[12:16] + "-" + s[16:20] + "-" + s[20:]
}
func Append(items ...any) (b []byte) {
for _, item := range items {
switch v := item.(type) {
case string:
b = append(b, v...)
case []byte:
b = append(b, v[:]...)
default:
panic(v)
}
}
return
}
func newRequestError(req any) error {
return fmt.Errorf("hap: wrong request: %#v", req)
}
func newResponseError(req, res any) error {
return fmt.Errorf("hap: wrong response: %#v, on request: %#v", res, req)
}