diff --git a/README.md b/README.md index fc57856..5067d06 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,54 @@ -# webrtc_signaling +This is modified version of https://github.com/godotengine/godot-demo-projects/tree/master/networking/webrtc_signaling +It adds ability for dynamic lobby host swap and ability to say should lobby have only 1 host... + +# A WebSocket signaling server/client for WebRTC. + +This demo is devided in 4 parts: + +- The `server` folder contains the signaling server implementation written in GDScript (so it can be run by a game server running Godot) +- The `server_node` folder contains the signaling server implementation written in Node.js (if you don't plan to run a game server but only match-making). +- The `client` part contains the client implementation in GDScript. + - Itself divided into raw protocol and `WebRTCMultiplayer` handling. +- The `demo` contains a small app that uses it. + +**NOTE**: You must extract the [latest version](https://github.com/godotengine/webrtc-native/releases) of the WebRTC GDNative plugin in the project folder to run from desktop. + +Language: GDScript + +Renderer: GLES 2 + +Check out this demo on the asset library: https://godotengine.org/asset-library/asset/537 + +## Protocol + +The protocol is JSON based, and uses messages in the form: + +``` +{ + "id": "number", + "type": "number", + "data": "string", +} +``` + +With `type` being the message type, `id` being a connected peer or `0`, and `data` being the message specific data. + +Messages are the following: + +- `0 = JOIN`, must be sent by client immediately after connection to get a lobby assigned or join a known one (via the `data` field). + This messages is also sent by server back to the client to notify the assigned lobby, or simply a successful join. +- `1 = ID`, sent by server to identify the client when it joins a room (the `id` field will contain the be assigned ID). +- `2 = PEER_CONNECT`, sent by server to notify new peers in the same lobby (the `id` field will contain the ID of the new peer). +- `3 = PEER_DISCONNECT`, sent by server to notify when a peer in the same lobby disconnects (the `id` field will contain the ID of the disconnected peer). +- `4 = OFFER`, sent by the client when creating a WebRTC offer then relayed back by the server to the destination peer. +- `5 = ANSWER`, sent by the client when creating a WebRTC answer then relayed back by the server to the destination peer. +- `6 = CANDIDATE`, sent by the client when generating new WebRTC candidates then relayed back by the server to the destination peer. +- `7 = SEAL`, sent by client to seal the lobby (only the client that created it is allowed to seal a lobby), and then back by the server to notify success. + When a lobby is sealed, no new client will be able to join, and the lobby will be destroyed (and clients disconnected) after 10 seconds. + +For relayed messages (i.e. for `OFFER`, `ANSWER`, and `CANDIDATE`), the client will set the `id` field as the destination peer, then the server will replace it with the id of the sending peer, and send it to the proper destination. + +## Screenshots + +![Screenshot](screenshots/screenshot.png) diff --git a/client/multiplayer_client.gd b/client/multiplayer_client.gd new file mode 100644 index 0000000..059fa3d --- /dev/null +++ b/client/multiplayer_client.gd @@ -0,0 +1,109 @@ +extends "ws_webrtc_client.gd" + +var rtc_mp: WebRTCMultiplayerPeer = WebRTCMultiplayerPeer.new() +var sealed := false + +func _init(): + connected.connect(self._connected) + disconnected.connect(self._disconnected) + + offer_received.connect(self._offer_received) + answer_received.connect(self._answer_received) + candidate_received.connect(self._candidate_received) + + lobby_joined.connect(self._lobby_joined) + lobby_sealed.connect(self._lobby_sealed) + peer_connected.connect(self._peer_connected) + peer_disconnected.connect(self._peer_disconnected) + + +func start(url, lobby = "", mesh:=true): + stop() + sealed = false + self.mesh = mesh + self.lobby = lobby + connect_to_url(url) + + +func stop(): + multiplayer.multiplayer_peer = null + rtc_mp.close() + close() + + +func _create_peer(id, host_id): + var peer: WebRTCPeerConnection = WebRTCPeerConnection.new() + peer.initialize({ + "iceServers": [ { "urls": ["stun:stun.l.google.com:19302","stun:tun.hoiio.com:3478","stun:stun.voip.aebc.com:3478","stun.services.mozilla.com:3478"] } ] + }) + peer.session_description_created.connect(self._offer_created.bind(id)) + peer.ice_candidate_created.connect(self._new_ice_candidate.bind(id)) + rtc_mp.add_peer(peer, id) + print("Is peer host: %s" % [host_id != rtc_mp.get_unique_id()]) + if id < rtc_mp.get_unique_id(): # So only one peer creates offers. + peer.create_offer() + return peer + + +func _new_ice_candidate(mid_name, index_name, sdp_name, id): + send_candidate(id, mid_name, index_name, sdp_name) + + +func _offer_created(type, data, id): + if not rtc_mp.has_peer(id): + return + print("created ", type) + rtc_mp.get_peer(id).connection.set_local_description(type, data) + if type == "offer": send_offer(id, data) + else: send_answer(id, data) + + +func _connected(id, use_mesh): + print("Connected %d, mesh: %s" % [id, use_mesh]) + if use_mesh: + rtc_mp.create_mesh(id) + elif id == 1: + rtc_mp.create_server() + else: + rtc_mp.create_client(id) + multiplayer.multiplayer_peer = rtc_mp + + +func _lobby_joined(lobby): + self.lobby = lobby + + +func _lobby_sealed(): + sealed = true + + +func _disconnected(): + print("Disconnected: %d: %s" % [code, reason]) + if not sealed: + stop() # Unexpected disconnect + + +func _peer_connected(id, host_id): + print("Peer connected %d" % id) + _create_peer(id, host_id) + + +func _peer_disconnected(id): + if rtc_mp.has_peer(id): rtc_mp.remove_peer(id) + + +func _offer_received(id, offer): + print("Got offer: %d" % id) + if rtc_mp.has_peer(id): + rtc_mp.get_peer(id).connection.set_remote_description("offer", offer) + + +func _answer_received(id, answer): + print("Got answer: %d" % id) + if rtc_mp.has_peer(id): + rtc_mp.get_peer(id).connection.set_remote_description("answer", answer) + + +func _candidate_received(id, mid, index, sdp): + if rtc_mp.has_peer(id): + rtc_mp.get_peer(id).connection.add_ice_candidate(mid, index, sdp) diff --git a/client/ws_webrtc_client.gd b/client/ws_webrtc_client.gd new file mode 100644 index 0000000..c5974bf --- /dev/null +++ b/client/ws_webrtc_client.gd @@ -0,0 +1,122 @@ +extends Node + +enum Message {JOIN, ID, PEER_CONNECT, PEER_DISCONNECT, OFFER, ANSWER, CANDIDATE, SEAL} + +@export var autojoin := true +@export var lobby := "" # Will create a new lobby if empty. +@export var mesh := true # Will use the lobby host as relay otherwise. + +var ws: WebSocketPeer = WebSocketPeer.new() +var code = 1000 +var reason = "Unknown" + +signal lobby_joined(lobby) +signal connected(id, use_mesh) +signal disconnected() +signal peer_connected(id, host_id) +signal peer_disconnected(id) +signal offer_received(id, offer) +signal answer_received(id, answer) +signal candidate_received(id, mid, index, sdp) +signal lobby_sealed() + + +func connect_to_url(url): + close() + code = 1000 + reason = "Unknown" + ws.connect_to_url(url) + + +func close(): + ws.close() + + +func _process(delta): + var old_state: int = ws.get_ready_state() + if old_state == WebSocketPeer.STATE_CLOSED: + return + ws.poll() + var state = ws.get_ready_state() + if state != old_state and state == WebSocketPeer.STATE_OPEN and autojoin: + join_lobby(lobby) + while state == WebSocketPeer.STATE_OPEN and ws.get_available_packet_count(): + if not _parse_msg(): + print("Error parsing message from server.") + if state == WebSocketPeer.STATE_CLOSED: + code = ws.get_close_code() + reason = ws.get_close_reason() + disconnected.emit() + + +func _parse_msg(): + var parsed = JSON.parse_string(ws.get_packet().get_string_from_utf8()) + if typeof(parsed) != TYPE_DICTIONARY or not parsed.has("type") or not parsed.has("id") or \ + typeof(parsed.get("data")) != TYPE_STRING: + return false + + var msg := parsed as Dictionary + if not str(msg.type).is_valid_int() or not str(msg.id).is_valid_int(): + return false + + var type := str(msg.type).to_int() + var src_id := str(msg.id).to_int() + + if type == Message.ID: + connected.emit(src_id, msg.data) + elif type == Message.JOIN: + lobby_joined.emit(msg.data) + elif type == Message.SEAL: + lobby_sealed.emit() + elif type == Message.PEER_CONNECT: + # Client connected + peer_connected.emit(src_id, str(msg.data).to_int()) + elif type == Message.PEER_DISCONNECT: + # Client connected + peer_disconnected.emit(src_id) + elif type == Message.OFFER: + # Offer received + offer_received.emit(src_id, msg.data) + elif type == Message.ANSWER: + # Answer received + answer_received.emit(src_id, msg.data) + elif type == Message.CANDIDATE: + # Candidate received + var candidate: PackedStringArray = msg.data.split("\n", false) + if candidate.size() != 3: + return false + if not candidate[1].is_valid_int(): + return false + candidate_received.emit(src_id, candidate[0], candidate[1].to_int(), candidate[2]) + else: + return false + return true # Parsed + + +func join_lobby(lobby: String, single_host:=false): + var data = {"lobby":lobby,"single_host":single_host} + return _send_msg(Message.JOIN, 0 if mesh else 1, JSON.stringify(data)) + + +func seal_lobby(): + return _send_msg(Message.SEAL, 0) + + +func send_candidate(id, mid, index, sdp) -> int: + return _send_msg(Message.CANDIDATE, id, "\n%s\n%d\n%s" % [mid, index, sdp]) + + +func send_offer(id, offer) -> int: + return _send_msg(Message.OFFER, id, offer) + + +func send_answer(id, answer) -> int: + return _send_msg(Message.ANSWER, id, answer) + + +func _send_msg(type: int, id: int, data:="") -> int: + return ws.send_text(JSON.stringify({ + "type": type, + "id": id, + "data": data + })) diff --git a/demo/client_ui.gd b/demo/client_ui.gd new file mode 100644 index 0000000..8227b1f --- /dev/null +++ b/demo/client_ui.gd @@ -0,0 +1,80 @@ +extends Control + +@onready var client = $Client +@onready var host = $VBoxContainer/Connect/Host +@onready var room = $VBoxContainer/Connect/RoomSecret +@onready var mesh = $VBoxContainer/Connect/Mesh + +func _ready(): + client.lobby_joined.connect(self._lobby_joined) + client.lobby_sealed.connect(self._lobby_sealed) + client.connected.connect(self._connected) + client.disconnected.connect(self._disconnected) + + multiplayer.connected_to_server.connect(self._mp_server_connected) + multiplayer.connection_failed.connect(self._mp_server_disconnect) + multiplayer.server_disconnected.connect(self._mp_server_disconnect) + multiplayer.peer_connected.connect(self._mp_peer_connected) + multiplayer.peer_disconnected.connect(self._mp_peer_disconnected) + + +@rpc("any_peer", "call_local") +func ping(argument): + _log("[Multiplayer] Ping from peer %d: arg: %s" % [multiplayer.get_remote_sender_id(), argument]) + + +func _mp_server_connected(): + _log("[Multiplayer] Server connected (I am %d)" % client.rtc_mp.get_unique_id()) + + +func _mp_server_disconnect(): + _log("[Multiplayer] Server disconnected (I am %d)" % client.rtc_mp.get_unique_id()) + + +func _mp_peer_connected(id: int): + _log("[Multiplayer] Peer %d connected" % id) + + +func _mp_peer_disconnected(id: int): + _log("[Multiplayer] Peer %d disconnected" % id) + + +func _connected(id): + _log("[Signaling] Server connected with ID: %d" % id) + + +func _disconnected(): + _log("[Signaling] Server disconnected: %d - %s" % [client.code, client.reason]) + + +func _lobby_joined(lobby): + _log("[Signaling] Joined lobby %s" % lobby) + + +func _lobby_sealed(): + _log("[Signaling] Lobby has been sealed") + + +func _log(msg): + print(msg) + $VBoxContainer/TextEdit.text += str(msg) + "\n" + + +func _on_peers_pressed(): + _log(multiplayer.get_peers()) + + +func _on_ping_pressed(): + ping.rpc(randf()) + + +func _on_seal_pressed(): + client.seal_lobby() + + +func _on_start_pressed(): + client.start(host.text, room.text, mesh.button_pressed) + + +func _on_stop_pressed(): + client.stop() diff --git a/demo/client_ui.tscn b/demo/client_ui.tscn new file mode 100644 index 0000000..623da91 --- /dev/null +++ b/demo/client_ui.tscn @@ -0,0 +1,83 @@ +[gd_scene load_steps=3 format=3 uid="uid://cpwp4xx6mv5p"] + +[ext_resource type="Script" path="res://demo/client_ui.gd" id="1"] +[ext_resource type="Script" path="res://client/multiplayer_client.gd" id="2"] + +[node name="ClientUI" type="Control"] +layout_mode = 3 +anchors_preset = 0 +offset_right = 1024.0 +offset_bottom = 600.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1") + +[node name="Client" type="Node" parent="."] +script = ExtResource("2") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Connect" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/Connect"] +layout_mode = 2 +text = "Connect to:" + +[node name="Host" type="LineEdit" parent="VBoxContainer/Connect"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "ws://localhost:9080" + +[node name="Room" type="Label" parent="VBoxContainer/Connect"] +layout_mode = 2 +size_flags_vertical = 5 +text = "Room" + +[node name="RoomSecret" type="LineEdit" parent="VBoxContainer/Connect"] +layout_mode = 2 +placeholder_text = "secret" + +[node name="Mesh" type="CheckBox" parent="VBoxContainer/Connect"] +layout_mode = 2 +button_pressed = true +text = "Mesh" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Start" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Start" + +[node name="Stop" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Stop" + +[node name="Seal" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Seal" + +[node name="Ping" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Ping" + +[node name="Peers" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Print peers" + +[node name="TextEdit" type="TextEdit" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Start" to="." method="_on_start_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Stop" to="." method="_on_stop_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Seal" to="." method="_on_seal_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Ping" to="." method="_on_ping_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Peers" to="." method="_on_peers_pressed"] diff --git a/demo/main.gd b/demo/main.gd new file mode 100644 index 0000000..d416548 --- /dev/null +++ b/demo/main.gd @@ -0,0 +1,24 @@ +extends Control + +func _enter_tree(): + for c in $VBoxContainer/Clients.get_children(): + # So each child gets its own separate MultiplayerAPI. + get_tree().set_multiplayer( + MultiplayerAPI.create_default_interface(), + NodePath("%s/VBoxContainer/Clients/%s" % [get_path(), c.name]) + ) + +func _ready(): + if OS.get_name() == "HTML5": + $VBoxContainer/Signaling.hide() + + +func _on_listen_toggled(button_pressed): + if button_pressed: + $Server.listen(int($VBoxContainer/Signaling/Port.value)) + else: + $Server.stop() + + +func _on_LinkButton_pressed(): + OS.shell_open("https://github.com/godotengine/webrtc-native/releases") diff --git a/demo/main.tscn b/demo/main.tscn new file mode 100644 index 0000000..aae6715 --- /dev/null +++ b/demo/main.tscn @@ -0,0 +1,71 @@ +[gd_scene load_steps=4 format=3 uid="uid://5p1bp2kcs0py"] + +[ext_resource type="Script" path="res://demo/main.gd" id="1"] +[ext_resource type="PackedScene" uid="uid://cpwp4xx6mv5p" path="res://demo/client_ui.tscn" id="2"] +[ext_resource type="Script" path="res://server/ws_webrtc_server.gd" id="3"] + +[node name="Control" type="Control"] +layout_mode = 3 +anchor_left = 0.0136719 +anchor_top = 0.0166667 +anchor_right = 0.986328 +anchor_bottom = 0.983333 +script = ExtResource("1") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 0 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Signaling" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/Signaling"] +layout_mode = 2 +text = "Signaling server:" + +[node name="Port" type="SpinBox" parent="VBoxContainer/Signaling"] +layout_mode = 2 +min_value = 1025.0 +max_value = 65535.0 +value = 9080.0 + +[node name="ListenButton" type="Button" parent="VBoxContainer/Signaling"] +layout_mode = 2 +toggle_mode = true +text = "Listen" + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/Signaling"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="LinkButton" type="LinkButton" parent="VBoxContainer/Signaling/CenterContainer"] +layout_mode = 2 +text = "Make sure to download the GDNative WebRTC Plugin and place it in the project folder" + +[node name="Clients" type="GridContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +columns = 2 + +[node name="ClientUI" parent="VBoxContainer/Clients" instance=ExtResource("2")] +layout_mode = 2 + +[node name="ClientUI2" parent="VBoxContainer/Clients" instance=ExtResource("2")] +layout_mode = 2 + +[node name="ClientUI3" parent="VBoxContainer/Clients" instance=ExtResource("2")] +layout_mode = 2 + +[node name="ClientUI4" parent="VBoxContainer/Clients" instance=ExtResource("2")] +layout_mode = 2 + +[node name="Server" type="Node" parent="."] +script = ExtResource("3") + +[connection signal="toggled" from="VBoxContainer/Signaling/ListenButton" to="." method="_on_listen_toggled"] +[connection signal="pressed" from="VBoxContainer/Signaling/CenterContainer/LinkButton" to="." method="_on_LinkButton_pressed"] diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..0c29a9d --- /dev/null +++ b/project.godot @@ -0,0 +1,34 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="WebRTC Signaling Example" +config/description="A WebSocket signaling server/client for WebRTC. +This demo is devided in 4 parts. +The protocol is text based, and composed by a command and possibly +multiple payload arguments, each separated by a new line." +config/tags=PackedStringArray("demo", "network", "official") +run/main_scene="res://demo/main.tscn" +config/features=PackedStringArray("4.2") + +[debug] + +gdscript/warnings/shadowed_variable=false +gdscript/warnings/unused_argument=false + +[display] + +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + +[network] + +modules/webrtc_gdnative_script="res://demo/webrtc/webrtc.gdns" diff --git a/screenshots/.gdignore b/screenshots/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/screenshots/screenshot.png b/screenshots/screenshot.png new file mode 100644 index 0000000..5eb4935 Binary files /dev/null and b/screenshots/screenshot.png differ diff --git a/server/ws_webrtc_server.gd b/server/ws_webrtc_server.gd new file mode 100644 index 0000000..138e0cc --- /dev/null +++ b/server/ws_webrtc_server.gd @@ -0,0 +1,231 @@ +extends Node + +enum Message {JOIN, ID, PEER_CONNECT, PEER_DISCONNECT, OFFER, ANSWER, CANDIDATE, SEAL} + +const TIMEOUT = 1000 # Unresponsive clients times out after 1 sec +const SEAL_TIME = 10000 # A sealed room will be closed after this time +const ALFNUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +var _alfnum = ALFNUM.to_ascii_buffer() + +var rand: RandomNumberGenerator = RandomNumberGenerator.new() +var lobbies: Dictionary = {} +var tcp_server := TCPServer.new() +var peers: Dictionary = {} + +class Peer extends RefCounted: + var id = -1 + var lobby = "" + var time = Time.get_ticks_msec() + var ws = WebSocketPeer.new() + + + func _init(peer_id, tcp): + id = peer_id + ws.accept_stream(tcp) + + + func is_ws_open() -> bool: + return ws.get_ready_state() == WebSocketPeer.STATE_OPEN + + + func send(type: int, id: int, data:=""): + return ws.send_text(JSON.stringify({ + "type": type, + "id": id, + "data": data, + })) + + +class Lobby extends RefCounted: + var peers: = {} + var peers_order: = [] + var host: int = -1 + var sealed: bool = false + var time = 0 + var mesh := true + var single_host := false + + func _init(host_id: int, use_mesh: bool, is_single_host: bool): + host = host_id + mesh = use_mesh + single_host = is_single_host + + func join(peer: Peer) -> bool: + if sealed: return false + if not peer.is_ws_open(): return false + peer.send(Message.ID, peer.id, "true" if mesh else "") #(1 if peer.id == host else peer.id) + for p in peers.values(): + if not p.is_ws_open(): + continue + if not mesh and p.id != host: + # Only host is visible when using client-server + continue + p.send(Message.PEER_CONNECT, peer.id, str(peers_order[0])) + peer.send(Message.PEER_CONNECT, p.id, str(peers_order[0])) + peers[peer.id] = peer + peers_order.append(peer.id) + return true + + + func leave(peer: Peer) -> bool: + if peers_order.has(peer.id): + peers_order.erase(peer.id) + if peers_order.size()>0 and !single_host: + host=peers_order[0] + if not peers.has(peer.id): return false + peers.erase(peer.id) + var close = false + if peer.id == host: + # The room host disconnected, will disconnect all peers. + close = true + if sealed: return close + # Notify other peers. + for p in peers.values(): + if not p.is_ws_open(): + continue + if close: + # Disconnect peers. + p.ws.close() + else: + # Notify disconnection. + p.send(Message.PEER_DISCONNECT, peer.id) + return close + + + func seal(peer_id: int) -> bool: + # Only host can seal the room. + if host != peer_id: return false + sealed = true + for p in peers.values(): + if not p.is_ws_open(): + continue + p.send(Message.SEAL, 0) + time = Time.get_ticks_msec() + peers.clear() + peers_order.clear() + return true + + +func _process(delta): + poll() + + +func listen(port): + stop() + rand.seed = Time.get_unix_time_from_system() + tcp_server.listen(port) + + +func stop(): + tcp_server.stop() + peers.clear() + + +func poll(): + if not tcp_server.is_listening(): + return + + if tcp_server.is_connection_available(): + var id = randi() % (1 << 31) + peers[id] = Peer.new(id, tcp_server.take_connection()) + + # Poll peers. + var to_remove := [] + for p in peers.values(): + # Peers timeout. + if p.lobby == "" and Time.get_ticks_msec() - p.time > TIMEOUT: + p.ws.close() + p.ws.poll() + while p.is_ws_open() and p.ws.get_available_packet_count(): + if not _parse_msg(p): + print("Parse message failed from peer %d" % p.id) + to_remove.push_back(p.id) + p.ws.close() + break + var state = p.ws.get_ready_state() + if state == WebSocketPeer.STATE_CLOSED: + print("Peer %d disconnected from lobby: '%s'" % [p.id, p.lobby]) + # Remove from lobby (and lobby itself if host). + if lobbies.has(p.lobby) and lobbies[p.lobby].leave(p): + print("Deleted lobby %s" % p.lobby) + lobbies.erase(p.lobby) + # Remove from peers + to_remove.push_back(p.id) + + # Lobby seal. + for k in lobbies: + if not lobbies[k].sealed: + continue + if lobbies[k].time + SEAL_TIME < Time.get_ticks_msec(): + # Close lobby. + for p in lobbies[k].peers: + p.ws.close() + to_remove.push_back(p.id) + + # Remove stale peers + for id in to_remove: + peers.erase(id) + + +func _join_lobby(peer: Peer, lobby: String, mesh: bool, single_host:bool) -> bool: + if lobby == "": + for _i in range(0, 32): + lobby += char(_alfnum[rand.randi_range(0, ALFNUM.length()-1)]) + lobbies[lobby] = Lobby.new(peer.id, mesh, single_host) + elif not lobbies.has(lobby): + return false + lobbies[lobby].join(peer) + peer.lobby = lobby + # Notify peer of its lobby + peer.send(Message.JOIN, 0, lobby) + print("Peer %d joined lobby: '%s'" % [peer.id, lobby]) + return true + + +func _parse_msg(peer: Peer) -> bool: + var pkt_str: String = peer.ws.get_packet().get_string_from_utf8() + var parsed = JSON.parse_string(pkt_str) + if typeof(parsed) != TYPE_DICTIONARY or not parsed.has("type") or not parsed.has("id") or \ + typeof(parsed.get("data")) != TYPE_STRING: + return false + if not str(parsed.type).is_valid_int() or not str(parsed.id).is_valid_int(): + return false + + var msg := { + "type": str(parsed.type).to_int(), + "id": str(parsed.id).to_int(), + "data": parsed.data + } + + if msg.type == Message.JOIN: + if peer.lobby: # Peer must not have joined a lobby already! + return false + var dt = JSON.parse_string(msg.data) + return _join_lobby(peer, dt.lobby, msg.id == 0, dt.single_host) + + if not lobbies.has(peer.lobby): # Lobby not found? + return false + + var lobby = lobbies[peer.lobby] + + if msg.type == Message.SEAL: + # Client is sealing the room + return lobby.seal(peer.id) + + var dest_id: int = msg.id + if dest_id == MultiplayerPeer.TARGET_PEER_SERVER: + dest_id = lobby.host + + if not peers.has(dest_id): # Destination ID not connected + return false + + if peers[dest_id].lobby != peer.lobby: # Trying to contact someone not in same lobby + return false + + if msg.type in [Message.OFFER, Message.ANSWER, Message.CANDIDATE]: + var source = peer.id#MultiplayerPeer.TARGET_PEER_SERVER if peer.id == lobby.host else peer.id + peers[dest_id].send(msg.type, source, msg.data) + return true + + return false # Unknown message diff --git a/server_node/.eslintrc.js b/server_node/.eslintrc.js new file mode 100644 index 0000000..199ba20 --- /dev/null +++ b/server_node/.eslintrc.js @@ -0,0 +1,52 @@ +module.exports = { + "env": { + "browser": true, + "es2021": true, + }, + "extends": [ + "airbnb-base", + ], + "parserOptions": { + "ecmaVersion": 12, + }, + "ignorePatterns": "*.externs.js", + "rules": { + "no-console": "off", + "func-names": "off", + // Use tabs for consistency with the C++ codebase. + "indent": ["error", "tab"], + "max-len": "off", + "no-else-return": ["error", {allowElseIf: true}], + "curly": ["error", "all"], + "brace-style": ["error", "1tbs", { "allowSingleLine": false }], + "no-bitwise": "off", + "no-continue": "off", + "no-self-assign": "off", + "no-tabs": "off", + "no-param-reassign": ["error", { "props": false }], + "no-plusplus": "off", + "no-unused-vars": ["error", { "args": "none" }], + "prefer-destructuring": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "camelcase": "off", + "no-underscore-dangle": "off", + "max-classes-per-file": "off", + "prefer-arrow-callback": "off", + // Messes up with copyright headers in source files. + "spaced-comment": "off", + // Completely breaks emscripten libraries. + "object-shorthand": "off", + // Closure compiler (exported properties) + "quote-props": ["error", "consistent"], + "dot-notation": "off", + // No comma dangle for functions (it's madness, and ES2017) + "comma-dangle": ["error", { + "arrays": "always-multiline", + "objects": "always-multiline", + "imports": "always-multiline", + "exports": "always-multiline", + "functions": "never" + }], + } +}; diff --git a/server_node/.gitignore b/server_node/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/server_node/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/server_node/package-lock.json b/server_node/package-lock.json new file mode 100644 index 0000000..2b6ff22 --- /dev/null +++ b/server_node/package-lock.json @@ -0,0 +1,36 @@ +{ + "name": "signaling_server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "signaling_server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "ws": "^7.5.9" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/server_node/package.json b/server_node/package.json new file mode 100644 index 0000000..0e6cdf4 --- /dev/null +++ b/server_node/package.json @@ -0,0 +1,20 @@ +{ + "name": "signaling_server", + "version": "1.0.0", + "description": "", + "main": "server.js", + "dependencies": { + "ws": "^7.5.9" + }, + "devDependencies": { + "eslint": "^8.28.0", + "eslint-config-airbnb-base": "^14.2.1", + "eslint-plugin-import": "^2.23.4" + }, + "scripts": { + "lint": "eslint server.js && echo \"Lint OK\" && exit 0", + "format": "eslint server.js --fix && echo \"Lint OK\" && exit 0" + }, + "author": "Fabio Alessandrelli", + "license": "MIT" +} diff --git a/server_node/server.js b/server_node/server.js new file mode 100644 index 0000000..064c5f4 --- /dev/null +++ b/server_node/server.js @@ -0,0 +1,297 @@ +const WebSocket = require('ws'); +const crypto = require('crypto'); + +const MAX_PEERS = 4096; +const MAX_LOBBIES = 1024; +const PORT = 9080; +const ALFNUM = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + +const NO_LOBBY_TIMEOUT = 1000; +const SEAL_CLOSE_TIMEOUT = 10000; +const PING_INTERVAL = 10000; + +const STR_NO_LOBBY = 'Have not joined lobby yet'; +const STR_HOST_DISCONNECTED = 'Room host has disconnected'; +const STR_ONLY_HOST_CAN_SEAL = 'Only host can seal the lobby'; +const STR_SEAL_COMPLETE = 'Seal complete'; +const STR_TOO_MANY_LOBBIES = 'Too many lobbies open, disconnecting'; +const STR_ALREADY_IN_LOBBY = 'Already in a lobby'; +const STR_LOBBY_DOES_NOT_EXISTS = 'Lobby does not exists'; +const STR_LOBBY_IS_SEALED = 'Lobby is sealed'; +const STR_INVALID_FORMAT = 'Invalid message format'; +const STR_NEED_LOBBY = 'Invalid message when not in a lobby'; +const STR_SERVER_ERROR = 'Server error, lobby not found'; +const STR_INVALID_DEST = 'Invalid destination'; +const STR_INVALID_CMD = 'Invalid command'; +const STR_TOO_MANY_PEERS = 'Too many peers connected'; +const STR_INVALID_TRANSFER_MODE = 'Invalid transfer mode, must be text'; + +const CMD = { + JOIN: 0, // eslint-disable-line sort-keys + ID: 1, // eslint-disable-line sort-keys + PEER_CONNECT: 2, // eslint-disable-line sort-keys + PEER_DISCONNECT: 3, // eslint-disable-line sort-keys + OFFER: 4, // eslint-disable-line sort-keys + ANSWER: 5, // eslint-disable-line sort-keys + CANDIDATE: 6, // eslint-disable-line sort-keys + SEAL: 7, // eslint-disable-line sort-keys +}; + +function randomInt(low, high) { + return Math.floor(Math.random() * (high - low + 1) + low); +} + +function randomId() { + return Math.abs(new Int32Array(crypto.randomBytes(4).buffer)[0]); +} + +function randomSecret() { + let out = ''; + for (let i = 0; i < 16; i++) { + out += ALFNUM[randomInt(0, ALFNUM.length - 1)]; + } + return out; +} + +function ProtoMessage(type, id, data) { + return JSON.stringify({ + 'type': type, + 'id': id, + 'data': data || '', + }); +} + +const wss = new WebSocket.Server({ port: PORT }); + +class ProtoError extends Error { + constructor(code, message) { + super(message); + this.code = code; + } +} + +class Peer { + constructor(id, ws) { + this.id = id; + this.ws = ws; + this.lobby = ''; + // Close connection after 1 sec if client has not joined a lobby + this.timeout = setTimeout(() => { + if (!this.lobby) { + ws.close(4000, STR_NO_LOBBY); + } + }, NO_LOBBY_TIMEOUT); + } +} + +class Lobby { + constructor(name, host, mesh, single_host) { + this.name = name; + this.host = host; + this.mesh = mesh; + this.single_host = single_host; + this.peers = []; + this.sealed = false; + this.closeTimer = -1; + } + + getPeerId(peer) { + return peer.id; + } + + join(peer) { + const assigned = this.getPeerId(peer); + peer.ws.send(ProtoMessage(CMD.ID, assigned, this.mesh ? 'true' : '')); + this.peers.forEach((p) => { + p.ws.send(ProtoMessage(CMD.PEER_CONNECT, assigned)); + peer.ws.send(ProtoMessage(CMD.PEER_CONNECT, this.getPeerId(p))); + }); + this.peers.push(peer); + } + + leave(peer) { + const idx = this.peers.findIndex((p) => peer === p); + if (idx === -1) { + return false; + } + if (this.peers.length>1 && !this.single_host) { + this.host=this.getPeerId(this.peers[1]) + } + const assigned = this.getPeerId(peer); + const close = assigned === this.host; + this.peers.forEach((p) => { + if (close) { // Room host disconnected, must close. + p.ws.close(4000, STR_HOST_DISCONNECTED); + } else { // Notify peer disconnect. + p.ws.send(ProtoMessage(CMD.PEER_DISCONNECT, assigned)); + } + }); + this.peers.splice(idx, 1); + if (close && this.closeTimer >= 0) { + // We are closing already. + clearTimeout(this.closeTimer); + this.closeTimer = -1; + } + return close; + } + + seal(peer) { + // Only host can seal + if (peer.id !== this.host) { + throw new ProtoError(4000, STR_ONLY_HOST_CAN_SEAL); + } + this.sealed = true; + this.peers.forEach((p) => { + p.ws.send(ProtoMessage(CMD.SEAL, 0)); + }); + console.log(`Peer ${peer.id} sealed lobby ${this.name} ` + + `with ${this.peers.length} peers`); + this.closeTimer = setTimeout(() => { + // Close peer connection to host (and thus the lobby) + this.peers.forEach((p) => { + p.ws.close(1000, STR_SEAL_COMPLETE); + }); + }, SEAL_CLOSE_TIMEOUT); + } +} + +const lobbies = new Map(); +let peersCount = 0; + +function joinLobby(peer, pLobby, mesh, single_host) { + let lobbyName = pLobby; + if (lobbyName === '') { + if (lobbies.size >= MAX_LOBBIES) { + throw new ProtoError(4000, STR_TOO_MANY_LOBBIES); + } + // Peer must not already be in a lobby + if (peer.lobby !== '') { + throw new ProtoError(4000, STR_ALREADY_IN_LOBBY); + } + lobbyName = randomSecret(); + lobbies.set(lobbyName, new Lobby(lobbyName, peer.id, mesh, single_host)); + console.log(`Peer ${peer.id} created lobby ${lobbyName}`); + console.log(`Open lobbies: ${lobbies.size}`); + } + const lobby = lobbies.get(lobbyName); + if (!lobby) { + throw new ProtoError(4000, STR_LOBBY_DOES_NOT_EXISTS); + } + if (lobby.sealed) { + throw new ProtoError(4000, STR_LOBBY_IS_SEALED); + } + peer.lobby = lobbyName; + console.log(`Peer ${peer.id} joining lobby ${lobbyName} ` + + `with ${lobby.peers.length} peers`); + lobby.join(peer); + peer.ws.send(ProtoMessage(CMD.JOIN, 0, lobbyName)); +} + +function parseMsg(peer, msg) { + let json = null; + try { + json = JSON.parse(msg); + } catch (e) { + throw new ProtoError(4000, STR_INVALID_FORMAT); + } + + const type = typeof (json['type']) === 'number' ? Math.floor(json['type']) : -1; + const id = typeof (json['id']) === 'number' ? Math.floor(json['id']) : -1; + const data = typeof (json['data']) === 'string' ? json['data'] : ''; + + if (type < 0 || id < 0) { + throw new ProtoError(4000, STR_INVALID_FORMAT); + } + + // Lobby joining. + if (type === CMD.JOIN) { + const dt = JSON.parse(data); + joinLobby(peer, dt['lobby'], id === 0, dt['single_host']); + return; + } + + if (!peer.lobby) { + throw new ProtoError(4000, STR_NEED_LOBBY); + } + const lobby = lobbies.get(peer.lobby); + if (!lobby) { + throw new ProtoError(4000, STR_SERVER_ERROR); + } + + // Lobby sealing. + if (type === CMD.SEAL) { + lobby.seal(peer); + return; + } + + // Message relaying format: + // + // { + // "type": CMD.[OFFER|ANSWER|CANDIDATE], + // "id": DEST_ID, + // "data": PAYLOAD + // } + if (type === CMD.OFFER || type === CMD.ANSWER || type === CMD.CANDIDATE) { + let destId = id; + if (id === 1) { + destId = lobby.host; + } + const dest = lobby.peers.find((e) => e.id === destId); + // Dest is not in this room. + if (!dest) { + throw new ProtoError(4000, STR_INVALID_DEST); + } + dest.ws.send(ProtoMessage(type, lobby.getPeerId(peer), data)); + return; + } + throw new ProtoError(4000, STR_INVALID_CMD); +} + +wss.on('connection', (ws) => { + if (peersCount >= MAX_PEERS) { + ws.close(4000, STR_TOO_MANY_PEERS); + return; + } + peersCount++; + const id = randomId(); + const peer = new Peer(id, ws); + ws.on('message', (message) => { + if (typeof message !== 'string') { + ws.close(4000, STR_INVALID_TRANSFER_MODE); + return; + } + try { + parseMsg(peer, message); + } catch (e) { + const code = e.code || 4000; + console.log(`Error parsing message from ${id}:\n${ + message}`); + ws.close(code, e.message); + } + }); + ws.on('close', (code, reason) => { + peersCount--; + console.log(`Connection with peer ${peer.id} closed ` + + `with reason ${code}: ${reason}`); + if (peer.lobby && lobbies.has(peer.lobby) + && lobbies.get(peer.lobby).leave(peer)) { + lobbies.delete(peer.lobby); + console.log(`Deleted lobby ${peer.lobby}`); + console.log(`Open lobbies: ${lobbies.size}`); + peer.lobby = ''; + } + if (peer.timeout >= 0) { + clearTimeout(peer.timeout); + peer.timeout = -1; + } + }); + ws.on('error', (error) => { + console.error(error); + }); +}); + +const interval = setInterval(() => { // eslint-disable-line no-unused-vars + wss.clients.forEach((ws) => { + ws.ping(); + }); +}, PING_INTERVAL); diff --git a/server_node/server.js.txt b/server_node/server.js.txt new file mode 100644 index 0000000..9cf5a21 --- /dev/null +++ b/server_node/server.js.txt @@ -0,0 +1,295 @@ +const WebSocket = require('ws'); +const crypto = require('crypto'); + +const MAX_PEERS = 4096; +const MAX_LOBBIES = 1024; +const PORT = 9080; +const ALFNUM = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + +const NO_LOBBY_TIMEOUT = 1000; +const SEAL_CLOSE_TIMEOUT = 10000; +const PING_INTERVAL = 10000; + +const STR_NO_LOBBY = 'Have not joined lobby yet'; +const STR_HOST_DISCONNECTED = 'Room host has disconnected'; +const STR_ONLY_HOST_CAN_SEAL = 'Only host can seal the lobby'; +const STR_SEAL_COMPLETE = 'Seal complete'; +const STR_TOO_MANY_LOBBIES = 'Too many lobbies open, disconnecting'; +const STR_ALREADY_IN_LOBBY = 'Already in a lobby'; +const STR_LOBBY_DOES_NOT_EXISTS = 'Lobby does not exists'; +const STR_LOBBY_IS_SEALED = 'Lobby is sealed'; +const STR_INVALID_FORMAT = 'Invalid message format'; +const STR_NEED_LOBBY = 'Invalid message when not in a lobby'; +const STR_SERVER_ERROR = 'Server error, lobby not found'; +const STR_INVALID_DEST = 'Invalid destination'; +const STR_INVALID_CMD = 'Invalid command'; +const STR_TOO_MANY_PEERS = 'Too many peers connected'; +const STR_INVALID_TRANSFER_MODE = 'Invalid transfer mode, must be text'; + +const CMD = { + JOIN: 0, // eslint-disable-line sort-keys + ID: 1, // eslint-disable-line sort-keys + PEER_CONNECT: 2, // eslint-disable-line sort-keys + PEER_DISCONNECT: 3, // eslint-disable-line sort-keys + OFFER: 4, // eslint-disable-line sort-keys + ANSWER: 5, // eslint-disable-line sort-keys + CANDIDATE: 6, // eslint-disable-line sort-keys + SEAL: 7, // eslint-disable-line sort-keys +}; + +function randomInt(low, high) { + return Math.floor(Math.random() * (high - low + 1) + low); +} + +function randomId() { + return Math.abs(new Int32Array(crypto.randomBytes(4).buffer)[0]); +} + +function randomSecret() { + let out = ''; + for (let i = 0; i < 16; i++) { + out += ALFNUM[randomInt(0, ALFNUM.length - 1)]; + } + return out; +} + +function ProtoMessage(type, id, data) { + return JSON.stringify({ + 'type': type, + 'id': id, + 'data': data || '', + }); +} + +const wss = new WebSocket.Server({ port: PORT }); + +class ProtoError extends Error { + constructor(code, message) { + super(message); + this.code = code; + } +} + +class Peer { + constructor(id, ws) { + this.id = id; + this.ws = ws; + this.lobby = ''; + // Close connection after 1 sec if client has not joined a lobby + this.timeout = setTimeout(() => { + if (!this.lobby) { + ws.close(4000, STR_NO_LOBBY); + } + }, NO_LOBBY_TIMEOUT); + } +} + +class Lobby { + constructor(name, host, mesh) { + this.name = name; + this.host = host; + this.mesh = mesh; + this.peers = []; + this.sealed = false; + this.closeTimer = -1; + } + + getPeerId(peer) { + if (this.host === peer.id) { + return 1; + } + return peer.id; + } + + join(peer) { + const assigned = this.getPeerId(peer); + peer.ws.send(ProtoMessage(CMD.ID, assigned, this.mesh ? 'true' : '')); + this.peers.forEach((p) => { + p.ws.send(ProtoMessage(CMD.PEER_CONNECT, assigned)); + peer.ws.send(ProtoMessage(CMD.PEER_CONNECT, this.getPeerId(p))); + }); + this.peers.push(peer); + } + + leave(peer) { + const idx = this.peers.findIndex((p) => peer === p); + if (idx === -1) { + return false; + } + const assigned = this.getPeerId(peer); + const close = assigned === 1; + this.peers.forEach((p) => { + if (close) { // Room host disconnected, must close. + p.ws.close(4000, STR_HOST_DISCONNECTED); + } else { // Notify peer disconnect. + p.ws.send(ProtoMessage(CMD.PEER_DISCONNECT, assigned)); + } + }); + this.peers.splice(idx, 1); + if (close && this.closeTimer >= 0) { + // We are closing already. + clearTimeout(this.closeTimer); + this.closeTimer = -1; + } + return close; + } + + seal(peer) { + // Only host can seal + if (peer.id !== this.host) { + throw new ProtoError(4000, STR_ONLY_HOST_CAN_SEAL); + } + this.sealed = true; + this.peers.forEach((p) => { + p.ws.send(ProtoMessage(CMD.SEAL, 0)); + }); + console.log(`Peer ${peer.id} sealed lobby ${this.name} ` + + `with ${this.peers.length} peers`); + this.closeTimer = setTimeout(() => { + // Close peer connection to host (and thus the lobby) + this.peers.forEach((p) => { + p.ws.close(1000, STR_SEAL_COMPLETE); + }); + }, SEAL_CLOSE_TIMEOUT); + } +} + +const lobbies = new Map(); +let peersCount = 0; + +function joinLobby(peer, pLobby, mesh) { + let lobbyName = pLobby; + if (lobbyName === '') { + if (lobbies.size >= MAX_LOBBIES) { + throw new ProtoError(4000, STR_TOO_MANY_LOBBIES); + } + // Peer must not already be in a lobby + if (peer.lobby !== '') { + throw new ProtoError(4000, STR_ALREADY_IN_LOBBY); + } + lobbyName = randomSecret(); + lobbies.set(lobbyName, new Lobby(lobbyName, peer.id, mesh)); + console.log(`Peer ${peer.id} created lobby ${lobbyName}`); + console.log(`Open lobbies: ${lobbies.size}`); + } + const lobby = lobbies.get(lobbyName); + if (!lobby) { + throw new ProtoError(4000, STR_LOBBY_DOES_NOT_EXISTS); + } + if (lobby.sealed) { + throw new ProtoError(4000, STR_LOBBY_IS_SEALED); + } + peer.lobby = lobbyName; + console.log(`Peer ${peer.id} joining lobby ${lobbyName} ` + + `with ${lobby.peers.length} peers`); + lobby.join(peer); + peer.ws.send(ProtoMessage(CMD.JOIN, 0, lobbyName)); +} + +function parseMsg(peer, msg) { + let json = null; + try { + json = JSON.parse(msg); + } catch (e) { + throw new ProtoError(4000, STR_INVALID_FORMAT); + } + + const type = typeof (json['type']) === 'number' ? Math.floor(json['type']) : -1; + const id = typeof (json['id']) === 'number' ? Math.floor(json['id']) : -1; + const data = typeof (json['data']) === 'string' ? json['data'] : ''; + + if (type < 0 || id < 0) { + throw new ProtoError(4000, STR_INVALID_FORMAT); + } + + // Lobby joining. + if (type === CMD.JOIN) { + joinLobby(peer, data, id === 0); + return; + } + + if (!peer.lobby) { + throw new ProtoError(4000, STR_NEED_LOBBY); + } + const lobby = lobbies.get(peer.lobby); + if (!lobby) { + throw new ProtoError(4000, STR_SERVER_ERROR); + } + + // Lobby sealing. + if (type === CMD.SEAL) { + lobby.seal(peer); + return; + } + + // Message relaying format: + // + // { + // "type": CMD.[OFFER|ANSWER|CANDIDATE], + // "id": DEST_ID, + // "data": PAYLOAD + // } + if (type === CMD.OFFER || type === CMD.ANSWER || type === CMD.CANDIDATE) { + let destId = id; + if (id === 1) { + destId = lobby.host; + } + const dest = lobby.peers.find((e) => e.id === destId); + // Dest is not in this room. + if (!dest) { + throw new ProtoError(4000, STR_INVALID_DEST); + } + dest.ws.send(ProtoMessage(type, lobby.getPeerId(peer), data)); + return; + } + throw new ProtoError(4000, STR_INVALID_CMD); +} + +wss.on('connection', (ws) => { + if (peersCount >= MAX_PEERS) { + ws.close(4000, STR_TOO_MANY_PEERS); + return; + } + peersCount++; + const id = randomId(); + const peer = new Peer(id, ws); + ws.on('message', (message) => { + if (typeof message !== 'string') { + ws.close(4000, STR_INVALID_TRANSFER_MODE); + return; + } + try { + parseMsg(peer, message); + } catch (e) { + const code = e.code || 4000; + console.log(`Error parsing message from ${id}:\n${ + message}`); + ws.close(code, e.message); + } + }); + ws.on('close', (code, reason) => { + peersCount--; + console.log(`Connection with peer ${peer.id} closed ` + + `with reason ${code}: ${reason}`); + if (peer.lobby && lobbies.has(peer.lobby) + && lobbies.get(peer.lobby).leave(peer)) { + lobbies.delete(peer.lobby); + console.log(`Deleted lobby ${peer.lobby}`); + console.log(`Open lobbies: ${lobbies.size}`); + peer.lobby = ''; + } + if (peer.timeout >= 0) { + clearTimeout(peer.timeout); + peer.timeout = -1; + } + }); + ws.on('error', (error) => { + console.error(error); + }); +}); + +const interval = setInterval(() => { // eslint-disable-line no-unused-vars + wss.clients.forEach((ws) => { + ws.ping(); + }); +}, PING_INTERVAL); diff --git a/webrtc/LICENSE.json b/webrtc/LICENSE.json new file mode 100644 index 0000000..1c1f7a6 --- /dev/null +++ b/webrtc/LICENSE.json @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2022 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/webrtc/LICENSE.libdatachannel b/webrtc/LICENSE.libdatachannel new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/webrtc/LICENSE.libdatachannel @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/webrtc/LICENSE.libjuice b/webrtc/LICENSE.libjuice new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/webrtc/LICENSE.libjuice @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/webrtc/LICENSE.libsrtp b/webrtc/LICENSE.libsrtp new file mode 100644 index 0000000..af0a2ac --- /dev/null +++ b/webrtc/LICENSE.libsrtp @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2001-2017 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ diff --git a/webrtc/LICENSE.openssl b/webrtc/LICENSE.openssl new file mode 100644 index 0000000..49cc83d --- /dev/null +++ b/webrtc/LICENSE.openssl @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/webrtc/LICENSE.plog b/webrtc/LICENSE.plog new file mode 100644 index 0000000..8a91a0a --- /dev/null +++ b/webrtc/LICENSE.plog @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Sergey Podobry + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/webrtc/LICENSE.usrsctp b/webrtc/LICENSE.usrsctp new file mode 100644 index 0000000..a2d1f98 --- /dev/null +++ b/webrtc/LICENSE.usrsctp @@ -0,0 +1,27 @@ +Copyright (c) 2015, Randall Stewart and Michael Tuexen +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of usrsctp nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/webrtc/LICENSE.webrtc-native b/webrtc/LICENSE.webrtc-native new file mode 100644 index 0000000..ec92632 --- /dev/null +++ b/webrtc/LICENSE.webrtc-native @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Godot Engine + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/webrtc/lib/libwebrtc_native.android.template_debug.arm64.so b/webrtc/lib/libwebrtc_native.android.template_debug.arm64.so new file mode 100644 index 0000000..fc45b56 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.android.template_debug.arm64.so differ diff --git a/webrtc/lib/libwebrtc_native.android.template_debug.x86_64.so b/webrtc/lib/libwebrtc_native.android.template_debug.x86_64.so new file mode 100644 index 0000000..081fe35 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.android.template_debug.x86_64.so differ diff --git a/webrtc/lib/libwebrtc_native.android.template_release.arm64.so b/webrtc/lib/libwebrtc_native.android.template_release.arm64.so new file mode 100644 index 0000000..e438270 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.android.template_release.arm64.so differ diff --git a/webrtc/lib/libwebrtc_native.android.template_release.x86_64.so b/webrtc/lib/libwebrtc_native.android.template_release.x86_64.so new file mode 100644 index 0000000..e5bdcc1 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.android.template_release.x86_64.so differ diff --git a/webrtc/lib/libwebrtc_native.ios.template_debug.arm64.dylib b/webrtc/lib/libwebrtc_native.ios.template_debug.arm64.dylib new file mode 100644 index 0000000..bdf5e35 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.ios.template_debug.arm64.dylib differ diff --git a/webrtc/lib/libwebrtc_native.ios.template_debug.x86_64.simulator.dylib b/webrtc/lib/libwebrtc_native.ios.template_debug.x86_64.simulator.dylib new file mode 100644 index 0000000..2d8db21 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.ios.template_debug.x86_64.simulator.dylib differ diff --git a/webrtc/lib/libwebrtc_native.ios.template_release.arm64.dylib b/webrtc/lib/libwebrtc_native.ios.template_release.arm64.dylib new file mode 100644 index 0000000..9389e03 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.ios.template_release.arm64.dylib differ diff --git a/webrtc/lib/libwebrtc_native.ios.template_release.x86_64.simulator.dylib b/webrtc/lib/libwebrtc_native.ios.template_release.x86_64.simulator.dylib new file mode 100644 index 0000000..f1cbbfb Binary files /dev/null and b/webrtc/lib/libwebrtc_native.ios.template_release.x86_64.simulator.dylib differ diff --git a/webrtc/lib/libwebrtc_native.linux.template_debug.x86_32.so b/webrtc/lib/libwebrtc_native.linux.template_debug.x86_32.so new file mode 100644 index 0000000..67988b9 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.linux.template_debug.x86_32.so differ diff --git a/webrtc/lib/libwebrtc_native.linux.template_debug.x86_64.so b/webrtc/lib/libwebrtc_native.linux.template_debug.x86_64.so new file mode 100644 index 0000000..9d647fc Binary files /dev/null and b/webrtc/lib/libwebrtc_native.linux.template_debug.x86_64.so differ diff --git a/webrtc/lib/libwebrtc_native.linux.template_release.x86_32.so b/webrtc/lib/libwebrtc_native.linux.template_release.x86_32.so new file mode 100644 index 0000000..19d34d4 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.linux.template_release.x86_32.so differ diff --git a/webrtc/lib/libwebrtc_native.linux.template_release.x86_64.so b/webrtc/lib/libwebrtc_native.linux.template_release.x86_64.so new file mode 100644 index 0000000..686252c Binary files /dev/null and b/webrtc/lib/libwebrtc_native.linux.template_release.x86_64.so differ diff --git a/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/Resources/Info.plist b/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/Resources/Info.plist new file mode 100644 index 0000000..f4d8e8a --- /dev/null +++ b/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleExecutable + libwebrtc_native.macos.template_debug.universal.dylib + CFBundleIdentifier + org.godotengine.webrtc-native + CFBundleInfoDictionaryVersion + 6.0 + CFBundleDisplayName + libwebrtc_native.macos.template_debug.universal + CFBundleName + webrtc_native + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1.0.0 + LSMinimumSystemVersion + 11.0 + + diff --git a/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/libwebrtc_native.macos.template_debug.universal.dylib b/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/libwebrtc_native.macos.template_debug.universal.dylib new file mode 100644 index 0000000..de690a0 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.macos.template_debug.universal.framework/libwebrtc_native.macos.template_debug.universal.dylib differ diff --git a/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/Resources/Info.plist b/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/Resources/Info.plist new file mode 100644 index 0000000..a0219e7 --- /dev/null +++ b/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleExecutable + libwebrtc_native.macos.template_release.universal.dylib + CFBundleIdentifier + org.godotengine.webrtc-native + CFBundleInfoDictionaryVersion + 6.0 + CFBundleDisplayName + libwebrtc_native.macos.template_release.universal + CFBundleName + webrtc_native + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1.0.0 + LSMinimumSystemVersion + 11.0 + + diff --git a/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/libwebrtc_native.macos.template_release.universal.dylib b/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/libwebrtc_native.macos.template_release.universal.dylib new file mode 100644 index 0000000..b425616 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.macos.template_release.universal.framework/libwebrtc_native.macos.template_release.universal.dylib differ diff --git a/webrtc/lib/libwebrtc_native.windows.template_debug.x86_32.dll b/webrtc/lib/libwebrtc_native.windows.template_debug.x86_32.dll new file mode 100644 index 0000000..003d9d2 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.windows.template_debug.x86_32.dll differ diff --git a/webrtc/lib/libwebrtc_native.windows.template_debug.x86_64.dll b/webrtc/lib/libwebrtc_native.windows.template_debug.x86_64.dll new file mode 100644 index 0000000..a4b2697 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.windows.template_debug.x86_64.dll differ diff --git a/webrtc/lib/libwebrtc_native.windows.template_release.x86_32.dll b/webrtc/lib/libwebrtc_native.windows.template_release.x86_32.dll new file mode 100644 index 0000000..451baf0 Binary files /dev/null and b/webrtc/lib/libwebrtc_native.windows.template_release.x86_32.dll differ diff --git a/webrtc/lib/libwebrtc_native.windows.template_release.x86_64.dll b/webrtc/lib/libwebrtc_native.windows.template_release.x86_64.dll new file mode 100644 index 0000000..bc62c5d Binary files /dev/null and b/webrtc/lib/libwebrtc_native.windows.template_release.x86_64.dll differ diff --git a/webrtc/webrtc.gdextension b/webrtc/webrtc.gdextension new file mode 100644 index 0000000..a112463 --- /dev/null +++ b/webrtc/webrtc.gdextension @@ -0,0 +1,30 @@ +[configuration] + +entry_symbol = "webrtc_extension_init" +compatibility_minimum = 4.1 + +[libraries] + +linux.debug.x86_64 = "lib/libwebrtc_native.linux.template_debug.x86_64.so" +linux.debug.x86_32 = "lib/libwebrtc_native.linux.template_debug.x86_32.so" +linux.debug.arm64 = "lib/libwebrtc_native.linux.template_debug.arm64.so" +linux.debug.arm32 = "lib/libwebrtc_native.linux.template_debug.arm32.so" +macos.debug = "lib/libwebrtc_native.macos.template_debug.universal.framework" +windows.debug.x86_64 = "lib/libwebrtc_native.windows.template_debug.x86_64.dll" +windows.debug.x86_32 = "lib/libwebrtc_native.windows.template_debug.x86_32.dll" +android.debug.arm64 = "lib/libwebrtc_native.android.template_debug.arm64.so" +android.debug.x86_64 = "lib/libwebrtc_native.android.template_debug.x86_64.so" +ios.debug.arm64 = "lib/libwebrtc_native.ios.template_debug.arm64.dylib" +ios.debug.x86_64 = "lib/libwebrtc_native.ios.template_debug.x86_64.simulator.dylib" + +linux.release.x86_64 = "lib/libwebrtc_native.linux.template_release.x86_64.so" +linux.release.x86_32 = "lib/libwebrtc_native.linux.template_release.x86_32.so" +linux.release.arm64 = "lib/libwebrtc_native.linux.template_release.arm64.so" +linux.release.arm32 = "lib/libwebrtc_native.linux.template_release.arm32.so" +macos.release = "lib/libwebrtc_native.macos.template_release.universal.framework" +windows.release.x86_64 = "lib/libwebrtc_native.windows.template_release.x86_64.dll" +windows.release.x86_32 = "lib/libwebrtc_native.windows.template_release.x86_32.dll" +android.release.arm64 = "lib/libwebrtc_native.android.template_release.arm64.so" +android.release.x86_64 = "lib/libwebrtc_native.android.template_release.x86_64.so" +ios.release.arm64 = "lib/libwebrtc_native.ios.template_release.arm64.dylib" +ios.release.x86_64 = "lib/libwebrtc_native.ios.template_release.x86_64.simulator.dylib"