p2p-cljs / test / ird / p2p / wrtc_test.cljs
504 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
(ns ird.p2p.wrtc-test
  "Two real WebRTC data channels inside one process, always on: two rooms
  signal through the in-process fake relay while their peer connections —
  genuine node-datachannel (libdatachannel) connections from
  ird.p2p.impl.wrtc/wrtc-factory — negotiate SDP through the room, trickle
  ICE and connect over loopback. Proves both peers reach :peer-ready
  :via :direct, then round-trips one small binary frame, one 50,000-byte
  binary payload (chunked over the channel) and one JSON frame. Set
  IRD_P2P_NO_WRTC=1 to skip where node-datachannel has no prebuilt binary."
  (:require [cljs.test :refer [deftest is]]
            [cljs.core.async :as async :refer [<!]]
            [ird.p2p :as p2p]
            [ird.p2p.crypto :as crypto]
            [ird.p2p.descriptor :as desc]
            [ird.p2p.fake-relay :as fake]
            [ird.p2p.impl.bytes :as bytes]
            [ird.p2p.impl.wrtc :as wrtc]
            [ird.p2p.test-util :as tu :refer [deftest-async]]
            [ird.p2p.transport.ws :as ws]))

(def low "00000000000000000000000000000001")
(def high "0f1e2d3c4b5a69788796a5b4c3d2e1f0")

(deftest ice-servers-translate-to-libdatachannel-entries
  (is (= [{:hostname "stun.example" :port 3478}
          {:hostname "turn.example" :port 3478 :username "u" :password "p" :relayType "TurnUdp"}
          {:hostname "turn.example" :port 3478 :username "u" :password "p" :relayType "TurnTcp"}
          {:hostname "turn.example" :port 5349 :username "u" :password "p" :relayType "TurnTls"}]
         (wrtc/ice-server-entries {:urls ["stun:stun.example" "turn:turn.example:3478?transport=udp"
                                          "turn:turn.example:3478?transport=tcp" "turns:turn.example:5349"
                                          "not a url"]
                                   :username "u" :credential "p"}))))

(deftest-async two-real-data-channels-over-loopback
  {:timeout-ms 45000}
  (if (tu/env "IRD_P2P_NO_WRTC")
    (is true "IRD_P2P_NO_WRTC set — skipping the real WebRTC data-channel test")
    (let [relay (fake/make-relay)
          factory (wrtc/wrtc-factory)
          ;; the fallback descriptor points TURN credentials at https://h/…; answer
          ;; that with a failure so the ICE configuration degrades to no servers
          app (fn [] (p2p/make-app {:host "h" :app-salt "wrtc/v1"
                                    :descriptor (desc/fallback "h")
                                    :http-fn (tu/responding 503 {:error "no turn"})
                                    :transport (ws/transport {:socket-fn (fake/socket-fn relay)})
                                    :pc-factory factory}))
          secret (crypto/random-secret)
          ra (<! (p2p/join (app) secret {:peer-id low :options {:pacing? false}}))
          ca (tu/collector (p2p/events ra))
          rb (<! (p2p/join (app) secret {:peer-id high :options {:pacing? false}}))
          cb (tu/collector (p2p/events rb))]
      (is (not (tu/error? ra)) (some-> ra ex-message))
      (is (not (tu/error? rb)) (some-> rb ex-message))
      ;; membership over the relay, then the real data channel comes up on both sides
      (is (some? (<! (tu/wait-for ca #(= {:type :peer-ready :peer high :via :relayed} %) 10000))))
      (is (some? (<! (tu/wait-for ca #(= {:type :peer-ready :peer high :via :direct} %) 20000))))
      (is (some? (<! (tu/wait-for cb #(= {:type :peer-ready :peer low :via :direct} %) 20000))))
      (is (= :direct (p2p/transport-of ra high)))
      (is (= :direct (p2p/transport-of rb low)))
      ;; a small binary frame (one data-channel message) both ways
      (let [small (bytes/bytes->b64 (map #(mod % 251) (range 3000)))]
        (is (true? (<! (p2p/send ra high (p2p/data small)))))
        (is (some? (<! (tu/wait-for cb #(= {:kind :data :payload small} (:message %)) 10000))))
        (is (true? (<! (p2p/send rb low (p2p/data small)))))
        (is (some? (<! (tu/wait-for ca #(= {:kind :data :payload small} (:message %)) 10000)))))
      ;; a 50,000-byte payload, chunked over the channel like the Swift smoke test's
      (let [big (bytes/bytes->b64 (map #(mod % 253) (range 50000)))]
        (is (= 50000 (bytes/byte-length big)))
        (is (true? (<! (p2p/send ra high (p2p/data big)))))
        (is (some? (<! (tu/wait-for cb #(= {:kind :data :payload big} (:message %)) 20000)))))
      ;; and a JSON frame
      (is (true? (<! (p2p/send rb low (p2p/json {:text "over a real data channel"})))))
      (is (some? (<! (tu/wait-for ca #(= "over a real data channel" (get-in % [:message :value :text])) 10000))))
      (<! (p2p/leave ra))
      (<! (p2p/leave rb)))))

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