update to edition 2024
This commit is contained in:
parent
0daa7b0e3f
commit
6d81aa3a17
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "navka-client"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.45", features = ["full"] }
|
||||
|
||||
@ -1,37 +1,47 @@
|
||||
//! navka-client – forward keyboard/mouse HID reports to navka-server
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use anyhow::Result;
|
||||
use navka_common::navka::HidReport;
|
||||
use navka_common::navka::relay_client::RelayClient;
|
||||
use tokio::sync::mpsc;
|
||||
use navka_common::navka::{hid_report::*, relay_client::RelayClient, HidReport};
|
||||
use tokio::{sync::mpsc, time::sleep};
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
use tonic::{Request, transport::Channel};
|
||||
use tonic::{transport::Channel, Request};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// 1) connect to the navka-server gRPC endpoint
|
||||
let channel = Channel::from_static("http://127.0.0.1:50051").connect().await?;
|
||||
let mut client = RelayClient::new(channel);
|
||||
// Connect to navka-server (adjust the address if server not local)
|
||||
let channel = Channel::from_static("http://127.0.0.1:50051")
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
// 2) create an mpsc channel that we can push HID reports into
|
||||
let (tx_request, rx_request) = mpsc::channel::<HidReport>(32);
|
||||
let outbound = ReceiverStream::new(rx_request);
|
||||
// mpsc channel -> ReceiverStream -> gRPC bidirectional stream
|
||||
let (tx, rx) = mpsc::channel::<HidReport>(32);
|
||||
let outbound = ReceiverStream::new(rx);
|
||||
|
||||
// 3) start the bi-directional stream (note the REQUIRED argument)
|
||||
let response = client.stream(Request::new(outbound)).await?;
|
||||
let mut inbound = response.into_inner(); // Streaming<HidReport>
|
||||
// Kick off the RPC – note: in tonic 0.11 the request object is built
|
||||
// by wrapping the outbound stream in `Request::new(...)`.
|
||||
let mut inbound = RelayClient::new(channel)
|
||||
.stream(Request::new(outbound))
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
// 4) demo: send “press A”, wait 100 ms, send “release”
|
||||
// Example task: press and release the 'a' key once.
|
||||
tokio::spawn(async move {
|
||||
let press_a = HidReport { data: vec![0x00,0x00,0x04,0,0,0,0,0] };
|
||||
let release = HidReport { data: vec![0x00; 8] };
|
||||
// 8-byte boot-keyboard report: [mods, reserved, key1..6]
|
||||
let press_a = HidReport {
|
||||
data: vec![0x00, 0x00, 0x04, 0, 0, 0, 0, 0],
|
||||
};
|
||||
let release = HidReport { data: vec![0; 8] };
|
||||
|
||||
tx_request.send(press_a).await.ok();
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
tx_request.send(release).await.ok();
|
||||
tx.send(press_a).await.ok();
|
||||
sleep(std::time::Duration::from_millis(100)).await;
|
||||
tx.send(release).await.ok();
|
||||
});
|
||||
|
||||
// 5) print anything the server echoes back
|
||||
while let Some(msg) = inbound.message().await? {
|
||||
println!("🔄 got report from server: {:?}", msg.data);
|
||||
// Print whatever the server echoes back.
|
||||
while let Some(report) = inbound.message().await? {
|
||||
println!("🔄 received: {:?}", report.data);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -2,10 +2,20 @@
|
||||
set -euo pipefail
|
||||
|
||||
# 1) Install system dependencies (Arch Linux)
|
||||
sudo pacman -S --needed --noconfirm git rustup protobuf gcc ustreamer pulseaudio tailscale
|
||||
sudo pacman -S --needed --noconfirm git rustup protobuf gcc pulseaudio tailscale snapd
|
||||
# Enable and start snapd if not already:
|
||||
sudo systemctl enable --now snapd.socket
|
||||
# Create classic symlink for snap (one-time):
|
||||
sudo ln -sf /var/lib/snapd/snap /snap
|
||||
# Install µStreamer via Snap (if you actually need streaming)
|
||||
if ! snap list | grep -q ustreamer; then
|
||||
sudo snap install ustreamer
|
||||
fi
|
||||
|
||||
# 2) Ensure Rust toolchain is present
|
||||
rustup toolchain install stable
|
||||
sudo install -Dm755 target/release/navka-server /usr/local/bin/navka-server
|
||||
sudo install -Dm755 gadget/navka-gadget.sh /usr/local/bin/navka-gadget.sh
|
||||
|
||||
# 3) Determine repo URL from the current directory
|
||||
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
@ -4,6 +4,8 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
||||
navka-common = { path = "../common" }
|
||||
tokio-stream = "0.1"
|
||||
tokio = { version = "1.45", features = ["full", "fs"] } # add "fs"
|
||||
tokio-stream = "0.1"
|
||||
tonic = { version = "0.11", features = ["transport"] }
|
||||
anyhow = "1.0"
|
||||
navka-common = { path = "../common" }
|
||||
|
||||
@ -1,43 +1,73 @@
|
||||
use navka_common::navka::{relay_server::{Relay, RelayServer}, HidReport};
|
||||
use tokio::{fs::OpenOptions, io::AsyncWriteExt, sync::mpsc};
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
//! navka-server – bridge HID reports between client (gRPC) and /dev/hidg0
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use anyhow::Result;
|
||||
use navka_common::navka::{
|
||||
hid_report::*, relay_server::Relay, HidReport, RelayServer,
|
||||
};
|
||||
use std::{path::Path, sync::Arc};
|
||||
use tokio::{
|
||||
fs::OpenOptions,
|
||||
io::AsyncWriteExt,
|
||||
signal,
|
||||
sync::{mpsc, Mutex},
|
||||
};
|
||||
use tonic::{transport::Server, Request, Response, Status};
|
||||
|
||||
const HID_DEV: &str = "/dev/hidg0";
|
||||
|
||||
#[derive(Default)]
|
||||
struct RelaySvc;
|
||||
/// Implementation of the gRPC service generated by tonic-build.
|
||||
#[derive(Debug)]
|
||||
pub struct RelaySvc {
|
||||
/// Shared handle to /dev/hidg0 (protected by a mutex because several
|
||||
/// gRPC streams may write concurrently).
|
||||
hidg: Arc<Mutex<tokio::fs::File>>,
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl Relay for RelaySvc {
|
||||
type StreamStream = ReceiverStream<Result<HidReport, Status>>;
|
||||
type StreamStream = tokio_stream::wrappers::ReceiverStream<Result<HidReport, Status>>;
|
||||
|
||||
async fn stream(
|
||||
&self,
|
||||
request: Request<tonic::Streaming<HidReport>>,
|
||||
) -> Result<Response<Self::StreamStream>, Status> {
|
||||
let mut inbound = request.into_inner();
|
||||
let (tx, rx) = mpsc::channel(8);
|
||||
|
||||
// writer task: client → hidg0
|
||||
// Channel we’ll use if one day we need to send something back.
|
||||
let (tx, rx) = mpsc::channel(32);
|
||||
|
||||
let hidg = self.hidg.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut hid = OpenOptions::new().write(true).open(HID_DEV).await.unwrap();
|
||||
while let Some(Ok(report)) = inbound.message().await {
|
||||
hid.write_all(&report.data).await.unwrap();
|
||||
while let Some(report) = inbound.message().await.transpose()? {
|
||||
// Write raw 8-byte packet to the gadget device
|
||||
hidg.lock().await.write_all(&report.data).await?;
|
||||
}
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
// nothing to send back yet
|
||||
Ok(Response::new(ReceiverStream::new(rx)))
|
||||
Ok(Response::new(tokio_stream::wrappers::ReceiverStream::new(rx)))
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let addr = "0.0.0.0:4000".parse()?;
|
||||
async fn main() -> Result<()> {
|
||||
// Open /dev/hidg0 once and share it.
|
||||
let hid_dev = if Path::new("/dev/hidg0").exists() {
|
||||
OpenOptions::new().write(true).open("/dev/hidg0").await?
|
||||
} else {
|
||||
anyhow::bail!("/dev/hidg0 not found – is navka-gadget running?");
|
||||
};
|
||||
|
||||
let svc = RelayServer::new(RelaySvc {
|
||||
hidg: Arc::new(Mutex::new(hid_dev)),
|
||||
});
|
||||
|
||||
println!("🛰️ navka-server listening on 0.0.0.0:50051");
|
||||
Server::builder()
|
||||
.add_service(RelayServer::new(RelaySvc::default()))
|
||||
.serve(addr)
|
||||
.add_service(svc)
|
||||
.serve_with_shutdown("0.0.0.0:50051".parse()?, async {
|
||||
signal::ctrl_c().await.ok();
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user