Skip to content

Commit

Permalink
fix(signalling): simplify signalling server, webrtc, update ts bindin…
Browse files Browse the repository at this point in the history
…gs (#938)

Description
---

Remove extraneous serializations to and from json in signalling server
and webrtc
Improve signalling server errors
Add response logger to indexer for debugging

Motivation and Context
---
Updates to tari.js : tari-project/tari.js#1
Ref: tari-project/tari-template-web#1

How Has This Been Tested?
---
Using signalling server to connect and submit transactions from web to
walletd

What process can a PR reviewer use to test or verify this change?
---
Use template web to connect to your walletd via signalling

Breaking Changes
---

- [x] None
- [ ] Requires data directory to be deleted
- [ ] Other - Please specify
  • Loading branch information
sdbondi authored Feb 19, 2024
1 parent f4df35e commit 3cfbf6e
Show file tree
Hide file tree
Showing 112 changed files with 702 additions and 576 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ ts-rs = { version = "7.1", features = [
"indexmap-impl",
] }
url = "2.4.1"
urlencoding = "2.1.3"
wasmer = "2.3.0"
wasmer-middlewares = "2.3.0"
webrtc = "0.9.0"
Expand Down
1 change: 1 addition & 0 deletions applications/tari_dan_wallet_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ time = { workspace = true }
thiserror = { workspace = true }
tokio = { version = "1", features = ["macros"] }
url = { workspace = true }
urlencoding = { workspace = true }
29 changes: 22 additions & 7 deletions applications/tari_dan_wallet_cli/src/command/webrtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
// 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.

use anyhow::anyhow;
use clap::{Args, Subcommand};
use tari_wallet_daemon_client::{types::WebRtcStartRequest, WalletDaemonClient};
use url::Url;

#[derive(Debug, Subcommand, Clone)]
pub enum WebRtcSubcommand {
Expand All @@ -31,22 +33,35 @@ pub enum WebRtcSubcommand {

#[derive(Debug, Args, Clone)]
pub struct StartArgs {
pub signaling_server_token: String,
pub webrtc_permissions_token: String,
pub token_name: String,
#[clap(long, alias = "url")]
pub signaling_server_url: Option<Url>,
pub signaling_server_token: Option<String>,
pub webrtc_permissions_token: Option<serde_json::Value>,
pub token_name: Option<String>,
}

impl WebRtcSubcommand {
pub async fn handle(self, mut client: WalletDaemonClient) -> anyhow::Result<()> {
#[allow(clippy::enum_glob_use)]
use WebRtcSubcommand::*;
match self {
Start(args) => {
Start(mut args) => {
if let Some(url) = args.signaling_server_url {
let mut parts = url.path_segments().ok_or_else(|| anyhow!("Malformed Tari URL"))?;
args.signaling_server_token =
Some(parts.next().ok_or_else(|| anyhow!("Malformed Tari URL"))?.to_string());

let token = parts.next().ok_or_else(|| anyhow!("Malformed Tari URL"))?;
let token = urlencoding::decode(token)?;
args.webrtc_permissions_token = Some(serde_json::from_str(token.as_ref())?);
args.token_name = Some(parts.next().ok_or_else(|| anyhow!("Malformed Tari URL"))?.to_string());
}

let _resp = client
.webrtc_start(WebRtcStartRequest {
signaling_server_token: args.signaling_server_token,
permissions: args.webrtc_permissions_token,
name: args.token_name,
signaling_server_token: args.signaling_server_token.unwrap(),
permissions: args.webrtc_permissions_token.unwrap(),
name: args.token_name.unwrap(),
})
.await?;
},
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_dan_wallet_daemon/src/handlers/webrtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ pub fn handle_start(
})?;
let webrtc_start_request = value.parse_params::<WebRtcStartRequest>()?;
let shutdown_signal = (*shutdown_signal).clone();
let permissions = serde_json::from_str::<JrpcPermissions>(&webrtc_start_request.permissions).map_err(|e| {
let permissions = serde_json::from_value::<JrpcPermissions>(webrtc_start_request.permissions).map_err(|e| {
JsonRpcResponse::error(
answer_id,
JsonRpcError::new(
JsonRpcErrorReason::InternalError,
JsonRpcErrorReason::InvalidRequest,
e.to_string(),
serde_json::Value::Null,
),
Expand Down
125 changes: 55 additions & 70 deletions applications/tari_dan_wallet_daemon/src/webrtc.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::{net::SocketAddr, pin::Pin, sync::Arc};
use std::{net::SocketAddr, sync::Arc};

use anyhow::Result;
use axum_jrpc::{JsonRpcAnswer, JsonRpcRequest, JsonRpcResponse};
use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};
use serde::{Deserialize, Serialize};
use serde_json as json;
use serde_json::json;
use tari_shutdown::ShutdownSignal;
use webrtc::{
Expand All @@ -25,14 +26,14 @@ const LOG_TARGET: &str = "tari::dan::wallet_daemon::webrtc";
struct Request {
id: u64,
method: String,
params: String,
params: json::Value,
token: String,
}

#[derive(Serialize, Debug)]
struct Response {
id: u64,
payload: String,
payload: json::Value,
}

async fn make_request<T: Serialize>(
Expand Down Expand Up @@ -70,14 +71,14 @@ fn get_rtc_configuration() -> RTCConfiguration {
}
}

pub fn on_ice_candidate(
pub async fn on_ice_candidate(
ice_candidate: Option<RTCIceCandidate>,
signaling_server_token_clone: String,
signaling_server_address: SocketAddr,
) -> Pin<Box<impl futures::Future<Output = ()>>> {
) {
if let Some(ice_candidate) = ice_candidate {
tokio::task::spawn(async move {
match &ice_candidate.to_json() {
match ice_candidate.to_json() {
Ok(ice_candidate) => {
if let Err(err) = make_request(
signaling_server_address,
Expand All @@ -96,74 +97,61 @@ pub fn on_ice_candidate(
};
});
}
Box::pin(async {})
}

pub fn on_message(
pub async fn on_message(
msg: DataChannelMessage,
d_on_message: Arc<RTCDataChannel>,
permissions_token: String,
address: SocketAddr,
) -> Pin<Box<impl futures::Future<Output = ()>>> {
Box::pin(async move {
match String::from_utf8(msg.data.to_vec()) {
Ok(msg_str) => match serde_json::from_str::<Request>(&msg_str) {
Ok(request) => {
let response;
if request.method == "get.token" {
match serde_json::to_string(&permissions_token) {
Ok(token) => {
response = Response {
payload: token,
id: request.id,
}
},
Err(e) => {
log::error!(target: LOG_TARGET, "{}", e.to_string());
return;
},
}
} else {
let result = match serde_json::from_str::<serde_json::Value>(&request.params) {
Ok(params) => {
match make_request(address, Some(request.token), request.method, params).await {
Ok(response) => response.to_string(),
Err(e) => e.to_string(),
}
},
Err(e) => e.to_string(),
};
response = Response {
payload: result,
id: request.id,
};
) {
match String::from_utf8(msg.data.to_vec()) {
Ok(msg_str) => match serde_json::from_str::<Request>(&msg_str) {
Ok(request) => {
let response;
if request.method == "get.token" {
match json::to_value(permissions_token) {
Ok(token) => {
response = Response {
payload: token,
id: request.id,
}
},
Err(e) => {
log::error!(target: LOG_TARGET, "{}", e.to_string());
return;
},
}
let text = match serde_json::to_string(&response) {
Ok(response) => response,
Err(e) => e.to_string(),
} else {
let result = make_request(address, Some(request.token), request.method, request.params)
.await
.unwrap_or_else(|e| json!({"error": e.to_string()}));
response = Response {
payload: result,
id: request.id,
};
if let Err(e) = d_on_message.send_text(text).await {
log::error!(target: LOG_TARGET, "{}", e.to_string())
};
},
Err(e) => log::error!(target: LOG_TARGET, "{}", e.to_string()),
}
let text = serde_json::to_string(&response).unwrap_or_else(|e| e.to_string());
if let Err(e) = d_on_message.send_text(text).await {
log::error!(target: LOG_TARGET, "{}", e.to_string())
};
},
Err(e) => log::error!(target: LOG_TARGET, "{}", e.to_string()),
};
})
Err(e) => log::error!(target: LOG_TARGET, "Error parsing request: {}", e.to_string()),
},
Err(e) => log::error!(target: LOG_TARGET, "Message is not valid UTF-8: {}", e.to_string()),
};
}

pub fn on_data_channel(
d: Arc<RTCDataChannel>,
permissions_token: String,
address: SocketAddr,
) -> Pin<Box<impl futures::Future<Output = ()>>> {
Box::pin(async move {
let d_on_message = d.clone();
d.on_message(Box::new(move |msg: DataChannelMessage| {
on_message(msg, d_on_message.clone(), permissions_token.clone(), address)
}))
})
pub async fn on_data_channel(d: Arc<RTCDataChannel>, permissions_token: String, address: SocketAddr) {
let d_on_message = d.clone();
d.on_message(Box::new(move |msg: DataChannelMessage| {
Box::pin(on_message(
msg,
d_on_message.clone(),
permissions_token.clone(),
address,
))
}))
}

pub async fn webrtc_start_session(
Expand All @@ -177,16 +165,16 @@ pub async fn webrtc_start_session(

let pc = api.new_peer_connection(get_rtc_configuration()).await?;
pc.on_data_channel(Box::new(move |d: Arc<RTCDataChannel>| {
on_data_channel(d, permissions_token.clone(), address)
Box::pin(on_data_channel(d, permissions_token.clone(), address))
}));

let signaling_server_token_clone = signaling_server_token.clone();
pc.on_ice_candidate(Box::new(move |ice_candidate: Option<RTCIceCandidate>| {
on_ice_candidate(
Box::pin(on_ice_candidate(
ice_candidate,
signaling_server_token_clone.clone(),
signaling_server_address,
)
))
}));

let offer = make_request(
Expand All @@ -213,10 +201,7 @@ pub async fn webrtc_start_session(
)
.await?;

let ices: Vec<RTCIceCandidateInit> = serde_json::from_str(
ices.as_str()
.ok_or_else(|| anyhow::anyhow!("RTC Ice candidate error"))?,
)?;
let ices: Vec<RTCIceCandidateInit> = serde_json::from_value(ices)?;
for ice_candidate in ices {
println!("ice_candidate {:?}", ice_candidate);
// let ice_candidate: RTCIceCandidateInit = serde_json::from_str(ice_candidate.as_str())?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ const ConnectorDialog = () => {
};

const handleAuth = () => {
let allowedPermissions = [
const allowedPermissions = [
...permissions,
...optionalPermissions.filter((value, index) => chosenOptionalPermissions[index]),
];
webrtcStart({
signaling_server_token: signalingServerJWT,
permissions: JSON.stringify(allowedPermissions),
permissions: allowedPermissions,
name: name,
}).then((resp) => {
setPage(page + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ export default function Permissions({
<FormControl component="fieldset" variant="standard" style={{ width: "100%" }}>
<Divider />
<FormGroup>
{requiredPermissions.map((permissions) => {
{requiredPermissions.map((permission) => {
return (
<>
<FormControlLabel
control={<Switch checked={true} disabled={true} />}
label={permissions.toString()}
label={permission?.toString()}
labelPlacement="start"
key={permissions.toString()}
key={permission?.toString()}
className="permissions-switch"
/>
<Divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,5 +419,5 @@ export function parse(permission: any) {
} else if (permission.hasOwnProperty("NftGetOwnershipProof")) {
return new TariPermissionNftGetOwnershipProof(permission.NftGetOwnershipProof);
}
return null;
return permission;
}
Loading

0 comments on commit 3cfbf6e

Please sign in to comment.