139 lines
4.7 KiB
Rust
139 lines
4.7 KiB
Rust
|
|
#[cfg(coverage)]
|
||
|
|
#[tonic::async_trait]
|
||
|
|
impl Relay for Handler {
|
||
|
|
type StreamKeyboardStream = ReceiverStream<Result<KeyboardReport, Status>>;
|
||
|
|
type StreamMouseStream = ReceiverStream<Result<MouseReport, Status>>;
|
||
|
|
type CaptureVideoStream = VideoStream;
|
||
|
|
type CaptureAudioStream = AudioStream;
|
||
|
|
type StreamMicrophoneStream = ReceiverStream<Result<Empty, Status>>;
|
||
|
|
type StreamCameraStream = ReceiverStream<Result<Empty, Status>>;
|
||
|
|
|
||
|
|
async fn stream_keyboard(
|
||
|
|
&self,
|
||
|
|
req: Request<tonic::Streaming<KeyboardReport>>,
|
||
|
|
) -> Result<Response<Self::StreamKeyboardStream>, Status> {
|
||
|
|
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||
|
|
let kb = self.kb.clone();
|
||
|
|
let report_delay = live_keyboard_report_delay();
|
||
|
|
|
||
|
|
tokio::spawn(async move {
|
||
|
|
let mut s = req.into_inner();
|
||
|
|
while let Some(pkt) = s.next().await.transpose()? {
|
||
|
|
let _ = runtime_support::write_hid_report(&kb, &hid_endpoint(0), &pkt.data).await;
|
||
|
|
tx.send(Ok(pkt)).await.ok();
|
||
|
|
if !report_delay.is_zero() {
|
||
|
|
#[cfg(not(coverage))]
|
||
|
|
tokio::time::sleep(report_delay).await;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Ok::<(), Status>(())
|
||
|
|
});
|
||
|
|
|
||
|
|
Ok(Response::new(ReceiverStream::new(rx)))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn stream_mouse(
|
||
|
|
&self,
|
||
|
|
req: Request<tonic::Streaming<MouseReport>>,
|
||
|
|
) -> Result<Response<Self::StreamMouseStream>, Status> {
|
||
|
|
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||
|
|
let ms = self.ms.clone();
|
||
|
|
|
||
|
|
tokio::spawn(async move {
|
||
|
|
let mut s = req.into_inner();
|
||
|
|
while let Some(pkt) = s.next().await.transpose()? {
|
||
|
|
let _ = runtime_support::write_hid_report(&ms, &hid_endpoint(1), &pkt.data).await;
|
||
|
|
tx.send(Ok(pkt)).await.ok();
|
||
|
|
}
|
||
|
|
Ok::<(), Status>(())
|
||
|
|
});
|
||
|
|
|
||
|
|
Ok(Response::new(ReceiverStream::new(rx)))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn stream_microphone(
|
||
|
|
&self,
|
||
|
|
req: Request<tonic::Streaming<AudioPacket>>,
|
||
|
|
) -> Result<Response<Self::StreamMicrophoneStream>, Status> {
|
||
|
|
let uac_dev = std::env::var("LESAVKA_UAC_DEV").unwrap_or_else(|_| "hw:UAC2Gadget,0".into());
|
||
|
|
let mut sink = runtime_support::open_voice_with_retry(&uac_dev)
|
||
|
|
.await
|
||
|
|
.map_err(|e| Status::internal(format!("{e:#}")))?;
|
||
|
|
let (tx, rx) = tokio::sync::mpsc::channel(1);
|
||
|
|
|
||
|
|
tokio::spawn(async move {
|
||
|
|
let mut inbound = req.into_inner();
|
||
|
|
while let Some(pkt) = inbound.next().await.transpose()? {
|
||
|
|
sink.push(&pkt);
|
||
|
|
}
|
||
|
|
sink.finish();
|
||
|
|
let _ = tx.send(Ok(Empty {})).await;
|
||
|
|
Ok::<(), Status>(())
|
||
|
|
});
|
||
|
|
|
||
|
|
Ok(Response::new(ReceiverStream::new(rx)))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn stream_camera(
|
||
|
|
&self,
|
||
|
|
req: Request<tonic::Streaming<VideoPacket>>,
|
||
|
|
) -> Result<Response<Self::StreamCameraStream>, Status> {
|
||
|
|
let cfg = camera::current_camera_config();
|
||
|
|
let (session_id, relay) = self.camera_rt.activate(&cfg).await?;
|
||
|
|
let camera_rt = self.camera_rt.clone();
|
||
|
|
let (tx, rx) = tokio::sync::mpsc::channel(1);
|
||
|
|
|
||
|
|
tokio::spawn(async move {
|
||
|
|
let mut s = req.into_inner();
|
||
|
|
while let Some(pkt) = s.next().await.transpose()? {
|
||
|
|
if !camera_rt.is_active(session_id) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
relay.feed(pkt);
|
||
|
|
}
|
||
|
|
tx.send(Ok(Empty {})).await.ok();
|
||
|
|
Ok::<(), Status>(())
|
||
|
|
});
|
||
|
|
|
||
|
|
Ok(Response::new(ReceiverStream::new(rx)))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn capture_video(
|
||
|
|
&self,
|
||
|
|
req: Request<MonitorRequest>,
|
||
|
|
) -> Result<Response<Self::CaptureVideoStream>, Status> {
|
||
|
|
self.capture_video_reply(req.into_inner()).await
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn capture_audio(
|
||
|
|
&self,
|
||
|
|
_req: Request<MonitorRequest>,
|
||
|
|
) -> Result<Response<Self::CaptureAudioStream>, Status> {
|
||
|
|
Err(Status::internal(
|
||
|
|
"audio capture unavailable in coverage harness",
|
||
|
|
))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn paste_text(&self, req: Request<PasteRequest>) -> Result<Response<PasteReply>, Status> {
|
||
|
|
self.paste_text_reply(req).await
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn reset_usb(&self, _req: Request<Empty>) -> Result<Response<ResetUsbReply>, Status> {
|
||
|
|
self.reset_usb_reply().await
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn get_capture_power(
|
||
|
|
&self,
|
||
|
|
_req: Request<Empty>,
|
||
|
|
) -> Result<Response<CapturePowerState>, Status> {
|
||
|
|
self.get_capture_power_reply().await
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn set_capture_power(
|
||
|
|
&self,
|
||
|
|
req: Request<SetCapturePowerRequest>,
|
||
|
|
) -> Result<Response<CapturePowerState>, Status> {
|
||
|
|
self.set_capture_power_reply(req).await
|
||
|
|
}
|
||
|
|
}
|