xref: /aosp_15_r20/system/nfc/tools/casimir/src/main-grpc.rs (revision 7eba2f3b06c51ae21384f6a4f14577b668a869b3)
1*7eba2f3bSAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*7eba2f3bSAndroid Build Coastguard Worker //
3*7eba2f3bSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*7eba2f3bSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*7eba2f3bSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*7eba2f3bSAndroid Build Coastguard Worker //
7*7eba2f3bSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*7eba2f3bSAndroid Build Coastguard Worker //
9*7eba2f3bSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*7eba2f3bSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*7eba2f3bSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7eba2f3bSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*7eba2f3bSAndroid Build Coastguard Worker // limitations under the License.
14*7eba2f3bSAndroid Build Coastguard Worker 
15*7eba2f3bSAndroid Build Coastguard Worker //! NFCC and RF emulator.
16*7eba2f3bSAndroid Build Coastguard Worker 
17*7eba2f3bSAndroid Build Coastguard Worker use anyhow::Result;
18*7eba2f3bSAndroid Build Coastguard Worker use argh::FromArgs;
19*7eba2f3bSAndroid Build Coastguard Worker use log::{error, info, warn};
20*7eba2f3bSAndroid Build Coastguard Worker use std::collections::HashMap;
21*7eba2f3bSAndroid Build Coastguard Worker use std::future::Future;
22*7eba2f3bSAndroid Build Coastguard Worker use std::net::{Ipv4Addr, SocketAddrV4};
23*7eba2f3bSAndroid Build Coastguard Worker use std::pin::{pin, Pin};
24*7eba2f3bSAndroid Build Coastguard Worker use std::task::Poll;
25*7eba2f3bSAndroid Build Coastguard Worker use tokio::io::AsyncReadExt;
26*7eba2f3bSAndroid Build Coastguard Worker use tokio::io::AsyncWriteExt;
27*7eba2f3bSAndroid Build Coastguard Worker use tokio::net::{tcp, TcpListener, TcpStream};
28*7eba2f3bSAndroid Build Coastguard Worker use tokio::select;
29*7eba2f3bSAndroid Build Coastguard Worker use tokio::sync::mpsc;
30*7eba2f3bSAndroid Build Coastguard Worker 
31*7eba2f3bSAndroid Build Coastguard Worker pub mod controller;
32*7eba2f3bSAndroid Build Coastguard Worker pub mod packets;
33*7eba2f3bSAndroid Build Coastguard Worker mod proto;
34*7eba2f3bSAndroid Build Coastguard Worker 
35*7eba2f3bSAndroid Build Coastguard Worker use controller::Controller;
36*7eba2f3bSAndroid Build Coastguard Worker use packets::{nci, rf};
37*7eba2f3bSAndroid Build Coastguard Worker use proto::{casimir, casimir_grpc};
38*7eba2f3bSAndroid Build Coastguard Worker 
39*7eba2f3bSAndroid Build Coastguard Worker const MAX_DEVICES: usize = 128;
40*7eba2f3bSAndroid Build Coastguard Worker type Id = u16;
41*7eba2f3bSAndroid Build Coastguard Worker 
42*7eba2f3bSAndroid Build Coastguard Worker /// Read RF Control and Data packets received on the RF transport.
43*7eba2f3bSAndroid Build Coastguard Worker /// Performs recombination of the segmented packets.
44*7eba2f3bSAndroid Build Coastguard Worker pub struct RfReader {
45*7eba2f3bSAndroid Build Coastguard Worker     socket: tcp::OwnedReadHalf,
46*7eba2f3bSAndroid Build Coastguard Worker }
47*7eba2f3bSAndroid Build Coastguard Worker 
48*7eba2f3bSAndroid Build Coastguard Worker /// Write RF Control and Data packets received to the RF transport.
49*7eba2f3bSAndroid Build Coastguard Worker /// Performs segmentation of the packets.
50*7eba2f3bSAndroid Build Coastguard Worker pub struct RfWriter {
51*7eba2f3bSAndroid Build Coastguard Worker     socket: tcp::OwnedWriteHalf,
52*7eba2f3bSAndroid Build Coastguard Worker }
53*7eba2f3bSAndroid Build Coastguard Worker 
54*7eba2f3bSAndroid Build Coastguard Worker impl RfReader {
55*7eba2f3bSAndroid Build Coastguard Worker     /// Create a new RF reader from the TCP socket half.
new(socket: tcp::OwnedReadHalf) -> Self56*7eba2f3bSAndroid Build Coastguard Worker     pub fn new(socket: tcp::OwnedReadHalf) -> Self {
57*7eba2f3bSAndroid Build Coastguard Worker         RfReader { socket }
58*7eba2f3bSAndroid Build Coastguard Worker     }
59*7eba2f3bSAndroid Build Coastguard Worker 
60*7eba2f3bSAndroid Build Coastguard Worker     /// Read a single RF packet from the reader.
61*7eba2f3bSAndroid Build Coastguard Worker     /// RF packets are framed with the byte size encoded as little-endian u16.
read(&mut self) -> Result<Vec<u8>>62*7eba2f3bSAndroid Build Coastguard Worker     pub async fn read(&mut self) -> Result<Vec<u8>> {
63*7eba2f3bSAndroid Build Coastguard Worker         const HEADER_SIZE: usize = 2;
64*7eba2f3bSAndroid Build Coastguard Worker         let mut header_bytes = [0; HEADER_SIZE];
65*7eba2f3bSAndroid Build Coastguard Worker 
66*7eba2f3bSAndroid Build Coastguard Worker         // Read the header bytes.
67*7eba2f3bSAndroid Build Coastguard Worker         self.socket.read_exact(&mut header_bytes[0..HEADER_SIZE]).await?;
68*7eba2f3bSAndroid Build Coastguard Worker         let packet_length = u16::from_le_bytes(header_bytes) as usize;
69*7eba2f3bSAndroid Build Coastguard Worker 
70*7eba2f3bSAndroid Build Coastguard Worker         // Read the packet data.
71*7eba2f3bSAndroid Build Coastguard Worker         let mut packet_bytes = vec![0; packet_length];
72*7eba2f3bSAndroid Build Coastguard Worker         self.socket.read_exact(&mut packet_bytes).await?;
73*7eba2f3bSAndroid Build Coastguard Worker 
74*7eba2f3bSAndroid Build Coastguard Worker         Ok(packet_bytes)
75*7eba2f3bSAndroid Build Coastguard Worker     }
76*7eba2f3bSAndroid Build Coastguard Worker }
77*7eba2f3bSAndroid Build Coastguard Worker 
78*7eba2f3bSAndroid Build Coastguard Worker impl RfWriter {
79*7eba2f3bSAndroid Build Coastguard Worker     /// Create a new RF writer from the TCP socket half.
new(socket: tcp::OwnedWriteHalf) -> Self80*7eba2f3bSAndroid Build Coastguard Worker     pub fn new(socket: tcp::OwnedWriteHalf) -> Self {
81*7eba2f3bSAndroid Build Coastguard Worker         RfWriter { socket }
82*7eba2f3bSAndroid Build Coastguard Worker     }
83*7eba2f3bSAndroid Build Coastguard Worker 
84*7eba2f3bSAndroid Build Coastguard Worker     /// Write a single RF packet to the writer.
85*7eba2f3bSAndroid Build Coastguard Worker     /// RF packets are framed with the byte size encoded as little-endian u16.
write(&mut self, packet: &[u8]) -> Result<()>86*7eba2f3bSAndroid Build Coastguard Worker     async fn write(&mut self, packet: &[u8]) -> Result<()> {
87*7eba2f3bSAndroid Build Coastguard Worker         let packet_length: u16 = packet.len().try_into()?;
88*7eba2f3bSAndroid Build Coastguard Worker         let header_bytes = packet_length.to_le_bytes();
89*7eba2f3bSAndroid Build Coastguard Worker 
90*7eba2f3bSAndroid Build Coastguard Worker         // Write the header bytes.
91*7eba2f3bSAndroid Build Coastguard Worker         self.socket.write_all(&header_bytes).await?;
92*7eba2f3bSAndroid Build Coastguard Worker 
93*7eba2f3bSAndroid Build Coastguard Worker         // Write the packet data.
94*7eba2f3bSAndroid Build Coastguard Worker         self.socket.write_all(packet).await?;
95*7eba2f3bSAndroid Build Coastguard Worker 
96*7eba2f3bSAndroid Build Coastguard Worker         Ok(())
97*7eba2f3bSAndroid Build Coastguard Worker     }
98*7eba2f3bSAndroid Build Coastguard Worker }
99*7eba2f3bSAndroid Build Coastguard Worker 
100*7eba2f3bSAndroid Build Coastguard Worker /// Identify the device type.
101*7eba2f3bSAndroid Build Coastguard Worker pub enum DeviceType {
102*7eba2f3bSAndroid Build Coastguard Worker     Nci,
103*7eba2f3bSAndroid Build Coastguard Worker     Rf,
104*7eba2f3bSAndroid Build Coastguard Worker }
105*7eba2f3bSAndroid Build Coastguard Worker 
106*7eba2f3bSAndroid Build Coastguard Worker /// Represent shared contextual information.
107*7eba2f3bSAndroid Build Coastguard Worker pub struct DeviceInformation {
108*7eba2f3bSAndroid Build Coastguard Worker     id: Id,
109*7eba2f3bSAndroid Build Coastguard Worker     position: u32,
110*7eba2f3bSAndroid Build Coastguard Worker     r#type: DeviceType,
111*7eba2f3bSAndroid Build Coastguard Worker }
112*7eba2f3bSAndroid Build Coastguard Worker 
113*7eba2f3bSAndroid Build Coastguard Worker /// Represent a generic NFC device interacting on the RF transport.
114*7eba2f3bSAndroid Build Coastguard Worker /// Devices communicate together through the RF mpsc channel.
115*7eba2f3bSAndroid Build Coastguard Worker /// NFCCs are an instance of Device.
116*7eba2f3bSAndroid Build Coastguard Worker pub struct Device {
117*7eba2f3bSAndroid Build Coastguard Worker     // Unique identifier associated with the device.
118*7eba2f3bSAndroid Build Coastguard Worker     // The identifier is assured never to be reused in the lifetime of
119*7eba2f3bSAndroid Build Coastguard Worker     // the emulator.
120*7eba2f3bSAndroid Build Coastguard Worker     id: Id,
121*7eba2f3bSAndroid Build Coastguard Worker     // Async task running the controller main loop.
122*7eba2f3bSAndroid Build Coastguard Worker     task: Pin<Box<dyn Future<Output = Result<()>>>>,
123*7eba2f3bSAndroid Build Coastguard Worker     // Channel for injecting RF data packets into the controller instance.
124*7eba2f3bSAndroid Build Coastguard Worker     rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
125*7eba2f3bSAndroid Build Coastguard Worker }
126*7eba2f3bSAndroid Build Coastguard Worker 
127*7eba2f3bSAndroid Build Coastguard Worker impl Device {
nci( id: Id, socket: TcpStream, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device128*7eba2f3bSAndroid Build Coastguard Worker     fn nci(
129*7eba2f3bSAndroid Build Coastguard Worker         id: Id,
130*7eba2f3bSAndroid Build Coastguard Worker         socket: TcpStream,
131*7eba2f3bSAndroid Build Coastguard Worker         controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
132*7eba2f3bSAndroid Build Coastguard Worker     ) -> Device {
133*7eba2f3bSAndroid Build Coastguard Worker         let (rf_tx, rf_rx) = mpsc::unbounded_channel();
134*7eba2f3bSAndroid Build Coastguard Worker         Device {
135*7eba2f3bSAndroid Build Coastguard Worker             id,
136*7eba2f3bSAndroid Build Coastguard Worker             rf_tx,
137*7eba2f3bSAndroid Build Coastguard Worker             task: Box::pin(async move {
138*7eba2f3bSAndroid Build Coastguard Worker                 let (nci_rx, nci_tx) = socket.into_split();
139*7eba2f3bSAndroid Build Coastguard Worker                 Controller::run(
140*7eba2f3bSAndroid Build Coastguard Worker                     id,
141*7eba2f3bSAndroid Build Coastguard Worker                     pin!(nci::Reader::new(nci_rx).into_stream()),
142*7eba2f3bSAndroid Build Coastguard Worker                     nci::Writer::new(nci_tx),
143*7eba2f3bSAndroid Build Coastguard Worker                     rf_rx,
144*7eba2f3bSAndroid Build Coastguard Worker                     controller_rf_tx,
145*7eba2f3bSAndroid Build Coastguard Worker                 )
146*7eba2f3bSAndroid Build Coastguard Worker                 .await
147*7eba2f3bSAndroid Build Coastguard Worker             }),
148*7eba2f3bSAndroid Build Coastguard Worker         }
149*7eba2f3bSAndroid Build Coastguard Worker     }
150*7eba2f3bSAndroid Build Coastguard Worker 
rf( id: Id, socket: TcpStream, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device151*7eba2f3bSAndroid Build Coastguard Worker     fn rf(
152*7eba2f3bSAndroid Build Coastguard Worker         id: Id,
153*7eba2f3bSAndroid Build Coastguard Worker         socket: TcpStream,
154*7eba2f3bSAndroid Build Coastguard Worker         controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
155*7eba2f3bSAndroid Build Coastguard Worker     ) -> Device {
156*7eba2f3bSAndroid Build Coastguard Worker         let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
157*7eba2f3bSAndroid Build Coastguard Worker         Device {
158*7eba2f3bSAndroid Build Coastguard Worker             id,
159*7eba2f3bSAndroid Build Coastguard Worker             rf_tx,
160*7eba2f3bSAndroid Build Coastguard Worker             task: Box::pin(async move {
161*7eba2f3bSAndroid Build Coastguard Worker                 let (socket_rx, socket_tx) = socket.into_split();
162*7eba2f3bSAndroid Build Coastguard Worker                 let mut rf_reader = RfReader::new(socket_rx);
163*7eba2f3bSAndroid Build Coastguard Worker                 let mut rf_writer = RfWriter::new(socket_tx);
164*7eba2f3bSAndroid Build Coastguard Worker 
165*7eba2f3bSAndroid Build Coastguard Worker                 let result: Result<((), ())> = futures::future::try_join(
166*7eba2f3bSAndroid Build Coastguard Worker                     async {
167*7eba2f3bSAndroid Build Coastguard Worker                         loop {
168*7eba2f3bSAndroid Build Coastguard Worker                             // Replace the sender identifier in the packet
169*7eba2f3bSAndroid Build Coastguard Worker                             // with the assigned number for the RF connection.
170*7eba2f3bSAndroid Build Coastguard Worker                             // TODO: currently the generated API does not allow
171*7eba2f3bSAndroid Build Coastguard Worker                             // modifying the parsed fields so the change needs to be
172*7eba2f3bSAndroid Build Coastguard Worker                             // applied to the unparsed packet.
173*7eba2f3bSAndroid Build Coastguard Worker                             let mut packet_bytes = rf_reader.read().await?;
174*7eba2f3bSAndroid Build Coastguard Worker                             packet_bytes[0..2].copy_from_slice(&id.to_le_bytes());
175*7eba2f3bSAndroid Build Coastguard Worker 
176*7eba2f3bSAndroid Build Coastguard Worker                             // Parse the input packet.
177*7eba2f3bSAndroid Build Coastguard Worker                             let packet = rf::RfPacket::parse(&packet_bytes)?;
178*7eba2f3bSAndroid Build Coastguard Worker 
179*7eba2f3bSAndroid Build Coastguard Worker                             // Forward the packet to other devices.
180*7eba2f3bSAndroid Build Coastguard Worker                             controller_rf_tx.send(packet)?;
181*7eba2f3bSAndroid Build Coastguard Worker                         }
182*7eba2f3bSAndroid Build Coastguard Worker                     },
183*7eba2f3bSAndroid Build Coastguard Worker                     async {
184*7eba2f3bSAndroid Build Coastguard Worker                         loop {
185*7eba2f3bSAndroid Build Coastguard Worker                             // Forward the packet to the socket connection.
186*7eba2f3bSAndroid Build Coastguard Worker                             use pdl_runtime::Packet;
187*7eba2f3bSAndroid Build Coastguard Worker                             let packet = rf_rx
188*7eba2f3bSAndroid Build Coastguard Worker                                 .recv()
189*7eba2f3bSAndroid Build Coastguard Worker                                 .await
190*7eba2f3bSAndroid Build Coastguard Worker                                 .ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
191*7eba2f3bSAndroid Build Coastguard Worker                             rf_writer.write(&packet.to_vec()).await?;
192*7eba2f3bSAndroid Build Coastguard Worker                         }
193*7eba2f3bSAndroid Build Coastguard Worker                     },
194*7eba2f3bSAndroid Build Coastguard Worker                 )
195*7eba2f3bSAndroid Build Coastguard Worker                 .await;
196*7eba2f3bSAndroid Build Coastguard Worker 
197*7eba2f3bSAndroid Build Coastguard Worker                 result?;
198*7eba2f3bSAndroid Build Coastguard Worker                 Ok(())
199*7eba2f3bSAndroid Build Coastguard Worker             }),
200*7eba2f3bSAndroid Build Coastguard Worker         }
201*7eba2f3bSAndroid Build Coastguard Worker     }
202*7eba2f3bSAndroid Build Coastguard Worker }
203*7eba2f3bSAndroid Build Coastguard Worker 
204*7eba2f3bSAndroid Build Coastguard Worker struct Scene {
205*7eba2f3bSAndroid Build Coastguard Worker     next_id: u16,
206*7eba2f3bSAndroid Build Coastguard Worker     waker: Option<std::task::Waker>,
207*7eba2f3bSAndroid Build Coastguard Worker     devices: [Option<Device>; MAX_DEVICES],
208*7eba2f3bSAndroid Build Coastguard Worker     context: std::sync::Arc<std::sync::Mutex<HashMap<Id, DeviceInformation>>>,
209*7eba2f3bSAndroid Build Coastguard Worker }
210*7eba2f3bSAndroid Build Coastguard Worker 
211*7eba2f3bSAndroid Build Coastguard Worker impl Scene {
new() -> Scene212*7eba2f3bSAndroid Build Coastguard Worker     fn new() -> Scene {
213*7eba2f3bSAndroid Build Coastguard Worker         const NONE: Option<Device> = None;
214*7eba2f3bSAndroid Build Coastguard Worker         Scene {
215*7eba2f3bSAndroid Build Coastguard Worker             next_id: 0,
216*7eba2f3bSAndroid Build Coastguard Worker             waker: None,
217*7eba2f3bSAndroid Build Coastguard Worker             devices: [NONE; MAX_DEVICES],
218*7eba2f3bSAndroid Build Coastguard Worker             context: std::sync::Arc::new(std::sync::Mutex::new(HashMap::new())),
219*7eba2f3bSAndroid Build Coastguard Worker         }
220*7eba2f3bSAndroid Build Coastguard Worker     }
221*7eba2f3bSAndroid Build Coastguard Worker 
wake(&mut self)222*7eba2f3bSAndroid Build Coastguard Worker     fn wake(&mut self) {
223*7eba2f3bSAndroid Build Coastguard Worker         if let Some(waker) = self.waker.take() {
224*7eba2f3bSAndroid Build Coastguard Worker             waker.wake()
225*7eba2f3bSAndroid Build Coastguard Worker         }
226*7eba2f3bSAndroid Build Coastguard Worker     }
227*7eba2f3bSAndroid Build Coastguard Worker 
add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id>228*7eba2f3bSAndroid Build Coastguard Worker     fn add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id> {
229*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
230*7eba2f3bSAndroid Build Coastguard Worker             if self.devices[n].is_none() {
231*7eba2f3bSAndroid Build Coastguard Worker                 let id = self.next_id;
232*7eba2f3bSAndroid Build Coastguard Worker                 self.devices[n] = Some(builder(id));
233*7eba2f3bSAndroid Build Coastguard Worker                 self.next_id += 1;
234*7eba2f3bSAndroid Build Coastguard Worker                 self.wake();
235*7eba2f3bSAndroid Build Coastguard Worker                 return Ok(id);
236*7eba2f3bSAndroid Build Coastguard Worker             }
237*7eba2f3bSAndroid Build Coastguard Worker         }
238*7eba2f3bSAndroid Build Coastguard Worker         Err(anyhow::anyhow!("max number of connections reached"))
239*7eba2f3bSAndroid Build Coastguard Worker     }
240*7eba2f3bSAndroid Build Coastguard Worker 
disconnect(&mut self, n: usize)241*7eba2f3bSAndroid Build Coastguard Worker     fn disconnect(&mut self, n: usize) {
242*7eba2f3bSAndroid Build Coastguard Worker         let id = self.devices[n].as_ref().unwrap().id;
243*7eba2f3bSAndroid Build Coastguard Worker         self.devices[n] = None;
244*7eba2f3bSAndroid Build Coastguard Worker         self.context.lock().unwrap().remove(&id);
245*7eba2f3bSAndroid Build Coastguard Worker         for other_n in 0..MAX_DEVICES {
246*7eba2f3bSAndroid Build Coastguard Worker             let Some(ref device) = self.devices[other_n] else { continue };
247*7eba2f3bSAndroid Build Coastguard Worker             assert!(n != other_n);
248*7eba2f3bSAndroid Build Coastguard Worker             device
249*7eba2f3bSAndroid Build Coastguard Worker                 .rf_tx
250*7eba2f3bSAndroid Build Coastguard Worker                 .send(
251*7eba2f3bSAndroid Build Coastguard Worker                     rf::DeactivateNotificationBuilder {
252*7eba2f3bSAndroid Build Coastguard Worker                         type_: rf::DeactivateType::Discovery,
253*7eba2f3bSAndroid Build Coastguard Worker                         reason: rf::DeactivateReason::RfLinkLoss,
254*7eba2f3bSAndroid Build Coastguard Worker                         sender: id,
255*7eba2f3bSAndroid Build Coastguard Worker                         receiver: device.id,
256*7eba2f3bSAndroid Build Coastguard Worker                         technology: rf::Technology::NfcA,
257*7eba2f3bSAndroid Build Coastguard Worker                         protocol: rf::Protocol::Undetermined,
258*7eba2f3bSAndroid Build Coastguard Worker                     }
259*7eba2f3bSAndroid Build Coastguard Worker                     .into(),
260*7eba2f3bSAndroid Build Coastguard Worker                 )
261*7eba2f3bSAndroid Build Coastguard Worker                 .expect("failed to send deactive notification")
262*7eba2f3bSAndroid Build Coastguard Worker         }
263*7eba2f3bSAndroid Build Coastguard Worker     }
264*7eba2f3bSAndroid Build Coastguard Worker 
send(&self, packet: &rf::RfPacket) -> Result<()>265*7eba2f3bSAndroid Build Coastguard Worker     fn send(&self, packet: &rf::RfPacket) -> Result<()> {
266*7eba2f3bSAndroid Build Coastguard Worker         let context = self.context.lock().unwrap();
267*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
268*7eba2f3bSAndroid Build Coastguard Worker             let Some(ref device) = self.devices[n] else { continue };
269*7eba2f3bSAndroid Build Coastguard Worker             if packet.get_sender() != device.id
270*7eba2f3bSAndroid Build Coastguard Worker                 && (packet.get_receiver() == u16::MAX || packet.get_receiver() == device.id)
271*7eba2f3bSAndroid Build Coastguard Worker                 && context.get(&device.id).map(|info| info.position)
272*7eba2f3bSAndroid Build Coastguard Worker                     == context.get(&packet.get_sender()).map(|info| info.position)
273*7eba2f3bSAndroid Build Coastguard Worker             {
274*7eba2f3bSAndroid Build Coastguard Worker                 device.rf_tx.send(packet.to_owned())?;
275*7eba2f3bSAndroid Build Coastguard Worker             }
276*7eba2f3bSAndroid Build Coastguard Worker         }
277*7eba2f3bSAndroid Build Coastguard Worker 
278*7eba2f3bSAndroid Build Coastguard Worker         Ok(())
279*7eba2f3bSAndroid Build Coastguard Worker     }
280*7eba2f3bSAndroid Build Coastguard Worker }
281*7eba2f3bSAndroid Build Coastguard Worker 
282*7eba2f3bSAndroid Build Coastguard Worker impl Future for Scene {
283*7eba2f3bSAndroid Build Coastguard Worker     type Output = ();
284*7eba2f3bSAndroid Build Coastguard Worker 
poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()>285*7eba2f3bSAndroid Build Coastguard Worker     fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()> {
286*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
287*7eba2f3bSAndroid Build Coastguard Worker             let dropped = match self.devices[n] {
288*7eba2f3bSAndroid Build Coastguard Worker                 Some(ref mut device) => match device.task.as_mut().poll(cx) {
289*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Ready(Ok(_)) => unreachable!(),
290*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Ready(Err(err)) => {
291*7eba2f3bSAndroid Build Coastguard Worker                         warn!("dropping device {}: {}", n, err);
292*7eba2f3bSAndroid Build Coastguard Worker                         true
293*7eba2f3bSAndroid Build Coastguard Worker                     }
294*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Pending => false,
295*7eba2f3bSAndroid Build Coastguard Worker                 },
296*7eba2f3bSAndroid Build Coastguard Worker                 None => false,
297*7eba2f3bSAndroid Build Coastguard Worker             };
298*7eba2f3bSAndroid Build Coastguard Worker             if dropped {
299*7eba2f3bSAndroid Build Coastguard Worker                 self.disconnect(n)
300*7eba2f3bSAndroid Build Coastguard Worker             }
301*7eba2f3bSAndroid Build Coastguard Worker         }
302*7eba2f3bSAndroid Build Coastguard Worker         self.waker = Some(cx.waker().clone());
303*7eba2f3bSAndroid Build Coastguard Worker         Poll::Pending
304*7eba2f3bSAndroid Build Coastguard Worker     }
305*7eba2f3bSAndroid Build Coastguard Worker }
306*7eba2f3bSAndroid Build Coastguard Worker 
307*7eba2f3bSAndroid Build Coastguard Worker #[derive(Clone)]
308*7eba2f3bSAndroid Build Coastguard Worker struct Service {
309*7eba2f3bSAndroid Build Coastguard Worker     context: std::sync::Arc<std::sync::Mutex<HashMap<Id, DeviceInformation>>>,
310*7eba2f3bSAndroid Build Coastguard Worker }
311*7eba2f3bSAndroid Build Coastguard Worker 
312*7eba2f3bSAndroid Build Coastguard Worker impl From<&DeviceInformation> for casimir::Device {
from(info: &DeviceInformation) -> Self313*7eba2f3bSAndroid Build Coastguard Worker     fn from(info: &DeviceInformation) -> Self {
314*7eba2f3bSAndroid Build Coastguard Worker         let mut device = casimir::Device::new();
315*7eba2f3bSAndroid Build Coastguard Worker         device.set_device_id(info.id as u32);
316*7eba2f3bSAndroid Build Coastguard Worker         device.set_position(info.position);
317*7eba2f3bSAndroid Build Coastguard Worker         match info.r#type {
318*7eba2f3bSAndroid Build Coastguard Worker             DeviceType::Nci => device.set_nci(Default::default()),
319*7eba2f3bSAndroid Build Coastguard Worker             DeviceType::Rf => device.set_rf(Default::default()),
320*7eba2f3bSAndroid Build Coastguard Worker         }
321*7eba2f3bSAndroid Build Coastguard Worker         device
322*7eba2f3bSAndroid Build Coastguard Worker     }
323*7eba2f3bSAndroid Build Coastguard Worker }
324*7eba2f3bSAndroid Build Coastguard Worker 
325*7eba2f3bSAndroid Build Coastguard Worker impl casimir_grpc::Casimir for Service {
list_devices( &mut self, _ctx: grpcio::RpcContext<'_>, _req: casimir::ListDevicesRequest, sink: grpcio::UnarySink<casimir::ListDevicesResponse>, )326*7eba2f3bSAndroid Build Coastguard Worker     fn list_devices(
327*7eba2f3bSAndroid Build Coastguard Worker         &mut self,
328*7eba2f3bSAndroid Build Coastguard Worker         _ctx: grpcio::RpcContext<'_>,
329*7eba2f3bSAndroid Build Coastguard Worker         _req: casimir::ListDevicesRequest,
330*7eba2f3bSAndroid Build Coastguard Worker         sink: grpcio::UnarySink<casimir::ListDevicesResponse>,
331*7eba2f3bSAndroid Build Coastguard Worker     ) {
332*7eba2f3bSAndroid Build Coastguard Worker         let mut response = casimir::ListDevicesResponse::new();
333*7eba2f3bSAndroid Build Coastguard Worker         response.set_device(
334*7eba2f3bSAndroid Build Coastguard Worker             self.context
335*7eba2f3bSAndroid Build Coastguard Worker                 .lock()
336*7eba2f3bSAndroid Build Coastguard Worker                 .unwrap()
337*7eba2f3bSAndroid Build Coastguard Worker                 .values()
338*7eba2f3bSAndroid Build Coastguard Worker                 .map(casimir::Device::from)
339*7eba2f3bSAndroid Build Coastguard Worker                 .collect::<Vec<_>>()
340*7eba2f3bSAndroid Build Coastguard Worker                 .into(),
341*7eba2f3bSAndroid Build Coastguard Worker         );
342*7eba2f3bSAndroid Build Coastguard Worker         sink.success(response);
343*7eba2f3bSAndroid Build Coastguard Worker     }
344*7eba2f3bSAndroid Build Coastguard Worker 
get_device( &mut self, _ctx: grpcio::RpcContext<'_>, req: casimir::GetDeviceRequest, sink: grpcio::UnarySink<casimir::GetDeviceResponse>, )345*7eba2f3bSAndroid Build Coastguard Worker     fn get_device(
346*7eba2f3bSAndroid Build Coastguard Worker         &mut self,
347*7eba2f3bSAndroid Build Coastguard Worker         _ctx: grpcio::RpcContext<'_>,
348*7eba2f3bSAndroid Build Coastguard Worker         req: casimir::GetDeviceRequest,
349*7eba2f3bSAndroid Build Coastguard Worker         sink: grpcio::UnarySink<casimir::GetDeviceResponse>,
350*7eba2f3bSAndroid Build Coastguard Worker     ) {
351*7eba2f3bSAndroid Build Coastguard Worker         match self.context.lock().unwrap().get(&(req.get_device_id() as u16)) {
352*7eba2f3bSAndroid Build Coastguard Worker             Some(info) => {
353*7eba2f3bSAndroid Build Coastguard Worker                 let mut response = casimir::GetDeviceResponse::new();
354*7eba2f3bSAndroid Build Coastguard Worker                 response.set_device(info.into());
355*7eba2f3bSAndroid Build Coastguard Worker                 sink.success(response)
356*7eba2f3bSAndroid Build Coastguard Worker             }
357*7eba2f3bSAndroid Build Coastguard Worker             None => sink.fail(grpcio::RpcStatus::with_message(
358*7eba2f3bSAndroid Build Coastguard Worker                 grpcio::RpcStatusCode::INVALID_ARGUMENT,
359*7eba2f3bSAndroid Build Coastguard Worker                 format!("device_id {} not found", req.get_device_id()),
360*7eba2f3bSAndroid Build Coastguard Worker             )),
361*7eba2f3bSAndroid Build Coastguard Worker         };
362*7eba2f3bSAndroid Build Coastguard Worker     }
363*7eba2f3bSAndroid Build Coastguard Worker 
move_device( &mut self, _ctx: grpcio::RpcContext<'_>, req: casimir::MoveDeviceRequest, sink: grpcio::UnarySink<casimir::MoveDeviceResponse>, )364*7eba2f3bSAndroid Build Coastguard Worker     fn move_device(
365*7eba2f3bSAndroid Build Coastguard Worker         &mut self,
366*7eba2f3bSAndroid Build Coastguard Worker         _ctx: grpcio::RpcContext<'_>,
367*7eba2f3bSAndroid Build Coastguard Worker         req: casimir::MoveDeviceRequest,
368*7eba2f3bSAndroid Build Coastguard Worker         sink: grpcio::UnarySink<casimir::MoveDeviceResponse>,
369*7eba2f3bSAndroid Build Coastguard Worker     ) {
370*7eba2f3bSAndroid Build Coastguard Worker         match self.context.lock().unwrap().get_mut(&(req.get_device_id() as u16)) {
371*7eba2f3bSAndroid Build Coastguard Worker             Some(info) => {
372*7eba2f3bSAndroid Build Coastguard Worker                 info.position = req.get_position();
373*7eba2f3bSAndroid Build Coastguard Worker                 sink.success(Default::default())
374*7eba2f3bSAndroid Build Coastguard Worker             }
375*7eba2f3bSAndroid Build Coastguard Worker             None => sink.fail(grpcio::RpcStatus::with_message(
376*7eba2f3bSAndroid Build Coastguard Worker                 grpcio::RpcStatusCode::INVALID_ARGUMENT,
377*7eba2f3bSAndroid Build Coastguard Worker                 format!("device_id {} not found", req.get_device_id()),
378*7eba2f3bSAndroid Build Coastguard Worker             )),
379*7eba2f3bSAndroid Build Coastguard Worker         };
380*7eba2f3bSAndroid Build Coastguard Worker     }
381*7eba2f3bSAndroid Build Coastguard Worker }
382*7eba2f3bSAndroid Build Coastguard Worker 
383*7eba2f3bSAndroid Build Coastguard Worker #[derive(FromArgs, Debug)]
384*7eba2f3bSAndroid Build Coastguard Worker /// Nfc emulator.
385*7eba2f3bSAndroid Build Coastguard Worker struct Opt {
386*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option, default = "7000")]
387*7eba2f3bSAndroid Build Coastguard Worker     /// configure the TCP port for the NCI server.
388*7eba2f3bSAndroid Build Coastguard Worker     nci_port: u16,
389*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option, default = "7001")]
390*7eba2f3bSAndroid Build Coastguard Worker     /// configure the TCP port for the RF server.
391*7eba2f3bSAndroid Build Coastguard Worker     rf_port: u16,
392*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option, default = "50051")]
393*7eba2f3bSAndroid Build Coastguard Worker     /// configure the gRPC port.
394*7eba2f3bSAndroid Build Coastguard Worker     grpc_port: u16,
395*7eba2f3bSAndroid Build Coastguard Worker }
396*7eba2f3bSAndroid Build Coastguard Worker 
run() -> Result<()>397*7eba2f3bSAndroid Build Coastguard Worker async fn run() -> Result<()> {
398*7eba2f3bSAndroid Build Coastguard Worker     env_logger::init_from_env(
399*7eba2f3bSAndroid Build Coastguard Worker         env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "debug"),
400*7eba2f3bSAndroid Build Coastguard Worker     );
401*7eba2f3bSAndroid Build Coastguard Worker 
402*7eba2f3bSAndroid Build Coastguard Worker     let opt: Opt = argh::from_env();
403*7eba2f3bSAndroid Build Coastguard Worker     let nci_listener =
404*7eba2f3bSAndroid Build Coastguard Worker         TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, opt.nci_port)).await?;
405*7eba2f3bSAndroid Build Coastguard Worker     let rf_listener =
406*7eba2f3bSAndroid Build Coastguard Worker         TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, opt.rf_port)).await?;
407*7eba2f3bSAndroid Build Coastguard Worker     let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
408*7eba2f3bSAndroid Build Coastguard Worker     let mut scene = Scene::new();
409*7eba2f3bSAndroid Build Coastguard Worker 
410*7eba2f3bSAndroid Build Coastguard Worker     info!("Listening for NCI connections at address 127.0.0.1:{}", opt.nci_port);
411*7eba2f3bSAndroid Build Coastguard Worker     info!("Listening for RF connections at address 127.0.0.1:{}", opt.rf_port);
412*7eba2f3bSAndroid Build Coastguard Worker     info!("Listening for gRPC connections at address 127.0.0.1:{}", opt.grpc_port);
413*7eba2f3bSAndroid Build Coastguard Worker 
414*7eba2f3bSAndroid Build Coastguard Worker     let env = std::sync::Arc::new(grpcio::Environment::new(1));
415*7eba2f3bSAndroid Build Coastguard Worker     let service = casimir_grpc::create_casimir(Service { context: scene.context.clone() });
416*7eba2f3bSAndroid Build Coastguard Worker     let quota = grpcio::ResourceQuota::new(Some("CasimirQuota")).resize_memory(1024 * 1024);
417*7eba2f3bSAndroid Build Coastguard Worker     let channel_builder = grpcio::ChannelBuilder::new(env.clone()).set_resource_quota(quota);
418*7eba2f3bSAndroid Build Coastguard Worker 
419*7eba2f3bSAndroid Build Coastguard Worker     let mut server = grpcio::ServerBuilder::new(env)
420*7eba2f3bSAndroid Build Coastguard Worker         .register_service(service)
421*7eba2f3bSAndroid Build Coastguard Worker         .channel_args(channel_builder.build_args())
422*7eba2f3bSAndroid Build Coastguard Worker         .build()
423*7eba2f3bSAndroid Build Coastguard Worker         .unwrap();
424*7eba2f3bSAndroid Build Coastguard Worker     server
425*7eba2f3bSAndroid Build Coastguard Worker         .add_listening_port(
426*7eba2f3bSAndroid Build Coastguard Worker             format!("127.0.0.1:{}", opt.grpc_port),
427*7eba2f3bSAndroid Build Coastguard Worker             grpcio::ServerCredentials::insecure(),
428*7eba2f3bSAndroid Build Coastguard Worker         )
429*7eba2f3bSAndroid Build Coastguard Worker         .unwrap();
430*7eba2f3bSAndroid Build Coastguard Worker     server.start();
431*7eba2f3bSAndroid Build Coastguard Worker 
432*7eba2f3bSAndroid Build Coastguard Worker     loop {
433*7eba2f3bSAndroid Build Coastguard Worker         select! {
434*7eba2f3bSAndroid Build Coastguard Worker             result = nci_listener.accept() => {
435*7eba2f3bSAndroid Build Coastguard Worker                 let (socket, addr) = result?;
436*7eba2f3bSAndroid Build Coastguard Worker                 info!("Incoming NCI connection from {}", addr);
437*7eba2f3bSAndroid Build Coastguard Worker                 match scene.add_device(|id| Device::nci(id, socket, rf_tx.clone())) {
438*7eba2f3bSAndroid Build Coastguard Worker                     Ok(id) => {
439*7eba2f3bSAndroid Build Coastguard Worker                         scene.context.lock().unwrap().insert(id, DeviceInformation {
440*7eba2f3bSAndroid Build Coastguard Worker                             id, position: id as u32, r#type: DeviceType::Nci
441*7eba2f3bSAndroid Build Coastguard Worker                         });
442*7eba2f3bSAndroid Build Coastguard Worker                         info!("Accepted NCI connection from {} with id {}", addr, id)
443*7eba2f3bSAndroid Build Coastguard Worker                     }
444*7eba2f3bSAndroid Build Coastguard Worker                     Err(err) => error!("Failed to accept NCI connection from {}: {}", addr, err)
445*7eba2f3bSAndroid Build Coastguard Worker                 }
446*7eba2f3bSAndroid Build Coastguard Worker             },
447*7eba2f3bSAndroid Build Coastguard Worker             result = rf_listener.accept() => {
448*7eba2f3bSAndroid Build Coastguard Worker                 let (socket, addr) = result?;
449*7eba2f3bSAndroid Build Coastguard Worker                 info!("Incoming RF connection from {}", addr);
450*7eba2f3bSAndroid Build Coastguard Worker                 match scene.add_device(|id| Device::rf(id, socket, rf_tx.clone())) {
451*7eba2f3bSAndroid Build Coastguard Worker                     Ok(id) => {
452*7eba2f3bSAndroid Build Coastguard Worker                         scene.context.lock().unwrap().insert(id, DeviceInformation {
453*7eba2f3bSAndroid Build Coastguard Worker                             id, position: id as u32, r#type: DeviceType::Rf
454*7eba2f3bSAndroid Build Coastguard Worker                         });
455*7eba2f3bSAndroid Build Coastguard Worker                         info!("Accepted RF connection from {} with id {}", addr, id)
456*7eba2f3bSAndroid Build Coastguard Worker                     }
457*7eba2f3bSAndroid Build Coastguard Worker                     Err(err) => error!("Failed to accept RF connection from {}: {}", addr, err)
458*7eba2f3bSAndroid Build Coastguard Worker                 }
459*7eba2f3bSAndroid Build Coastguard Worker             },
460*7eba2f3bSAndroid Build Coastguard Worker             _ = &mut scene => (),
461*7eba2f3bSAndroid Build Coastguard Worker             result = rf_rx.recv() => {
462*7eba2f3bSAndroid Build Coastguard Worker                 let packet = result.ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
463*7eba2f3bSAndroid Build Coastguard Worker                 scene.send(&packet)?
464*7eba2f3bSAndroid Build Coastguard Worker             }
465*7eba2f3bSAndroid Build Coastguard Worker         }
466*7eba2f3bSAndroid Build Coastguard Worker     }
467*7eba2f3bSAndroid Build Coastguard Worker }
468*7eba2f3bSAndroid Build Coastguard Worker 
469*7eba2f3bSAndroid Build Coastguard Worker #[tokio::main]
main() -> Result<()>470*7eba2f3bSAndroid Build Coastguard Worker async fn main() -> Result<()> {
471*7eba2f3bSAndroid Build Coastguard Worker     run().await
472*7eba2f3bSAndroid Build Coastguard Worker }
473