p2p-cljs / src / ird / p2p / errors.cljs
571 words
  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))

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/p2p-cljs.git