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 | (ns ird.p2p.errors
"Error values delivered on ird.p2p channels. All are ex-info with a :type
key:
:ird.p2p/upgrade-rejected the relay refused the WebSocket upgrade (:status)
:ird.p2p/relay-error the relay answered an error frame (:code)
:ird.p2p/http-error a non-2xx mailbox/TURN/mint response (:status :code :response)
:ird.p2p/peer-unknown sending to a peer that is not a verified member (:peer)
:ird.p2p/frame-too-large one relay frame would exceed max_frame_bytes (:bytes :limit)
:ird.p2p/config-error a precondition failed before any request (:detail)
:ird.p2p/transport-error the network layer failed (:detail)
:ird.p2p/timeout a deadline passed (:detail)
:ird.p2p/not-joined a send before the room was joined
:ird.p2p/closed the room or session has been closed
Remote tampering is never an error: envelopes that do not decrypt are
dropped silently, by design (PROTOCOL.md, \"decrypt or drop\")."
(:require [ird.p2p.async :as a]))
(defn upgrade-rejected
"The relay refused the WebSocket upgrade: 403 Origin not allowed (or
missing), 404 unknown app host, 429 too many connections."
[status]
(ex-info (str "WebSocket upgrade rejected with HTTP " status)
{:type :ird.p2p/upgrade-rejected :status status}))
(defn relay-error
"The relay answered `{\"t\":\"error\",\"code\":...}`. CODE is the node's
string (\"room-full\", \"too-many-rooms\", \"rate-limited\", \"bad-message\",
\"not-joined\", ...)."
[code]
(ex-info (str "Relay error: " code) {:type :ird.p2p/relay-error :code code}))
(defn http-error
"A non-2xx HTTP response. CODE is the node's error code when the body was
{\"error\": \"<code>\"}, RESPONSE the parsed body (nil when not JSON)."
[message status code response]
(ex-info message {:type :ird.p2p/http-error :status status :code code :response response}))
(defn peer-unknown
"The addressed peer is not a verified member of the room."
[peer]
(ex-info (str "Peer is not a verified member: " peer) {:type :ird.p2p/peer-unknown :peer peer}))
(defn frame-too-large
"A single relay frame would exceed the node's max_frame_bytes (the SDK
chunks messages, so this means a misconfiguration)."
[bytes limit]
(ex-info (str "Relay frame of " bytes " bytes exceeds the limit of " limit)
{:type :ird.p2p/frame-too-large :bytes bytes :limit limit}))
(defn config-error
"Invalid configuration or arguments, detected before any request."
[message detail]
(ex-info message {:type :ird.p2p/config-error :detail detail}))
(defn transport-error
"Low-level network failure (DNS, TLS, socket, non-JSON body)."
[message detail]
(ex-info message {:type :ird.p2p/transport-error :detail detail}))
(defn timeout
"A request or handshake exceeded its deadline."
[message detail]
(ex-info message {:type :ird.p2p/timeout :detail detail}))
(defn not-joined
"A send was attempted before the room was joined."
[]
(ex-info "Not joined" {:type :ird.p2p/not-joined}))
(defn closed
"The room or session has been closed."
[]
(ex-info "Closed" {:type :ird.p2p/closed}))
(def types
"Every :type an ird.p2p error can carry."
#{:ird.p2p/upgrade-rejected :ird.p2p/relay-error :ird.p2p/http-error :ird.p2p/peer-unknown
:ird.p2p/frame-too-large :ird.p2p/config-error :ird.p2p/transport-error :ird.p2p/timeout
:ird.p2p/not-joined :ird.p2p/closed})
(def error?
"True for any error value (any JavaScript Error, including ExceptionInfo).
Same as
ird.p2p.async/error?, re-exported for convenience."
a/error?)
(defn p2p-error?
"True when E is an ex-info produced by this library."
[e]
(contains? types (:type (ex-data e))))
(defn upgrade-rejected? [e] (= :ird.p2p/upgrade-rejected (:type (ex-data e))))
(defn relay-error? [e] (= :ird.p2p/relay-error (:type (ex-data e))))
(defn http-error? [e] (= :ird.p2p/http-error (:type (ex-data e))))
(defn peer-unknown? [e] (= :ird.p2p/peer-unknown (:type (ex-data e))))
(defn frame-too-large? [e] (= :ird.p2p/frame-too-large (:type (ex-data e))))
(defn config-error? [e] (= :ird.p2p/config-error (:type (ex-data e))))
(defn transport-error? [e] (= :ird.p2p/transport-error (:type (ex-data e))))
(defn timeout? [e] (= :ird.p2p/timeout (:type (ex-data e))))
(defn not-joined? [e] (= :ird.p2p/not-joined (:type (ex-data e))))
(defn closed? [e] (= :ird.p2p/closed (:type (ex-data e))))
(def relay-codes
"The relay's documented error codes."
#{"bad-message" "not-joined" "too-many-rooms" "room-full" "rate-limited"})
(defn mailbox-code-retryable?
"Whether a later retry of a mailbox request can succeed without changing it."
[code]
(contains? #{"rate_limited" "node_storage_full" "storage_unavailable" "storage_error"} code))
(defn mailbox-code-auth?
"Whether a mailbox failure is about the bearer token (re-mint once, then give up)."
[code]
(contains? #{"missing_token" "token_expired" "invalid_token" "token_out_of_scope"} code))
|