feat(runner): Rust updates and improvements (#196)

## Description
- Updates to latest Rust 2024 🎉
- Make DataChannel messages ordered on nestri-server side
- Bugfixes and code improvements + formatting

## Type of Change

- [x] Bug fix (non-breaking change)
- [x] New feature (non-breaking change)

## Checklist

- [x] I have updated relevant documentation
- [x] My code follows the project's coding style
- [x] My changes generate no new warnings/errors

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Wanjohi <elviswanjohi47@gmail.com>
This commit is contained in:
Kristian Ollikainen
2025-03-01 21:57:54 +02:00
committed by GitHub
parent ea96fed4f6
commit b18b08b822
11 changed files with 252 additions and 980 deletions

View File

@@ -7,6 +7,7 @@ on:
paths: paths:
- "containers/runner.Containerfile" - "containers/runner.Containerfile"
- "packages/scripts/**" - "packages/scripts/**"
- "packages/server/**"
- ".github/workflows/runner.yml" - ".github/workflows/runner.yml"
schedule: schedule:
- cron: 7 0 * * 1,3,6 # Regularly to keep that build cache warm - cron: 7 0 * * 1,3,6 # Regularly to keep that build cache warm
@@ -16,6 +17,7 @@ on:
- "containers/runner.Containerfile" - "containers/runner.Containerfile"
- ".github/workflows/runner.yml" - ".github/workflows/runner.yml"
- "packages/scripts/**" - "packages/scripts/**"
- "packages/server/**"
tags: tags:
- v*.*.* - v*.*.*
release: release:

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "nestri-server" name = "nestri-server"
version = "0.1.0-alpha.2" version = "0.1.0-alpha.2"
edition = "2021" edition = "2024"
[[bin]] [[bin]]
name = "nestri-server" name = "nestri-server"

View File

@@ -1,24 +1,24 @@
use std::ops::Deref; use std::ops::Deref;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct RateControlCQP { pub struct RateControlCQP {
/// Constant Quantization Parameter (CQP) quality level /// Constant Quantization Parameter (CQP) quality level
pub quality: u32, pub quality: u32,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct RateControlVBR { pub struct RateControlVBR {
/// Target bitrate in kbps /// Target bitrate in kbps
pub target_bitrate: i32, pub target_bitrate: i32,
/// Maximum bitrate in kbps /// Maximum bitrate in kbps
pub max_bitrate: i32, pub max_bitrate: i32,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct RateControlCBR { pub struct RateControlCBR {
/// Target bitrate in kbps /// Target bitrate in kbps
pub target_bitrate: i32, pub target_bitrate: i32,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum RateControl { pub enum RateControl {
/// Constant Quantization Parameter /// Constant Quantization Parameter
CQP(RateControlCQP), CQP(RateControlCQP),

View File

@@ -1,4 +1,5 @@
use crate::gpu::{self, get_gpu_by_card_path, get_gpus_by_vendor, GPUInfo}; use crate::args::encoding_args::RateControl;
use crate::gpu::{self, GPUInfo, get_gpu_by_card_path, get_gpus_by_vendor};
use gst::prelude::*; use gst::prelude::*;
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
@@ -245,7 +246,10 @@ pub fn encoder_gop_params(encoder: &VideoEncoderInfo, gop_size: u32) -> VideoEnc
}) })
} }
pub fn encoder_low_latency_params(encoder: &VideoEncoderInfo) -> VideoEncoderInfo { pub fn encoder_low_latency_params(
encoder: &VideoEncoderInfo,
rate_control: &RateControl,
) -> VideoEncoderInfo {
let mut encoder_optz = encoder_gop_params(encoder, 30); let mut encoder_optz = encoder_gop_params(encoder, 30);
match encoder_optz.encoder_api { match encoder_optz.encoder_api {
@@ -283,13 +287,8 @@ pub fn encoder_low_latency_params(encoder: &VideoEncoderInfo) -> VideoEncoderInf
encoder_optz.set_parameter("tune", "zerolatency"); encoder_optz.set_parameter("tune", "zerolatency");
} }
"svtav1enc" => { "svtav1enc" => {
encoder_optz.set_parameter("preset", "12"); encoder_optz.set_parameter("preset", "11");
let suffix = if encoder_optz.get_parameters_string().contains("cbr") { encoder_optz.set_parameter("parameters-string", "lookahead=0");
":pred-struct=1"
} else {
""
};
encoder_optz.set_parameter("parameters-string", &format!("lookahead=0{}", suffix));
} }
"av1enc" => { "av1enc" => {
encoder_optz.set_parameter("usage-profile", "realtime"); encoder_optz.set_parameter("usage-profile", "realtime");

View File

@@ -4,13 +4,13 @@ mod gpu;
mod latency; mod latency;
mod messages; mod messages;
mod nestrisink; mod nestrisink;
mod websocket;
mod proto; mod proto;
mod websocket;
use crate::args::encoding_args; use crate::args::encoding_args;
use crate::gpu::GPUVendor;
use crate::nestrisink::NestriSignaller; use crate::nestrisink::NestriSignaller;
use crate::websocket::NestriWebSocket; use crate::websocket::NestriWebSocket;
use crate::gpu::GPUVendor;
use futures_util::StreamExt; use futures_util::StreamExt;
use gst::prelude::*; use gst::prelude::*;
use gstrswebrtc::signaller::Signallable; use gstrswebrtc::signaller::Signallable;
@@ -55,12 +55,19 @@ fn handle_gpus(args: &args::Args) -> Option<gpu::GPUInfo> {
gpu = filtered_gpus.get(args.device.gpu_index as usize).cloned(); gpu = filtered_gpus.get(args.device.gpu_index as usize).cloned();
} else { } else {
// get first GPU // get first GPU
gpu = filtered_gpus.into_iter().find(|g| *g.vendor() != GPUVendor::UNKNOWN); gpu = filtered_gpus
.into_iter()
.find(|g| *g.vendor() != GPUVendor::UNKNOWN);
} }
} }
if gpu.is_none() { if gpu.is_none() {
println!("No GPU found with the specified parameters: vendor='{}', name='{}', index='{}', card_path='{}'", println!(
args.device.gpu_vendor, args.device.gpu_name, args.device.gpu_index, args.device.gpu_card_path); "No GPU found with the specified parameters: vendor='{}', name='{}', index='{}', card_path='{}'",
args.device.gpu_vendor,
args.device.gpu_name,
args.device.gpu_index,
args.device.gpu_card_path
);
return None; return None;
} }
let gpu = gpu.unwrap(); let gpu = gpu.unwrap();
@@ -83,7 +90,11 @@ fn handle_encoder_video(args: &args::Args) -> Option<enc_helper::VideoEncoderInf
encoder.codec.to_str(), encoder.codec.to_str(),
encoder.encoder_api.to_str(), encoder.encoder_api.to_str(),
encoder.encoder_type.to_str(), encoder.encoder_type.to_str(),
if let Some(gpu) = &encoder.gpu_info { gpu.device_name() } else { "CPU" }, if let Some(gpu) = &encoder.gpu_info {
gpu.device_name()
} else {
"CPU"
},
); );
} }
// Pick most suitable video encoder based on given arguments // Pick most suitable video encoder based on given arguments
@@ -99,8 +110,12 @@ fn handle_encoder_video(args: &args::Args) -> Option<enc_helper::VideoEncoderInf
); );
} }
if video_encoder.is_none() { if video_encoder.is_none() {
println!("No video encoder found with the specified parameters: name='{}', vcodec='{}', type='{}'", println!(
args.encoding.video.encoder, args.encoding.video.codec, args.encoding.video.encoder_type); "No video encoder found with the specified parameters: name='{}', vcodec='{}', type='{}'",
args.encoding.video.encoder,
args.encoding.video.codec,
args.encoding.video.encoder_type
);
return None; return None;
} }
let video_encoder = video_encoder.unwrap(); let video_encoder = video_encoder.unwrap();
@@ -113,7 +128,8 @@ fn handle_encoder_video_settings(
args: &args::Args, args: &args::Args,
video_encoder: &enc_helper::VideoEncoderInfo, video_encoder: &enc_helper::VideoEncoderInfo,
) -> enc_helper::VideoEncoderInfo { ) -> enc_helper::VideoEncoderInfo {
let mut optimized_encoder = enc_helper::encoder_low_latency_params(&video_encoder); let mut optimized_encoder =
enc_helper::encoder_low_latency_params(&video_encoder, &args.encoding.video.rate_control);
// Handle rate-control method // Handle rate-control method
match &args.encoding.video.rate_control { match &args.encoding.video.rate_control {
encoding_args::RateControl::CQP(cqp) => { encoding_args::RateControl::CQP(cqp) => {
@@ -240,14 +256,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
&match &args.encoding.audio.rate_control { &match &args.encoding.audio.rate_control {
encoding_args::RateControl::CBR(cbr) => cbr.target_bitrate * 1000i32, encoding_args::RateControl::CBR(cbr) => cbr.target_bitrate * 1000i32,
encoding_args::RateControl::VBR(vbr) => vbr.target_bitrate * 1000i32, encoding_args::RateControl::VBR(vbr) => vbr.target_bitrate * 1000i32,
_ => 128i32, _ => 128000i32,
}, },
); );
/* Video */ /* Video */
// Video Source Element // Video Source Element
let video_source = gst::ElementFactory::make("waylanddisplaysrc").build()?; let video_source = gst::ElementFactory::make("waylanddisplaysrc").build()?;
video_source.set_property("render-node", &gpu.render_path()); video_source.set_property_from_str("render-node", gpu.render_path());
// Caps Filter Element (resolution, fps) // Caps Filter Element (resolution, fps)
let caps_filter = gst::ElementFactory::make("capsfilter").build()?; let caps_filter = gst::ElementFactory::make("capsfilter").build()?;
@@ -289,6 +305,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let webrtcsink = BaseWebRTCSink::with_signaller(Signallable::from(signaller.clone())); let webrtcsink = BaseWebRTCSink::with_signaller(Signallable::from(signaller.clone()));
webrtcsink.set_property_from_str("stun-server", "stun://stun.l.google.com:19302"); webrtcsink.set_property_from_str("stun-server", "stun://stun.l.google.com:19302");
webrtcsink.set_property_from_str("congestion-control", "disabled"); webrtcsink.set_property_from_str("congestion-control", "disabled");
webrtcsink.set_property("do-retransmission", false);
// Add elements to the pipeline // Add elements to the pipeline
pipeline.add_many(&[ pipeline.add_many(&[
@@ -343,7 +360,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
} }
// Optimize latency of pipeline // Optimize latency of pipeline
video_source.sync_state_with_parent().expect("failed to sync with parent"); video_source
.sync_state_with_parent()
.expect("failed to sync with parent");
video_source.set_property("do-timestamp", &true); video_source.set_property("do-timestamp", &true);
audio_source.set_property("do-timestamp", &true); audio_source.set_property("do-timestamp", &true);
pipeline.set_property("latency", &0u64); pipeline.set_property("latency", &0u64);

View File

@@ -1,6 +1,6 @@
use crate::messages::{ use crate::messages::{
decode_message_as, encode_message, AnswerType, JoinerType, MessageAnswer, MessageBase, AnswerType, JoinerType, MessageAnswer, MessageBase, MessageICE, MessageJoin, MessageSDP,
MessageICE, MessageJoin, MessageSDP, decode_message_as, encode_message,
}; };
use crate::proto::proto::proto_input::InputType::{ use crate::proto::proto::proto_input::InputType::{
KeyDown, KeyUp, MouseKeyDown, MouseKeyUp, MouseMove, MouseMoveAbs, MouseWheel, KeyDown, KeyUp, MouseKeyDown, MouseKeyUp, MouseMove, MouseMoveAbs, MouseWheel,
@@ -10,7 +10,7 @@ use crate::websocket::NestriWebSocket;
use glib::subclass::prelude::*; use glib::subclass::prelude::*;
use gst::glib; use gst::glib;
use gst::prelude::*; use gst::prelude::*;
use gst_webrtc::{gst_sdp, WebRTCSDPType, WebRTCSessionDescription}; use gst_webrtc::{WebRTCSDPType, WebRTCSessionDescription, gst_sdp};
use gstrswebrtc::signaller::{Signallable, SignallableImpl}; use gstrswebrtc::signaller::{Signallable, SignallableImpl};
use prost::Message; use prost::Message;
use std::collections::HashSet; use std::collections::HashSet;
@@ -144,8 +144,9 @@ impl Signaller {
&[ &[
&"nestri-data-channel", &"nestri-data-channel",
&gst::Structure::builder("config") &gst::Structure::builder("config")
.field("ordered", &false) .field("ordered", &true)
.field("max-retransmits", &0u32) .field("max-retransmits", &0u32)
.field("priority", "high")
.build(), .build(),
], ],
), ),
@@ -337,12 +338,14 @@ impl ObjectSubclass for Signaller {
impl ObjectImpl for Signaller { impl ObjectImpl for Signaller {
fn properties() -> &'static [glib::ParamSpec] { fn properties() -> &'static [glib::ParamSpec] {
static PROPS: LazyLock<Vec<glib::ParamSpec>> = LazyLock::new(|| { static PROPS: LazyLock<Vec<glib::ParamSpec>> = LazyLock::new(|| {
vec![glib::ParamSpecBoolean::builder("manual-sdp-munging") vec![
.nick("Manual SDP munging") glib::ParamSpecBoolean::builder("manual-sdp-munging")
.blurb("Whether the signaller manages SDP munging itself") .nick("Manual SDP munging")
.default_value(false) .blurb("Whether the signaller manages SDP munging itself")
.read_only() .default_value(false)
.build()] .read_only()
.build(),
]
}); });
PROPS.as_ref() PROPS.as_ref()

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use crate::websocket::NestriWebSocket;
use gst::glib; use gst::glib;
use gst::subclass::prelude::*; use gst::subclass::prelude::*;
use gstrswebrtc::signaller::Signallable; use gstrswebrtc::signaller::Signallable;
use crate::websocket::NestriWebSocket; use std::sync::Arc;
mod imp; mod imp;

View File

@@ -3,17 +3,17 @@
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoTimestampEntry { pub struct ProtoTimestampEntry {
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub stage: ::prost::alloc::string::String, pub stage: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")] #[prost(message, optional, tag = "2")]
pub time: ::core::option::Option<::prost_types::Timestamp>, pub time: ::core::option::Option<::prost_types::Timestamp>,
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoLatencyTracker { pub struct ProtoLatencyTracker {
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub sequence_id: ::prost::alloc::string::String, pub sequence_id: ::prost::alloc::string::String,
#[prost(message, repeated, tag="2")] #[prost(message, repeated, tag = "2")]
pub timestamps: ::prost::alloc::vec::Vec<ProtoTimestampEntry>, pub timestamps: ::prost::alloc::vec::Vec<ProtoTimestampEntry>,
} }
/// MouseMove message /// MouseMove message
@@ -21,11 +21,11 @@ pub struct ProtoLatencyTracker {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMouseMove { pub struct ProtoMouseMove {
/// Fixed value "MouseMove" /// Fixed value "MouseMove"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub x: i32, pub x: i32,
#[prost(int32, tag="3")] #[prost(int32, tag = "3")]
pub y: i32, pub y: i32,
} }
/// MouseMoveAbs message /// MouseMoveAbs message
@@ -33,11 +33,11 @@ pub struct ProtoMouseMove {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMouseMoveAbs { pub struct ProtoMouseMoveAbs {
/// Fixed value "MouseMoveAbs" /// Fixed value "MouseMoveAbs"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub x: i32, pub x: i32,
#[prost(int32, tag="3")] #[prost(int32, tag = "3")]
pub y: i32, pub y: i32,
} }
/// MouseWheel message /// MouseWheel message
@@ -45,11 +45,11 @@ pub struct ProtoMouseMoveAbs {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMouseWheel { pub struct ProtoMouseWheel {
/// Fixed value "MouseWheel" /// Fixed value "MouseWheel"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub x: i32, pub x: i32,
#[prost(int32, tag="3")] #[prost(int32, tag = "3")]
pub y: i32, pub y: i32,
} }
/// MouseKeyDown message /// MouseKeyDown message
@@ -57,9 +57,9 @@ pub struct ProtoMouseWheel {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMouseKeyDown { pub struct ProtoMouseKeyDown {
/// Fixed value "MouseKeyDown" /// Fixed value "MouseKeyDown"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub key: i32, pub key: i32,
} }
/// MouseKeyUp message /// MouseKeyUp message
@@ -67,9 +67,9 @@ pub struct ProtoMouseKeyDown {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMouseKeyUp { pub struct ProtoMouseKeyUp {
/// Fixed value "MouseKeyUp" /// Fixed value "MouseKeyUp"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub key: i32, pub key: i32,
} }
/// KeyDown message /// KeyDown message
@@ -77,9 +77,9 @@ pub struct ProtoMouseKeyUp {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoKeyDown { pub struct ProtoKeyDown {
/// Fixed value "KeyDown" /// Fixed value "KeyDown"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub key: i32, pub key: i32,
} }
/// KeyUp message /// KeyUp message
@@ -87,53 +87,53 @@ pub struct ProtoKeyDown {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoKeyUp { pub struct ProtoKeyUp {
/// Fixed value "KeyUp" /// Fixed value "KeyUp"
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub r#type: ::prost::alloc::string::String, pub r#type: ::prost::alloc::string::String,
#[prost(int32, tag="2")] #[prost(int32, tag = "2")]
pub key: i32, pub key: i32,
} }
/// Union of all Input types /// Union of all Input types
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoInput { pub struct ProtoInput {
#[prost(oneof="proto_input::InputType", tags="1, 2, 3, 4, 5, 6, 7")] #[prost(oneof = "proto_input::InputType", tags = "1, 2, 3, 4, 5, 6, 7")]
pub input_type: ::core::option::Option<proto_input::InputType>, pub input_type: ::core::option::Option<proto_input::InputType>,
} }
/// Nested message and enum types in `ProtoInput`. /// Nested message and enum types in `ProtoInput`.
pub mod proto_input { pub mod proto_input {
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Oneof)] #[derive(Clone, PartialEq, ::prost::Oneof)]
pub enum InputType { pub enum InputType {
#[prost(message, tag="1")] #[prost(message, tag = "1")]
MouseMove(super::ProtoMouseMove), MouseMove(super::ProtoMouseMove),
#[prost(message, tag="2")] #[prost(message, tag = "2")]
MouseMoveAbs(super::ProtoMouseMoveAbs), MouseMoveAbs(super::ProtoMouseMoveAbs),
#[prost(message, tag="3")] #[prost(message, tag = "3")]
MouseWheel(super::ProtoMouseWheel), MouseWheel(super::ProtoMouseWheel),
#[prost(message, tag="4")] #[prost(message, tag = "4")]
MouseKeyDown(super::ProtoMouseKeyDown), MouseKeyDown(super::ProtoMouseKeyDown),
#[prost(message, tag="5")] #[prost(message, tag = "5")]
MouseKeyUp(super::ProtoMouseKeyUp), MouseKeyUp(super::ProtoMouseKeyUp),
#[prost(message, tag="6")] #[prost(message, tag = "6")]
KeyDown(super::ProtoKeyDown), KeyDown(super::ProtoKeyDown),
#[prost(message, tag="7")] #[prost(message, tag = "7")]
KeyUp(super::ProtoKeyUp), KeyUp(super::ProtoKeyUp),
} }
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMessageBase { pub struct ProtoMessageBase {
#[prost(string, tag="1")] #[prost(string, tag = "1")]
pub payload_type: ::prost::alloc::string::String, pub payload_type: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")] #[prost(message, optional, tag = "2")]
pub latency: ::core::option::Option<ProtoLatencyTracker>, pub latency: ::core::option::Option<ProtoLatencyTracker>,
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoMessageInput { pub struct ProtoMessageInput {
#[prost(message, optional, tag="1")] #[prost(message, optional, tag = "1")]
pub message_base: ::core::option::Option<ProtoMessageBase>, pub message_base: ::core::option::Option<ProtoMessageBase>,
#[prost(message, optional, tag="2")] #[prost(message, optional, tag = "2")]
pub data: ::core::option::Option<ProtoInput>, pub data: ::core::option::Option<ProtoInput>,
} }
// @@protoc_insertion_point(module) // @@protoc_insertion_point(module)

View File

@@ -1,17 +1,17 @@
use crate::messages::{decode_message, encode_message, MessageBase, MessageLog}; use crate::messages::{MessageBase, MessageLog, decode_message, encode_message};
use futures_util::StreamExt;
use futures_util::sink::SinkExt; use futures_util::sink::SinkExt;
use futures_util::stream::{SplitSink, SplitStream}; use futures_util::stream::{SplitSink, SplitStream};
use futures_util::StreamExt;
use log::{Level, Log, Metadata, Record}; use log::{Level, Log, Metadata, Record};
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::time::Duration; use std::time::Duration;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::{mpsc, Mutex, Notify}; use tokio::sync::{Mutex, Notify, mpsc};
use tokio::time::sleep; use tokio::time::sleep;
use tokio_tungstenite::tungstenite::{Message, Utf8Bytes}; use tokio_tungstenite::tungstenite::{Message, Utf8Bytes};
use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream}; use tokio_tungstenite::{MaybeTlsStream, WebSocketStream, connect_async};
type Callback = Box<dyn Fn(String) + Send + Sync>; type Callback = Box<dyn Fn(String) + Send + Sync>;
type WSRead = SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>; type WSRead = SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>;
@@ -95,7 +95,9 @@ impl NestriWebSocket {
while let Some(message_result) = ws_read.next().await { while let Some(message_result) = ws_read.next().await {
match message_result { match message_result {
Ok(message) => { Ok(message) => {
let data = message.into_text().expect("failed to turn message into text"); let data = message
.into_text()
.expect("failed to turn message into text");
let base_message = match decode_message(data.to_string()) { let base_message = match decode_message(data.to_string()) {
Ok(base_message) => base_message, Ok(base_message) => base_message,
Err(e) => { Err(e) => {