Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Jason WebSocket reconnection (#47) #75

Merged
merged 124 commits into from
Jan 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
2c098d0
Add RpcTransport::reconnect
evdokimovs Dec 3, 2019
c93a752
Added reconnection?? (currently not prooved)
evdokimovs Dec 3, 2019
9ccf7d2
on_message after reconnection fixed, but on_close after reconnection …
evdokimovs Dec 5, 2019
1a52a3f
Fix socket borrowing
evdokimovs Dec 5, 2019
fa17c10
YAY all works fine
evdokimovs Dec 6, 2019
aebc367
Cleanup
evdokimovs Dec 6, 2019
7a86dc6
Refactor
evdokimovs Dec 6, 2019
e70c652
Merge branch 'master' into 47-rpc-reconnection
evdokimovs Dec 9, 2019
24698a5
Some error management
evdokimovs Dec 9, 2019
2e0179e
Fix tests compilation, some refactor
evdokimovs Dec 9, 2019
c32af52
Fix tests and some bugs
evdokimovs Dec 10, 2019
aab34c3
Add tests for reconnection, remove some unwraps, add docs
evdokimovs Dec 10, 2019
ad3a74f
Merge branch 'master' into 47-rpc-reconnection
evdokimovs Dec 10, 2019
d2f07a8
Remove useless takes from Drop implementation
evdokimovs Dec 10, 2019
1e97d55
Reread [run ci]
evdokimovs Dec 11, 2019
909ef65
Reconnection timeout usage
evdokimovs Dec 12, 2019
ab398d4
Add some docs, refactor
evdokimovs Dec 12, 2019
e5fd060
Add test for reconnection deadline
evdokimovs Dec 12, 2019
3eed4c8
Reread [run ci]
evdokimovs Dec 12, 2019
4003cd6
rustfmt [run ci]
evdokimovs Dec 12, 2019
4e38650
Fix tests [run ci]
evdokimovs Dec 12, 2019
0d707d6
Correct some docs
evdokimovs Dec 12, 2019
a22c3ff
Update CHANGELOGs
evdokimovs Dec 12, 2019
c425c66
Add minor comment
evdokimovs Dec 12, 2019
7c54e11
Fix mistype in CHANGELOG
evdokimovs Dec 12, 2019
db9b597
Formatting fix
evdokimovs Dec 12, 2019
8a1ecff
Refactor heartbeat mechanism (mainly on Jason side)
evdokimovs Dec 13, 2019
45e1f3d
Some temporary crutch for Medea's heartbeat
evdokimovs Dec 13, 2019
2bff0d1
Send Pings with nums from a server
evdokimovs Dec 13, 2019
8931082
Add configuration of ping_interval
evdokimovs Dec 16, 2019
553fe74
Merge branch 'master' into 47-rpc-reconnection
evdokimovs Dec 16, 2019
37806cd
Fix tests compillation
evdokimovs Dec 16, 2019
a31a8e1
Fix some bugs, refactor ProgressiveDelayer
evdokimovs Dec 17, 2019
6218243
Minor style fix
evdokimovs Dec 17, 2019
c9954aa
Try pong before idle_timeout
evdokimovs Dec 18, 2019
25f6a67
Add ReconnectHandle, change map_weak! macro to trait
evdokimovs Dec 18, 2019
063f480
Implement reconnection configuration
evdokimovs Dec 18, 2019
b492160
Implement reconnection with backoff
evdokimovs Dec 18, 2019
5112a1f
Fix reconnect_timeout in dev config
evdokimovs Dec 18, 2019
a32f207
Fix some warns
evdokimovs Dec 19, 2019
b5ac037
Add and use JsDuration
evdokimovs Dec 19, 2019
adf2bc7
Use newtype for video/audio muting
evdokimovs Dec 19, 2019
1f32630
Use JsDuration in ProgressiveDelayer
evdokimovs Dec 19, 2019
3cc5763
Refactor are_senders_enabled
evdokimovs Dec 19, 2019
ef9fde9
Simple reconnector locking implementation
evdokimovs Dec 19, 2019
0bbe7f9
Implement Reconnector locking with guard
evdokimovs Dec 19, 2019
3b0eedd
Fix ReconnectorLock, some refactor
evdokimovs Dec 19, 2019
5120eb4
Instantly resolve reconnect promise if RpcClient already openned
evdokimovs Dec 19, 2019
d3d3802
Resolve Option::flatten TODO because it stabilized, minor refactor of…
evdokimovs Dec 19, 2019
0a78db5
Fix Jason tests
evdokimovs Dec 20, 2019
db631f4
Add docs, some styling fixes
evdokimovs Dec 20, 2019
d312c97
Add docs, fix some warns and formatting
evdokimovs Dec 20, 2019
d34cb09
Subscribe to the RpcTransport state for reconnecting
evdokimovs Dec 20, 2019
f95a777
Add reconnection notification into 'e2e-demo'
evdokimovs Dec 20, 2019
06f64d6
Refactor
evdokimovs Dec 23, 2019
3f6d88c
Fix tests
evdokimovs Dec 23, 2019
6bd00e7
Add some docs
evdokimovs Dec 23, 2019
8012b39
Fix for floating number precision in 'JsDuration'
evdokimovs Dec 23, 2019
f831f61
Fix lints
evdokimovs Dec 23, 2019
396dabe
Reread
evdokimovs Dec 23, 2019
ac44543
Add tests for heartbeat
evdokimovs Dec 23, 2019
594a8d7
Add tests for state subscibing while reconnecting
evdokimovs Dec 24, 2019
5acd0ec
Add tests for the BackoffDelayer
evdokimovs Dec 24, 2019
b65924d
Add test docs
evdokimovs Dec 24, 2019
7fbe703
Reread, add CHANGELOGs
evdokimovs Dec 24, 2019
b2e26a2
Upd deps [run ci]
evdokimovs Dec 24, 2019
e316769
Bump rust version [run ci]
evdokimovs Dec 24, 2019
1c125d2
Minor fixes
evdokimovs Dec 24, 2019
7c37b45
Add todos
alexlapa Dec 25, 2019
4e93807
Fix 'click' listener in 'e2e-demo', merge 'CallbackNotSet' errors
evdokimovs Dec 25, 2019
cca8afd
Improve docs
evdokimovs Dec 25, 2019
5ae6a77
Add connection state and reconnection with backoff into 'demo'
evdokimovs Dec 25, 2019
23d239b
Send RpcSettingsUpdate on every connection
evdokimovs Dec 25, 2019
bf3dd1b
Upd RFC
evdokimovs Dec 25, 2019
39aa873
1
alexlapa Dec 25, 2019
479ffd8
Merge remote-tracking branch 'origin/47-rpc-reconnection' into 47-rpc…
alexlapa Dec 25, 2019
7c05371
Fix test
evdokimovs Dec 25, 2019
6adacea
Refactor heartbeat
evdokimovs Dec 25, 2019
8c0c61c
Fix warns/lints [run ci]
evdokimovs Dec 25, 2019
b161ca6
Print Error with trace
evdokimovs Dec 25, 2019
4167939
Minor changes
evdokimovs Dec 25, 2019
61fc564
add todos
alexlapa Dec 26, 2019
188e29f
Merge branch 'master' into 47-rpc-reconnection
evdokimovs Dec 26, 2019
169f6b5
Merge branch '47-rpc-reconnection' of github.com:instrumentisto/medea…
evdokimovs Dec 26, 2019
560d856
Move RpcSettingsUpdated from Server::Msg::Event into ServerMsg
evdokimovs Dec 26, 2019
534505c
Use factory for RpcTransport creating
evdokimovs Dec 26, 2019
3c6f5dd
Use RpcClient::connect in ReconnectHandle
evdokimovs Dec 26, 2019
e2603a2
Correct connect behavior but with wrong state
evdokimovs Dec 26, 2019
2a92096
RpcClient state and subscibing to it
evdokimovs Dec 26, 2019
6235d94
Reconnect with backoff
evdokimovs Dec 26, 2019
87f1b06
Resolve connect after RpcSettingsUpdated receiving
evdokimovs Dec 26, 2019
d2ec6d9
Send pre-pong based on maximum ping interval
evdokimovs Dec 26, 2019
11c8291
Refactor
evdokimovs Dec 27, 2019
1b34ffe
Remove structures for Weak, refactor
evdokimovs Dec 27, 2019
af6047c
URL now &str
evdokimovs Dec 27, 2019
5e0b02d
Error handling in ReconnectHandle
evdokimovs Dec 27, 2019
03d5122
Remove JasonWeakHandler and add new_js_error! macro
evdokimovs Dec 27, 2019
b82a5bc
Fix warns, fmt, refactor
evdokimovs Dec 27, 2019
2fdc928
Fixing test WIP
evdokimovs Dec 27, 2019
3afc343
Use ping_interval * 2
evdokimovs Dec 27, 2019
1327916
Fix medea tests
evdokimovs Dec 27, 2019
dd542b4
Some docs, refactor
evdokimovs Dec 28, 2019
2841cfe
Merge branch 'master' into 47-rpc-reconnection
evdokimovs Dec 30, 2019
7e3023a
Fix heartbeat test
evdokimovs Dec 30, 2019
2cabb61
Fix some panics while medea tests
evdokimovs Dec 30, 2019
509bdc6
Add tests for state in RpcClient::connect
evdokimovs Dec 30, 2019
9c59446
Yay fixed this silent tests fail
evdokimovs Dec 30, 2019
3fe5cf1
Fix warns, refactor, some docs, fix some tests
evdokimovs Dec 30, 2019
abfbce1
Remove Event::RpcSettingsUpdated from RFC
evdokimovs Dec 30, 2019
c79bb50
Fix lints
evdokimovs Dec 30, 2019
1b9e572
Remove RpcTransport::on_close, provide reasons into Close state
evdokimovs Jan 2, 2020
0ade154
Refactor, add some docs
evdokimovs Jan 2, 2020
f6e7da8
Reread
evdokimovs Jan 2, 2020
6209fad
Reread [run ci]
evdokimovs Jan 2, 2020
a02059e
Final docs corrections
evdokimovs Jan 2, 2020
582271c
review [run ci]
alexlapa Jan 8, 2020
a8b4093
Add minor doc
evdokimovs Jan 8, 2020
9d0ce26
Correct client-api proto [skip ci]
tyranron Jan 14, 2020
ba386aa
Correct client-api proto [skip ci]
tyranron Jan 14, 2020
272b79e
Correct control-api proto [skip ci]
tyranron Jan 14, 2020
a384fa0
Correct medea [skip ci]
tyranron Jan 14, 2020
4b56a37
Correct medea-jason [skip ci]
tyranron Jan 16, 2020
a645f06
Fix Send/Sync issue in a Jason test
evdokimovs Jan 16, 2020
1b45588
Fix JsDuration multiplication on f64 [run ci]
evdokimovs Jan 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ All user visible changes to this project will be documented in this file. This p

- Configuration:
- Rename `[server]` section of Client API HTTP server as `[server.client.http]` ([#33]).
- RPC messaging:
- Reverse `Ping`/`Pong` naming: server sends `Ping` and expects `Pongs` from client now. ([#75]).

### Added

Expand All @@ -31,16 +33,19 @@ All user visible changes to this project will be documented in this file. This p
- Dynamic `Peer`s creation when client connects ([#28]);
- Auto-removing `Peer`s when `Member` disconnects ([#28]);
- Filter `SetIceCandidate` messages without `candidate` ([#50](/../../pull/50));
- Send reason of closing WebSocket connection as [Close](https://tools.ietf.org/html/rfc4566#section-5.14) frame's description ([#58](/../../pull/58)).
- Send reason of closing WebSocket connection as [Close](https://tools.ietf.org/html/rfc4566#section-5.14) frame's description ([#58](/../../pull/58));
- Send `Event::RpcSettingsUpdated` when `Member` connects ([#75]);
- Configuration:
- `[server.control.grpc]` section to configure Control API gRPC server ([#33]);
- `server.client.http.public_url` option to configure public URL of Client API HTTP server ([#33]).
- `server.client.http.public_url` option to configure public URL of Client API HTTP server ([#33]);
- `rpc.ping_interval` option to configure `Ping`s sending interval ([#75]).
- Testing:
- E2E tests for signalling ([#28]).

[#28]: /../../pull/28
[#33]: /../../pull/33
[#63]: /../../pull/63
[#75]: /../../pull/75



Expand Down
293 changes: 147 additions & 146 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
# Default:
# reconnect_timeout = "10s"

# Interval between pings that server sends to clients.
#
# Env var: MEDEA_RPC__PING_INTERVAL
# Default:
# ping_interval = "3s"




Expand Down
9 changes: 8 additions & 1 deletion jason/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ All user visible changes to this project will be documented in this file. This p
- Remove error argument from `on_local_stream` callback ([#54]);
- Room initialization ([#46]):
- Remove `Jason.join_room()`.
- Transport and messaging:
- Reverse `ping`/`pong` mechanism: expect `Ping`s from server and answer with `Pong`s ([#75]).

### Added

Expand All @@ -40,9 +42,13 @@ All user visible changes to this project will be documented in this file. This p
- `Room.join()`;
- Ability to inject local video/audio stream into `Room` via `Room.inject_local_stream()` ([#54]);
- `Room.on_failed_local_stream` callback ([#54]);
- Room management:
- Library API:
- `Room.on_connection_loss` callback that JS side can start Jason reconnection on connection loss with ([#75]);
- `Room.on_close` callback for WebSocket close initiated by server ([#55]).
- RPC messaging:
- Cleanup Jason state on normal (`code = 1000`) WebSocket close ([#55]).
- Cleanup Jason state on normal (`code = 1000`) WebSocket close ([#55]);
- `RpcClient` and `RpcTransport` reconnection ([#75]).
- Signalling:
- Emitting of RPC commands:
- `AddPeerConnectionMetrics` with `IceConnectionState` ([#71](/../../pull/71)).
Expand All @@ -58,6 +64,7 @@ All user visible changes to this project will be documented in this file. This p
[#46]: /../../pull/46
[#54]: /../../pull/54
[#55]: /../../pull/55
[#75]: /../../pull/75



Expand Down
31 changes: 27 additions & 4 deletions jason/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<title>Chat</title>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fakerator@0.3.0/dist/fakerator.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

Expand Down Expand Up @@ -156,7 +156,7 @@

let joinCallerButton = document.getElementById('join__join');
let usernameInput = document.getElementById('join__username');
usernameInput.value = faker.name.firstName();
usernameInput.value = Fakerator().names.firstNameM();

let room = await jason.init_room();

Expand Down Expand Up @@ -206,7 +206,23 @@
});
});

let connectionState = document.getElementById('connection-state__state');
room.on_connection_loss(async (reconnectHandle) => {
connectionState.className = 'badge badge-warning';
connectionState.textContent = 'Reconnecting';

try {
await reconnectHandle.reconnect_with_backoff(500, 2.0, 10000);
connectionState.className = 'badge badge-success';
connectionState.textContent = 'Connected';
} catch (e) {
console.error(e);
}
});

room.on_close(function (on_closed) {
connectionState.className = 'badge badge-danger';
connectionState.textContent = "Closed";
alert(
`Call was ended.
Reason: ${on_closed.reason()};
Expand Down Expand Up @@ -263,6 +279,8 @@
await axios.delete(controlUrl + roomId + '/' + username);
console.log("Creating new member.");
await room.join(await addNewMember(roomId, username));
connectionState.className = 'badge badge-success';
connectionState.textContent = 'Connected';

} catch (e) {
logError("Join to room failed", e);
Expand Down Expand Up @@ -362,8 +380,13 @@
</div>

<div id="control" class="input-group mb-3" style="display: none">
<button class="btn btn-info" id="control__mute_audio">Mute audio</button>
<button class="btn btn-info" id="control__mute_video">Mute video</button>
<button class="btn btn-info" id="control__mute_audio">Mute audio</button>
<button class="btn btn-info" id="control__mute_video">Mute video</button>
</div>

<div>
<span>Connection state: </span>
<span id="connection-state__state" class="badge badge-danger">Closed</span>
</div>

</div>
Expand Down
28 changes: 28 additions & 0 deletions jason/e2e-demo/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,34 @@ window.onload = async function() {
console.error(error);
});

room.on_connection_loss( async (reconnectHandle) => {
let connectionLossNotification = document.getElementsByClassName('connection-loss-notification')[0];
contentVisibility.show(connectionLossNotification);

let manualReconnectBtn = document.getElementsByClassName('connection-loss-notification__manual-reconnect')[0];
let connectionLossMsg = document.getElementsByClassName('connection-loss-notification__msg')[0];
let connectionLossDefaultText = connectionLossMsg.textContent;

manualReconnectBtn.onclick = async () => {
try {
connectionLossMsg.textContent = 'Trying to manually reconnect...';
await reconnectHandle.reconnect_with_delay(0);
contentVisibility.hide(connectionLossNotification);
console.error("Reconnected!");
} catch (e) {
console.error("Failed to manually reconnect: " + e.message());
} finally {
connectionLossMsg.textContent = connectionLossDefaultText;
}
};
try {
await reconnectHandle.reconnect_with_backoff(3000, 2.0, 10000);
} catch (e) {
console.error('Error in reconnection with backoff:\n' + e.message());
}
contentVisibility.hide(connectionLossNotification);
});

room.on_close(function (on_closed) {
let videos = document.getElementsByClassName('remote-videos')[0];
while (videos.firstChild) {
Expand Down
28 changes: 28 additions & 0 deletions jason/e2e-demo/video-call.html
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,28 @@
.control-debug__table-result>table>tr>th {
font-weight: normal;
}

.connection-loss-notification {
right: 50px;
top: 50px;
position: absolute;
background: #fff;
padding: 10px;
border-radius: 3px;
font-size: 11pt;
}

.connection-loss-notification__msg {
display: block;
}

.connection-loss-notification__manual-reconnect {
display: block;
color: #49668C;
text-align: center;
cursor: pointer;
margin-top: 5px;
}
</style>
</head>
<body>
Expand Down Expand Up @@ -343,6 +365,12 @@
</div>
</div>

<div class="connection-loss-notification toggle-content">
<span class="connection-loss-notification__msg">Connection lost.</span>
<span>Trying to reconnect with backoff...</span>
<a class="connection-loss-notification__manual-reconnect">Reconnect now</a>
</div>

<div class="control-debug-menu__toggle">
Dynamic Control API
</div>
Expand Down
11 changes: 6 additions & 5 deletions jason/src/api/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use std::{

use wasm_bindgen::prelude::*;

use crate::{peer::MediaStreamHandle, utils::Callback};
use crate::{
peer::MediaStreamHandle,
utils::{Callback, HandlerDetachedError},
};

/// Actual data of a connection with a specific remote [`Member`].
///
Expand All @@ -31,10 +34,8 @@ impl ConnectionHandle {
&mut self,
f: js_sys::Function,
) -> Result<(), JsValue> {
map_weak!(self, |inner| inner
.borrow_mut()
.on_remote_stream
.set_func(f))
upgrade_or_detached!(self.0)
.map(|inner| inner.borrow_mut().on_remote_stream.set_func(f))
}
}

Expand Down
18 changes: 14 additions & 4 deletions jason/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use wasm_bindgen_futures::spawn_local;
use crate::{
media::{MediaManager, MediaManagerHandle},
peer,
rpc::{ClientDisconnect, RpcClient as _, WebSocketRpcClient},
rpc::{
ClientDisconnect, RpcClient as _, RpcTransport, WebSocketRpcClient,
WebSocketRpcTransport,
},
set_panic_hook,
};

Expand Down Expand Up @@ -44,13 +47,20 @@ impl Jason {

/// Returns [`RoomHandle`] for [`Room`].
pub fn init_room(&self) -> RoomHandle {
let rpc = Rc::new(WebSocketRpcClient::new(3000));
let rpc = WebSocketRpcClient::new(Box::new(|token| {
Box::pin(async move {
let ws = WebSocketRpcTransport::new(&token)
.await
.map_err(|e| tracerr::new!(e))?;
Ok(Rc::new(ws) as Rc<dyn RpcTransport>)
})
}));
let peer_repository = Box::new(peer::Repository::new(Rc::clone(
&self.0.borrow().media_manager,
)));

let inner = self.0.clone();
spawn_local(rpc.on_close().map(move |res| {
spawn_local(rpc.on_normal_close().map(move |res| {
// TODO: Don't close all rooms when multiple rpc connections
// will be supported.
let reason = res.unwrap_or_else(|_| {
Expand All @@ -64,7 +74,7 @@ impl Jason {
inner.borrow_mut().media_manager = Rc::default();
}));

let room = Room::new(rpc, peer_repository);
let room = Room::new(Rc::new(rpc), peer_repository);
let handle = room.new_handle();
self.0.borrow_mut().rooms.push(room);
handle
Expand Down
Loading