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

Commit

Permalink
Configure Member's RPC connection settings via Control API (#95, #27)
Browse files Browse the repository at this point in the history
- add 'idle_timeout', 'reconnect_timeout' and 'ping_interval' to Member spec in Control API
- add RPC connection configuration fields to the 'e2e-demo' and 'medea-control-api-mock'
  • Loading branch information
evdokimovs authored Apr 7, 2020
1 parent 06db43d commit 43b9242
Show file tree
Hide file tree
Showing 32 changed files with 798 additions and 171 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ All user visible changes to this project will be documented in this file. This p
- gRPC Control API callbacks ([#63]):
- `on_join`;
- `on_leave`.
- Configuration of `Member`'s Client API RPC settings ([#95]).
- Signalling:
- Dynamic `Peer`s creation when client connects ([#28]);
- Auto-removing `Peer`s when `Member` disconnects ([#28]);
Expand Down Expand Up @@ -64,6 +65,7 @@ All user visible changes to this project will be documented in this file. This p
[#84]: /../../pull/84
[#86]: /../../pull/86
[#94]: /../../pull/94
[#95]: /../../pull/95



Expand Down
26 changes: 14 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions _dev/specs/pub-pub-video-call.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ spec:
credentials: test
on_join: "grpc://127.0.0.1:9099"
on_leave: "grpc://127.0.0.1:9099"
idle_timeout: 1m
reconnect_timeout: 1m
ping_interval: 10s
spec:
pipeline:
# Media element which is able to receive media data from client
Expand All @@ -28,6 +31,9 @@ spec:
credentials: test
on_join: "grpc://127.0.0.1:9099"
on_leave: "grpc://127.0.0.1:9099"
idle_timeout: 1m
reconnect_timeout: 1m
ping_interval: 10s
spec:
pipeline:
publish:
Expand Down
9 changes: 9 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,28 @@
# Duration, after which remote RPC client will be considered idle if no
# heartbeat messages received.
#
# It applies to all related pipelines as default value, but can be overridden
# for each specific case via Control API.
#
# Env var: MEDEA_RPC__IDLE_TIMEOUT
# Default:
# idle_timeout = "10s"

# Duration, after which the server deletes client session if remote RPC client
# does not reconnect after it is idle.
#
# It applies to all related pipelines as default value, but can be overridden
# for each specific case via Control API.
#
# Env var: MEDEA_RPC__RECONNECT_TIMEOUT
# Default:
# reconnect_timeout = "10s"

# Interval between pings that server sends to clients.
#
# It applies to all related pipelines as default value, but can be overridden
# for each specific case via Control API.
#
# Env var: MEDEA_RPC__PING_INTERVAL
# Default:
# ping_interval = "3s"
Expand Down
14 changes: 13 additions & 1 deletion docs/rfc/0001-control-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ spec:
on_join: "grpc://127.0.0.1:9091"
# Fires when "caller" client disconnects from media server via WebSocket.
on_leave: "grpc://127.0.0.1:9091"
# Timeout of receiving heartbeat messages from the member via WebSocket.
# Once reached, the member is considered being idle.
idle_timeout: 1m
# Timeout of the member reconnecting via WebSocket.
# Once reached, the member is considered disconnected.
reconnect_timeout: 3m
# Interval of sending pings from media server to the member via WebSocket.
ping_interval: 10s
pipeline:
# Media element which is able to receive media data from client via WebRTC.
publish:
Expand Down Expand Up @@ -780,7 +788,11 @@ message Room {
message Member {
optional string on_join = 1;
optional string on_leave = 2;
map<string, Member.Element> pipeline = 3;
optional string credentials = 3;
optional uint64 idle_timeout = 4;
optional uint64 reconnect_timeout = 5;
optional uint64 ping_interval = 6;
map<string, Member.Element> pipeline = 7;
message Element {
oneof el {
Expand Down
31 changes: 24 additions & 7 deletions jason/e2e-demo/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,25 @@ const controlDebugWindows = {
let memberId = container.getElementsByClassName('control-debug__id_member')[0].value;
let credentials = container.getElementsByClassName('member-spec__credentials')[0].value;

await controlApi.createMember(roomId, memberId, credentials);
let idleTimeout = container.getElementsByClassName('member-spec__idle-timeout')[0].value;
let reconnectTimeout = container.getElementsByClassName('member-spec__reconnect-timeout')[0].value;
let pingInterval = container.getElementsByClassName('member-spec__ping-interval')[0].value;

let spec = {};
if (credentials.length > 0) {
spec.credentials = credentials;
}
if (idleTimeout.length > 0) {
spec.idle_timeout = idleTimeout;
}
if (reconnectTimeout.length > 0) {
spec.reconnect_timeout = reconnectTimeout;
}
if (pingInterval.length > 0) {
spec.ping_interval = pingInterval;
}

await controlApi.createMember(roomId, memberId, spec);
});
},

Expand Down Expand Up @@ -546,16 +564,15 @@ const controlApi = {
}
},

createMember: async function(roomId, memberId, credentials) {
createMember: async function(roomId, memberId, spec) {
spec.kind = 'Member';
spec.pipeline = {};

try {
await axios({
method: 'post',
url: controlUrl + roomId + '/' + memberId,
data: {
kind: 'Member',
credentials: credentials,
pipeline: {}
}
data: spec
});
} catch (e) {
alert(JSON.stringify(e.response.data));
Expand Down
5 changes: 5 additions & 0 deletions jason/e2e-demo/video-call.html
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@
<input class="control-debug__id_room" placeholder="Room ID">
<input class="control-debug__id_member" placeholder="Member ID">
<input class="member-spec__credentials" placeholder="Credentials">
<br>
<input class="member-spec__idle-timeout" placeholder="IDLE timeout">
<input class="member-spec__reconnect-timeout" placeholder="Reconnect timeout">
<input class="member-spec__ping-interval" placeholder="Ping interval">


<button class="control-debug__execute">Execute</button>
</div>
Expand Down
5 changes: 3 additions & 2 deletions mock/control-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ publish = false

[dependencies]
actix = "0.9"
actix-rt = "1.0"
actix-cors = "0.2"
actix-rt = "1.0"
actix-web = "2.0"
clap = "2.33"
dotenv = "0.15"
tonic = "0.1"
humantime-serde = "1.0"
medea-control-api-proto = { path = "../../proto/control-api" }
protobuf = "2.11"
serde = { version = "1.0", features = ["derive"] }
Expand All @@ -26,3 +26,4 @@ slog-envlogger = "2.2"
slog-scope = "4.3"
slog-stdlog = "4.0"
slog-term = "2.5"
tonic = "0.1"
26 changes: 25 additions & 1 deletion mock/control-api/src/api/member.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! `Member` element related methods and entities.
use std::collections::HashMap;
use std::{collections::HashMap, convert::TryInto as _, time::Duration};

use medea_control_api_proto::grpc::api as proto;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -33,6 +33,20 @@ pub struct Member {
/// URL to which `OnLeave` Control API callback will be sent.
#[serde(skip_serializing_if = "Option::is_none")]
on_leave: Option<String>,

/// Timeout of receiving heartbeat messages from the `Member` via Client
/// API. Once reached, the `Member` is considered being idle.
#[serde(default, with = "humantime_serde")]
idle_timeout: Option<Duration>,

/// Timeout of the `Member` reconnecting via Client API.
/// Once reached, the `Member` is considered disconnected.
#[serde(default, with = "humantime_serde")]
reconnect_timeout: Option<Duration>,

/// Interval of sending pings from Medea to the `Member` via Client API.
#[serde(default, with = "humantime_serde")]
ping_interval: Option<Duration>,
}

impl Member {
Expand All @@ -51,6 +65,9 @@ impl Member {
credentials: self.credentials.unwrap_or_default(),
on_join: self.on_join.unwrap_or_default(),
on_leave: self.on_leave.unwrap_or_default(),
idle_timeout: self.idle_timeout.map(Into::into),
reconnect_timeout: self.reconnect_timeout.map(Into::into),
ping_interval: self.ping_interval.map(Into::into),
}
}

Expand All @@ -77,6 +94,13 @@ impl From<proto::Member> for Member {
credentials: Some(proto.credentials),
on_join: Some(proto.on_join).filter(|s| !s.is_empty()),
on_leave: Some(proto.on_leave).filter(|s| !s.is_empty()),
idle_timeout: proto.idle_timeout.map(|dur| dur.try_into().unwrap()),
reconnect_timeout: proto
.reconnect_timeout
.map(|dur| dur.try_into().unwrap()),
ping_interval: proto
.ping_interval
.map(|dur| dur.try_into().unwrap()),
}
}
}
5 changes: 3 additions & 2 deletions proto/control-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ categories = ["api-bindings", "network-programming"]

[features]
default = ["grpc"]
grpc = ["prost", "tonic-build", "tonic"]
grpc = ["prost", "prost-types", "tonic", "tonic-build"]

[dependencies]
prost = { version = "0.6", optional = true }
prost-types = { version = "0.6", optional = true }
tonic = { version = "0.1", optional = true }

[build-dependencies]
tonic-build = { version = "0.1", optional = true}
tonic-build = { version = "0.1", optional = true }
18 changes: 15 additions & 3 deletions proto/control-api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ mod grpc {
.build_client(true)
.build_server(true)
.compile(&grpc_spec_files, &[GRPC_DIR.to_string()])?;

// Remove empty `google.protobuf.rs` file generated by
// `prost-build`. This file doesn't affect to any
// functionality. It's generated only because of
// `prost-build` bug.
//
// Read instrumentisto/medea#95, hyperium/tonic#314 and
// danburkert/prost#228 for more info.
fs::remove_file(format!("{}/google.protobuf.rs", GRPC_DIR))
.expect(
"`google.protobuf.rs` file isn't generated. This \
is good news, because hyperium/tonic#314 issue \
was probably really fixed. Check it and if so, \
then just remove this line of code.",
);
break;
} else {
panic!("{}", e);
Expand Down Expand Up @@ -97,9 +112,6 @@ mod grpc {
self.0
.iter()
.map(|filename| format!("{}/{}.rs", GRPC_DIR, filename))
.chain(self.0.iter().map(|filename| {
format!("{}/{}_grpc.rs", GRPC_DIR, filename)
}))
.collect()
}
}
Expand Down
12 changes: 11 additions & 1 deletion proto/control-api/src/grpc/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ syntax = "proto3";

package api;

import "google/protobuf/duration.proto";

// Media server's Control API service.
service ControlApi {
// Creates new Element with a given ID.
Expand Down Expand Up @@ -140,8 +142,16 @@ message Member {
string on_leave = 3;
// Credentials of the Member to authorize via Client API with.
string credentials = 4;
// Timeout of receiving heartbeat messages from the Member via Client API.
// Once reached, the Member is considered being idle.
google.protobuf.Duration idle_timeout = 5;
// Timeout of the Member reconnecting via Client API.
// Once reached, the Member is considered disconnected.
google.protobuf.Duration reconnect_timeout = 6;
// Interval of sending pings from a media server to the Member via Client API.
google.protobuf.Duration ping_interval = 7;
// Pipeline of this Member.
map<string, Member.Element> pipeline = 5;
map<string, Member.Element> pipeline = 8;

// Elements which Member's pipeline can contain.
message Element {
Expand Down
Loading

0 comments on commit 43b9242

Please sign in to comment.