1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package ingress
import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"strings"
"github.com/gorilla/websocket"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/hostport"
)
const (
SubscribeNSID = "com.fedproxy.temp.xrpc.subscribe"
GetNonceNSID = "com.fedproxy.temp.xrpc.getRegistrationNonce"
TunnelNSID = "com.fedproxy.temp.xrpc.tunnel"
RegistrationType = "com.fedproxy.temp.xrpc.registration"
KeepalivePath = "/xrpc/com.publicdomainrelay.temp.keepalive.ping"
HealthPath = "/xrpc/_health"
DefaultServiceID = "xrpc_relay"
MaxFrameBytes = 64 << 20
DefaultMaxBodyBytes = 32 << 20
callerQueueDepth = 4096
maxCloseReasonBytes = 123
)
var relayedResponseHeaders = map[string]struct{}{
"dpop-nonce": {},
"www-authenticate": {},
"location": {},
"cache-control": {},
"retry-after": {},
}
var subscriptionHeaders = []string{"authorization", "atproto-proxy"}
type Signature struct {
Key string `json:"key"`
Signature string `json:"signature"`
}
type Registration struct {
Type string `json:"$type"`
Key string `json:"key"`
Nonce string `json:"nonce"`
Signatures []Signature `json:"signatures"`
}
type Request struct {
RequestID string
Method string
Path string
Params map[string]string
Body json.RawMessage
RawBody string
Headers map[string]string
}
type Response struct {
Status int
Body json.RawMessage
ContentType string
Headers map[string]string
}
type frame struct {
Type string `json:"$type"`
RequestID string `json:"requestId"`
Method string `json:"method"`
Path string `json:"path"`
Params map[string]string `json:"params"`
Body json.RawMessage `json:"body"`
RawBody *string `json:"rawBody"`
Headers map[string]string `json:"headers"`
Status int `json:"status"`
ContentType string `json:"contentType"`
SubscriptionID string `json:"subscriptionId"`
NSID string `json:"nsid"`
Message json.RawMessage `json:"message"`
Data string `json:"data"`
Code int `json:"code"`
Reason string `json:"reason"`
Key string `json:"key"`
Nonce string `json:"nonce"`
Signatures []Signature `json:"signatures"`
Subdomain string `json:"subdomain"`
IngressRef string `json:"ingressRef"`
}
func b64encode(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func b64decode(s string) ([]byte, error) {
return base64.StdEncoding.DecodeString(s)
}
func newID() string {
b := make([]byte, 16)
_, _ = rand.Read(b)
return hex.EncodeToString(b)
}
func httpOrigin(host string, tls bool) string {
if !tls && (strings.Contains(host, ":") || host == "localhost") {
return "http://" + host
}
return "https://" + host
}
func wsOrigin(host string, tls bool) string {
if !tls && (strings.Contains(host, ":") || host == "localhost") {
return "ws://" + host
}
return "wss://" + host
}
func IngressURL(did, host string) string {
return "https://" + hostport.DIDLabel(did) + "." + hostport.HostnameOnly(host)
}
func splitDataHost(host string, bases []string) (string, string, bool) {
for _, base := range bases {
if base == "" || base == "*" {
continue
}
if before, ok := strings.CutSuffix(host, "."+base); ok {
sub := before
if sub == "" {
continue
}
return base, sub, true
}
}
return "", "", false
}
func closeFrame(code int, reason string) []byte {
switch {
case code >= 1000 && code <= 1003, code >= 1007 && code <= 1014, code >= 3000 && code <= 4999:
default:
code = 1000
}
if len(reason) > maxCloseReasonBytes {
reason = reason[:maxCloseReasonBytes]
}
return websocket.FormatCloseMessage(code, reason)
}
func frameType(kind string) string {
return SubscribeNSID + "#" + kind
}
func kindOf(typeName string) string {
prefix := SubscribeNSID + "#"
if !strings.HasPrefix(typeName, prefix) {
return ""
}
return strings.TrimPrefix(typeName, prefix)
}