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 rustutils::inherited_fd;
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::Context;
25*7eba2f3bSAndroid Build Coastguard Worker use std::task::Poll;
26*7eba2f3bSAndroid Build Coastguard Worker use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
27*7eba2f3bSAndroid Build Coastguard Worker use tokio::net::{TcpListener, UnixListener};
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
34*7eba2f3bSAndroid Build Coastguard Worker use controller::Controller;
35*7eba2f3bSAndroid Build Coastguard Worker use packets::{nci, rf};
36*7eba2f3bSAndroid Build Coastguard Worker
37*7eba2f3bSAndroid Build Coastguard Worker const MAX_DEVICES: usize = 128;
38*7eba2f3bSAndroid Build Coastguard Worker type Id = u16;
39*7eba2f3bSAndroid Build Coastguard Worker
40*7eba2f3bSAndroid Build Coastguard Worker /// Read RF Control and Data packets received on the RF transport.
41*7eba2f3bSAndroid Build Coastguard Worker /// Performs recombination of the segmented packets.
42*7eba2f3bSAndroid Build Coastguard Worker pub struct RfReader {
43*7eba2f3bSAndroid Build Coastguard Worker socket: Pin<Box<dyn AsyncRead>>,
44*7eba2f3bSAndroid Build Coastguard Worker }
45*7eba2f3bSAndroid Build Coastguard Worker
46*7eba2f3bSAndroid Build Coastguard Worker /// Write RF Control and Data packets received to the RF transport.
47*7eba2f3bSAndroid Build Coastguard Worker /// Performs segmentation of the packets.
48*7eba2f3bSAndroid Build Coastguard Worker pub struct RfWriter {
49*7eba2f3bSAndroid Build Coastguard Worker socket: Pin<Box<dyn AsyncWrite>>,
50*7eba2f3bSAndroid Build Coastguard Worker }
51*7eba2f3bSAndroid Build Coastguard Worker
52*7eba2f3bSAndroid Build Coastguard Worker impl RfReader {
53*7eba2f3bSAndroid Build Coastguard Worker /// Create a new RF reader from an `AsyncRead` implementation.
new(socket: impl AsyncRead + 'static) -> Self54*7eba2f3bSAndroid Build Coastguard Worker pub fn new(socket: impl AsyncRead + 'static) -> Self {
55*7eba2f3bSAndroid Build Coastguard Worker RfReader { socket: Box::pin(socket) }
56*7eba2f3bSAndroid Build Coastguard Worker }
57*7eba2f3bSAndroid Build Coastguard Worker
58*7eba2f3bSAndroid Build Coastguard Worker /// Read a single RF packet from the reader.
59*7eba2f3bSAndroid Build Coastguard Worker /// RF packets are framed with the byte size encoded as little-endian u16.
read(&mut self) -> Result<Vec<u8>>60*7eba2f3bSAndroid Build Coastguard Worker pub async fn read(&mut self) -> Result<Vec<u8>> {
61*7eba2f3bSAndroid Build Coastguard Worker const HEADER_SIZE: usize = 2;
62*7eba2f3bSAndroid Build Coastguard Worker let mut header_bytes = [0; HEADER_SIZE];
63*7eba2f3bSAndroid Build Coastguard Worker
64*7eba2f3bSAndroid Build Coastguard Worker // Read the header bytes.
65*7eba2f3bSAndroid Build Coastguard Worker self.socket.read_exact(&mut header_bytes[0..HEADER_SIZE]).await?;
66*7eba2f3bSAndroid Build Coastguard Worker let packet_length = u16::from_le_bytes(header_bytes) as usize;
67*7eba2f3bSAndroid Build Coastguard Worker
68*7eba2f3bSAndroid Build Coastguard Worker // Read the packet data.
69*7eba2f3bSAndroid Build Coastguard Worker let mut packet_bytes = vec![0; packet_length];
70*7eba2f3bSAndroid Build Coastguard Worker self.socket.read_exact(&mut packet_bytes).await?;
71*7eba2f3bSAndroid Build Coastguard Worker
72*7eba2f3bSAndroid Build Coastguard Worker Ok(packet_bytes)
73*7eba2f3bSAndroid Build Coastguard Worker }
74*7eba2f3bSAndroid Build Coastguard Worker }
75*7eba2f3bSAndroid Build Coastguard Worker
76*7eba2f3bSAndroid Build Coastguard Worker impl RfWriter {
77*7eba2f3bSAndroid Build Coastguard Worker /// Create a new RF writer from an `AsyncWrite` implementation.
new(socket: impl AsyncWrite + 'static) -> Self78*7eba2f3bSAndroid Build Coastguard Worker pub fn new(socket: impl AsyncWrite + 'static) -> Self {
79*7eba2f3bSAndroid Build Coastguard Worker RfWriter { socket: Box::pin(socket) }
80*7eba2f3bSAndroid Build Coastguard Worker }
81*7eba2f3bSAndroid Build Coastguard Worker
82*7eba2f3bSAndroid Build Coastguard Worker /// Write a single RF packet to the writer.
83*7eba2f3bSAndroid Build Coastguard Worker /// RF packets are framed with the byte size encoded as little-endian u16.
write(&mut self, packet: &[u8]) -> Result<()>84*7eba2f3bSAndroid Build Coastguard Worker async fn write(&mut self, packet: &[u8]) -> Result<()> {
85*7eba2f3bSAndroid Build Coastguard Worker let packet_length: u16 = packet.len().try_into()?;
86*7eba2f3bSAndroid Build Coastguard Worker let header_bytes = packet_length.to_le_bytes();
87*7eba2f3bSAndroid Build Coastguard Worker
88*7eba2f3bSAndroid Build Coastguard Worker // Write the header bytes.
89*7eba2f3bSAndroid Build Coastguard Worker self.socket.write_all(&header_bytes).await?;
90*7eba2f3bSAndroid Build Coastguard Worker
91*7eba2f3bSAndroid Build Coastguard Worker // Write the packet data.
92*7eba2f3bSAndroid Build Coastguard Worker self.socket.write_all(packet).await?;
93*7eba2f3bSAndroid Build Coastguard Worker
94*7eba2f3bSAndroid Build Coastguard Worker Ok(())
95*7eba2f3bSAndroid Build Coastguard Worker }
96*7eba2f3bSAndroid Build Coastguard Worker }
97*7eba2f3bSAndroid Build Coastguard Worker
98*7eba2f3bSAndroid Build Coastguard Worker /// Represent a generic NFC device interacting on the RF transport.
99*7eba2f3bSAndroid Build Coastguard Worker /// Devices communicate together through the RF mpsc channel.
100*7eba2f3bSAndroid Build Coastguard Worker /// NFCCs are an instance of Device.
101*7eba2f3bSAndroid Build Coastguard Worker pub struct Device {
102*7eba2f3bSAndroid Build Coastguard Worker // Unique identifier associated with the device.
103*7eba2f3bSAndroid Build Coastguard Worker // The identifier is assured never to be reused in the lifetime of
104*7eba2f3bSAndroid Build Coastguard Worker // the emulator.
105*7eba2f3bSAndroid Build Coastguard Worker id: u16,
106*7eba2f3bSAndroid Build Coastguard Worker // Async task running the controller main loop.
107*7eba2f3bSAndroid Build Coastguard Worker task: Pin<Box<dyn Future<Output = Result<()>>>>,
108*7eba2f3bSAndroid Build Coastguard Worker // Channel for injecting RF data packets into the controller instance.
109*7eba2f3bSAndroid Build Coastguard Worker rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
110*7eba2f3bSAndroid Build Coastguard Worker }
111*7eba2f3bSAndroid Build Coastguard Worker
112*7eba2f3bSAndroid Build Coastguard Worker impl Device {
nci( id: Id, nci_rx: impl AsyncRead + 'static, nci_tx: impl AsyncWrite + 'static, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device113*7eba2f3bSAndroid Build Coastguard Worker fn nci(
114*7eba2f3bSAndroid Build Coastguard Worker id: Id,
115*7eba2f3bSAndroid Build Coastguard Worker nci_rx: impl AsyncRead + 'static,
116*7eba2f3bSAndroid Build Coastguard Worker nci_tx: impl AsyncWrite + 'static,
117*7eba2f3bSAndroid Build Coastguard Worker controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
118*7eba2f3bSAndroid Build Coastguard Worker ) -> Device {
119*7eba2f3bSAndroid Build Coastguard Worker let (rf_tx, rf_rx) = mpsc::unbounded_channel();
120*7eba2f3bSAndroid Build Coastguard Worker Device {
121*7eba2f3bSAndroid Build Coastguard Worker id,
122*7eba2f3bSAndroid Build Coastguard Worker rf_tx,
123*7eba2f3bSAndroid Build Coastguard Worker task: Box::pin(async move {
124*7eba2f3bSAndroid Build Coastguard Worker Controller::run(
125*7eba2f3bSAndroid Build Coastguard Worker id,
126*7eba2f3bSAndroid Build Coastguard Worker pin!(nci::Reader::new(nci_rx).into_stream()),
127*7eba2f3bSAndroid Build Coastguard Worker nci::Writer::new(nci_tx),
128*7eba2f3bSAndroid Build Coastguard Worker rf_rx,
129*7eba2f3bSAndroid Build Coastguard Worker controller_rf_tx,
130*7eba2f3bSAndroid Build Coastguard Worker )
131*7eba2f3bSAndroid Build Coastguard Worker .await
132*7eba2f3bSAndroid Build Coastguard Worker }),
133*7eba2f3bSAndroid Build Coastguard Worker }
134*7eba2f3bSAndroid Build Coastguard Worker }
135*7eba2f3bSAndroid Build Coastguard Worker
rf( id: Id, socket_rx: impl AsyncRead + 'static, socket_tx: impl AsyncWrite + 'static, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device136*7eba2f3bSAndroid Build Coastguard Worker fn rf(
137*7eba2f3bSAndroid Build Coastguard Worker id: Id,
138*7eba2f3bSAndroid Build Coastguard Worker socket_rx: impl AsyncRead + 'static,
139*7eba2f3bSAndroid Build Coastguard Worker socket_tx: impl AsyncWrite + 'static,
140*7eba2f3bSAndroid Build Coastguard Worker controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
141*7eba2f3bSAndroid Build Coastguard Worker ) -> Device {
142*7eba2f3bSAndroid Build Coastguard Worker let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
143*7eba2f3bSAndroid Build Coastguard Worker Device {
144*7eba2f3bSAndroid Build Coastguard Worker id,
145*7eba2f3bSAndroid Build Coastguard Worker rf_tx,
146*7eba2f3bSAndroid Build Coastguard Worker task: Box::pin(async move {
147*7eba2f3bSAndroid Build Coastguard Worker let mut rf_reader = RfReader::new(socket_rx);
148*7eba2f3bSAndroid Build Coastguard Worker let mut rf_writer = RfWriter::new(socket_tx);
149*7eba2f3bSAndroid Build Coastguard Worker
150*7eba2f3bSAndroid Build Coastguard Worker let result: Result<((), ())> = futures::future::try_join(
151*7eba2f3bSAndroid Build Coastguard Worker async {
152*7eba2f3bSAndroid Build Coastguard Worker loop {
153*7eba2f3bSAndroid Build Coastguard Worker // Replace the sender identifier in the packet
154*7eba2f3bSAndroid Build Coastguard Worker // with the assigned number for the RF connection.
155*7eba2f3bSAndroid Build Coastguard Worker // TODO: currently the generated API does not allow
156*7eba2f3bSAndroid Build Coastguard Worker // modifying the parsed fields so the change needs to be
157*7eba2f3bSAndroid Build Coastguard Worker // applied to the unparsed packet.
158*7eba2f3bSAndroid Build Coastguard Worker let mut packet_bytes = rf_reader.read().await?;
159*7eba2f3bSAndroid Build Coastguard Worker packet_bytes[0..2].copy_from_slice(&id.to_le_bytes());
160*7eba2f3bSAndroid Build Coastguard Worker
161*7eba2f3bSAndroid Build Coastguard Worker // Parse the input packet.
162*7eba2f3bSAndroid Build Coastguard Worker let packet = rf::RfPacket::parse(&packet_bytes)?;
163*7eba2f3bSAndroid Build Coastguard Worker
164*7eba2f3bSAndroid Build Coastguard Worker // Forward the packet to other devices.
165*7eba2f3bSAndroid Build Coastguard Worker controller_rf_tx.send(packet)?;
166*7eba2f3bSAndroid Build Coastguard Worker }
167*7eba2f3bSAndroid Build Coastguard Worker },
168*7eba2f3bSAndroid Build Coastguard Worker async {
169*7eba2f3bSAndroid Build Coastguard Worker loop {
170*7eba2f3bSAndroid Build Coastguard Worker // Forward the packet to the socket connection.
171*7eba2f3bSAndroid Build Coastguard Worker use pdl_runtime::Packet;
172*7eba2f3bSAndroid Build Coastguard Worker let packet = rf_rx
173*7eba2f3bSAndroid Build Coastguard Worker .recv()
174*7eba2f3bSAndroid Build Coastguard Worker .await
175*7eba2f3bSAndroid Build Coastguard Worker .ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
176*7eba2f3bSAndroid Build Coastguard Worker rf_writer.write(&packet.encode_to_vec()?).await?;
177*7eba2f3bSAndroid Build Coastguard Worker }
178*7eba2f3bSAndroid Build Coastguard Worker },
179*7eba2f3bSAndroid Build Coastguard Worker )
180*7eba2f3bSAndroid Build Coastguard Worker .await;
181*7eba2f3bSAndroid Build Coastguard Worker
182*7eba2f3bSAndroid Build Coastguard Worker result?;
183*7eba2f3bSAndroid Build Coastguard Worker Ok(())
184*7eba2f3bSAndroid Build Coastguard Worker }),
185*7eba2f3bSAndroid Build Coastguard Worker }
186*7eba2f3bSAndroid Build Coastguard Worker }
187*7eba2f3bSAndroid Build Coastguard Worker }
188*7eba2f3bSAndroid Build Coastguard Worker
189*7eba2f3bSAndroid Build Coastguard Worker struct Scene {
190*7eba2f3bSAndroid Build Coastguard Worker next_id: u16,
191*7eba2f3bSAndroid Build Coastguard Worker waker: Option<std::task::Waker>,
192*7eba2f3bSAndroid Build Coastguard Worker devices: [Option<Device>; MAX_DEVICES],
193*7eba2f3bSAndroid Build Coastguard Worker }
194*7eba2f3bSAndroid Build Coastguard Worker
195*7eba2f3bSAndroid Build Coastguard Worker impl Default for Scene {
default() -> Self196*7eba2f3bSAndroid Build Coastguard Worker fn default() -> Self {
197*7eba2f3bSAndroid Build Coastguard Worker const NONE: Option<Device> = None;
198*7eba2f3bSAndroid Build Coastguard Worker Scene { next_id: 0, waker: None, devices: [NONE; MAX_DEVICES] }
199*7eba2f3bSAndroid Build Coastguard Worker }
200*7eba2f3bSAndroid Build Coastguard Worker }
201*7eba2f3bSAndroid Build Coastguard Worker
202*7eba2f3bSAndroid Build Coastguard Worker impl Scene {
new() -> Scene203*7eba2f3bSAndroid Build Coastguard Worker fn new() -> Scene {
204*7eba2f3bSAndroid Build Coastguard Worker Default::default()
205*7eba2f3bSAndroid Build Coastguard Worker }
206*7eba2f3bSAndroid Build Coastguard Worker
wake(&mut self)207*7eba2f3bSAndroid Build Coastguard Worker fn wake(&mut self) {
208*7eba2f3bSAndroid Build Coastguard Worker if let Some(waker) = self.waker.take() {
209*7eba2f3bSAndroid Build Coastguard Worker waker.wake()
210*7eba2f3bSAndroid Build Coastguard Worker }
211*7eba2f3bSAndroid Build Coastguard Worker }
212*7eba2f3bSAndroid Build Coastguard Worker
add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id>213*7eba2f3bSAndroid Build Coastguard Worker fn add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id> {
214*7eba2f3bSAndroid Build Coastguard Worker for n in 0..MAX_DEVICES {
215*7eba2f3bSAndroid Build Coastguard Worker if self.devices[n].is_none() {
216*7eba2f3bSAndroid Build Coastguard Worker self.devices[n] = Some(builder(self.next_id));
217*7eba2f3bSAndroid Build Coastguard Worker self.next_id += 1;
218*7eba2f3bSAndroid Build Coastguard Worker self.wake();
219*7eba2f3bSAndroid Build Coastguard Worker return Ok(n as Id);
220*7eba2f3bSAndroid Build Coastguard Worker }
221*7eba2f3bSAndroid Build Coastguard Worker }
222*7eba2f3bSAndroid Build Coastguard Worker Err(anyhow::anyhow!("max number of connections reached"))
223*7eba2f3bSAndroid Build Coastguard Worker }
224*7eba2f3bSAndroid Build Coastguard Worker
disconnect(&mut self, n: usize)225*7eba2f3bSAndroid Build Coastguard Worker fn disconnect(&mut self, n: usize) {
226*7eba2f3bSAndroid Build Coastguard Worker let id = self.devices[n].as_ref().unwrap().id;
227*7eba2f3bSAndroid Build Coastguard Worker self.devices[n] = None;
228*7eba2f3bSAndroid Build Coastguard Worker for other_n in 0..MAX_DEVICES {
229*7eba2f3bSAndroid Build Coastguard Worker let Some(ref device) = self.devices[other_n] else { continue };
230*7eba2f3bSAndroid Build Coastguard Worker assert!(n != other_n);
231*7eba2f3bSAndroid Build Coastguard Worker device
232*7eba2f3bSAndroid Build Coastguard Worker .rf_tx
233*7eba2f3bSAndroid Build Coastguard Worker .send(
234*7eba2f3bSAndroid Build Coastguard Worker rf::DeactivateNotificationBuilder {
235*7eba2f3bSAndroid Build Coastguard Worker type_: rf::DeactivateType::Discovery,
236*7eba2f3bSAndroid Build Coastguard Worker reason: rf::DeactivateReason::RfLinkLoss,
237*7eba2f3bSAndroid Build Coastguard Worker sender: id,
238*7eba2f3bSAndroid Build Coastguard Worker receiver: device.id,
239*7eba2f3bSAndroid Build Coastguard Worker power_level: 255,
240*7eba2f3bSAndroid Build Coastguard Worker technology: rf::Technology::NfcA,
241*7eba2f3bSAndroid Build Coastguard Worker protocol: rf::Protocol::Undetermined,
242*7eba2f3bSAndroid Build Coastguard Worker }
243*7eba2f3bSAndroid Build Coastguard Worker .into(),
244*7eba2f3bSAndroid Build Coastguard Worker )
245*7eba2f3bSAndroid Build Coastguard Worker .expect("failed to send deactive notification")
246*7eba2f3bSAndroid Build Coastguard Worker }
247*7eba2f3bSAndroid Build Coastguard Worker }
248*7eba2f3bSAndroid Build Coastguard Worker
send(&self, packet: &rf::RfPacket) -> Result<()>249*7eba2f3bSAndroid Build Coastguard Worker fn send(&self, packet: &rf::RfPacket) -> Result<()> {
250*7eba2f3bSAndroid Build Coastguard Worker for n in 0..MAX_DEVICES {
251*7eba2f3bSAndroid Build Coastguard Worker let Some(ref device) = self.devices[n] else { continue };
252*7eba2f3bSAndroid Build Coastguard Worker if packet.get_sender() != device.id
253*7eba2f3bSAndroid Build Coastguard Worker && (packet.get_receiver() == u16::MAX || packet.get_receiver() == device.id)
254*7eba2f3bSAndroid Build Coastguard Worker {
255*7eba2f3bSAndroid Build Coastguard Worker device.rf_tx.send(packet.to_owned())?;
256*7eba2f3bSAndroid Build Coastguard Worker }
257*7eba2f3bSAndroid Build Coastguard Worker }
258*7eba2f3bSAndroid Build Coastguard Worker
259*7eba2f3bSAndroid Build Coastguard Worker Ok(())
260*7eba2f3bSAndroid Build Coastguard Worker }
261*7eba2f3bSAndroid Build Coastguard Worker }
262*7eba2f3bSAndroid Build Coastguard Worker
263*7eba2f3bSAndroid Build Coastguard Worker impl Future for Scene {
264*7eba2f3bSAndroid Build Coastguard Worker type Output = ();
265*7eba2f3bSAndroid Build Coastguard Worker
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>266*7eba2f3bSAndroid Build Coastguard Worker fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
267*7eba2f3bSAndroid Build Coastguard Worker for n in 0..MAX_DEVICES {
268*7eba2f3bSAndroid Build Coastguard Worker let dropped = match self.devices[n] {
269*7eba2f3bSAndroid Build Coastguard Worker Some(ref mut device) => match device.task.as_mut().poll(cx) {
270*7eba2f3bSAndroid Build Coastguard Worker Poll::Ready(Ok(_)) => unreachable!(),
271*7eba2f3bSAndroid Build Coastguard Worker Poll::Ready(Err(err)) => {
272*7eba2f3bSAndroid Build Coastguard Worker warn!("dropping device {}: {}", n, err);
273*7eba2f3bSAndroid Build Coastguard Worker true
274*7eba2f3bSAndroid Build Coastguard Worker }
275*7eba2f3bSAndroid Build Coastguard Worker Poll::Pending => false,
276*7eba2f3bSAndroid Build Coastguard Worker },
277*7eba2f3bSAndroid Build Coastguard Worker None => false,
278*7eba2f3bSAndroid Build Coastguard Worker };
279*7eba2f3bSAndroid Build Coastguard Worker if dropped {
280*7eba2f3bSAndroid Build Coastguard Worker self.disconnect(n)
281*7eba2f3bSAndroid Build Coastguard Worker }
282*7eba2f3bSAndroid Build Coastguard Worker }
283*7eba2f3bSAndroid Build Coastguard Worker self.waker = Some(cx.waker().clone());
284*7eba2f3bSAndroid Build Coastguard Worker Poll::Pending
285*7eba2f3bSAndroid Build Coastguard Worker }
286*7eba2f3bSAndroid Build Coastguard Worker }
287*7eba2f3bSAndroid Build Coastguard Worker
288*7eba2f3bSAndroid Build Coastguard Worker #[derive(FromArgs, Debug)]
289*7eba2f3bSAndroid Build Coastguard Worker /// Nfc emulator.
290*7eba2f3bSAndroid Build Coastguard Worker struct Opt {
291*7eba2f3bSAndroid Build Coastguard Worker #[argh(option)]
292*7eba2f3bSAndroid Build Coastguard Worker /// configure the TCP port for the NCI server.
293*7eba2f3bSAndroid Build Coastguard Worker nci_port: Option<u16>,
294*7eba2f3bSAndroid Build Coastguard Worker #[argh(option)]
295*7eba2f3bSAndroid Build Coastguard Worker /// configure a preexisting unix server fd for the NCI server.
296*7eba2f3bSAndroid Build Coastguard Worker nci_unix_fd: Option<i32>,
297*7eba2f3bSAndroid Build Coastguard Worker #[argh(option)]
298*7eba2f3bSAndroid Build Coastguard Worker /// configure the TCP port for the RF server.
299*7eba2f3bSAndroid Build Coastguard Worker rf_port: Option<u16>,
300*7eba2f3bSAndroid Build Coastguard Worker #[argh(option)]
301*7eba2f3bSAndroid Build Coastguard Worker /// configure a preexisting unix server fd for the RF server.
302*7eba2f3bSAndroid Build Coastguard Worker rf_unix_fd: Option<i32>,
303*7eba2f3bSAndroid Build Coastguard Worker }
304*7eba2f3bSAndroid Build Coastguard Worker
305*7eba2f3bSAndroid Build Coastguard Worker /// Abstraction between different server sources
306*7eba2f3bSAndroid Build Coastguard Worker enum Listener {
307*7eba2f3bSAndroid Build Coastguard Worker Tcp(TcpListener),
308*7eba2f3bSAndroid Build Coastguard Worker #[allow(unused)]
309*7eba2f3bSAndroid Build Coastguard Worker Unix(UnixListener),
310*7eba2f3bSAndroid Build Coastguard Worker }
311*7eba2f3bSAndroid Build Coastguard Worker
312*7eba2f3bSAndroid Build Coastguard Worker impl Listener {
accept_split( &self, ) -> Result<(Pin<Box<dyn AsyncRead>>, Pin<Box<dyn AsyncWrite>>, String)>313*7eba2f3bSAndroid Build Coastguard Worker async fn accept_split(
314*7eba2f3bSAndroid Build Coastguard Worker &self,
315*7eba2f3bSAndroid Build Coastguard Worker ) -> Result<(Pin<Box<dyn AsyncRead>>, Pin<Box<dyn AsyncWrite>>, String)> {
316*7eba2f3bSAndroid Build Coastguard Worker match self {
317*7eba2f3bSAndroid Build Coastguard Worker Listener::Tcp(tcp) => {
318*7eba2f3bSAndroid Build Coastguard Worker let (socket, addr) = tcp.accept().await?;
319*7eba2f3bSAndroid Build Coastguard Worker let (rx, tx) = socket.into_split();
320*7eba2f3bSAndroid Build Coastguard Worker Ok((Box::pin(rx), Box::pin(tx), format!("{}", addr)))
321*7eba2f3bSAndroid Build Coastguard Worker }
322*7eba2f3bSAndroid Build Coastguard Worker Listener::Unix(unix) => {
323*7eba2f3bSAndroid Build Coastguard Worker let (socket, addr) = unix.accept().await?;
324*7eba2f3bSAndroid Build Coastguard Worker let (rx, tx) = socket.into_split();
325*7eba2f3bSAndroid Build Coastguard Worker Ok((Box::pin(rx), Box::pin(tx), format!("{:?}", addr)))
326*7eba2f3bSAndroid Build Coastguard Worker }
327*7eba2f3bSAndroid Build Coastguard Worker }
328*7eba2f3bSAndroid Build Coastguard Worker }
329*7eba2f3bSAndroid Build Coastguard Worker }
330*7eba2f3bSAndroid Build Coastguard Worker
331*7eba2f3bSAndroid Build Coastguard Worker #[tokio::main]
run() -> Result<()>332*7eba2f3bSAndroid Build Coastguard Worker async fn run() -> Result<()> {
333*7eba2f3bSAndroid Build Coastguard Worker env_logger::init_from_env(
334*7eba2f3bSAndroid Build Coastguard Worker env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "debug"),
335*7eba2f3bSAndroid Build Coastguard Worker );
336*7eba2f3bSAndroid Build Coastguard Worker
337*7eba2f3bSAndroid Build Coastguard Worker let opt: Opt = argh::from_env();
338*7eba2f3bSAndroid Build Coastguard Worker
339*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = match (opt.nci_port, opt.nci_unix_fd) {
340*7eba2f3bSAndroid Build Coastguard Worker (None, Some(unix_fd)) => {
341*7eba2f3bSAndroid Build Coastguard Worker let owned_fd = inherited_fd::take_fd_ownership(unix_fd)?;
342*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = std::os::unix::net::UnixListener::from(owned_fd);
343*7eba2f3bSAndroid Build Coastguard Worker nci_listener.set_nonblocking(true)?;
344*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = UnixListener::from_std(nci_listener)?;
345*7eba2f3bSAndroid Build Coastguard Worker info!("Listening for NCI connections on fd {}", unix_fd);
346*7eba2f3bSAndroid Build Coastguard Worker Listener::Unix(nci_listener)
347*7eba2f3bSAndroid Build Coastguard Worker }
348*7eba2f3bSAndroid Build Coastguard Worker (port, None) => {
349*7eba2f3bSAndroid Build Coastguard Worker let port = port.unwrap_or(7000);
350*7eba2f3bSAndroid Build Coastguard Worker let nci_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
351*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = TcpListener::bind(nci_addr).await?;
352*7eba2f3bSAndroid Build Coastguard Worker info!("Listening for NCI connections at address {}", nci_addr);
353*7eba2f3bSAndroid Build Coastguard Worker Listener::Tcp(nci_listener)
354*7eba2f3bSAndroid Build Coastguard Worker }
355*7eba2f3bSAndroid Build Coastguard Worker _ => anyhow::bail!("Specify at most one of `--nci-port` and `--nci-unix-fd`."),
356*7eba2f3bSAndroid Build Coastguard Worker };
357*7eba2f3bSAndroid Build Coastguard Worker
358*7eba2f3bSAndroid Build Coastguard Worker let rf_listener = match (opt.rf_port, opt.rf_unix_fd) {
359*7eba2f3bSAndroid Build Coastguard Worker (None, Some(unix_fd)) => {
360*7eba2f3bSAndroid Build Coastguard Worker let owned_fd = inherited_fd::take_fd_ownership(unix_fd)?;
361*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = std::os::unix::net::UnixListener::from(owned_fd);
362*7eba2f3bSAndroid Build Coastguard Worker nci_listener.set_nonblocking(true)?;
363*7eba2f3bSAndroid Build Coastguard Worker let nci_listener = UnixListener::from_std(nci_listener)?;
364*7eba2f3bSAndroid Build Coastguard Worker info!("Listening for RF connections on fd {}", unix_fd);
365*7eba2f3bSAndroid Build Coastguard Worker Listener::Unix(nci_listener)
366*7eba2f3bSAndroid Build Coastguard Worker }
367*7eba2f3bSAndroid Build Coastguard Worker (port, None) => {
368*7eba2f3bSAndroid Build Coastguard Worker let port = port.unwrap_or(7001);
369*7eba2f3bSAndroid Build Coastguard Worker let rf_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
370*7eba2f3bSAndroid Build Coastguard Worker let rf_listener = TcpListener::bind(rf_addr).await?;
371*7eba2f3bSAndroid Build Coastguard Worker info!("Listening for RF connections at address {}", rf_addr);
372*7eba2f3bSAndroid Build Coastguard Worker Listener::Tcp(rf_listener)
373*7eba2f3bSAndroid Build Coastguard Worker }
374*7eba2f3bSAndroid Build Coastguard Worker _ => anyhow::bail!("Specify at most one of `--rf-port` and `--rf-unix-fd`"),
375*7eba2f3bSAndroid Build Coastguard Worker };
376*7eba2f3bSAndroid Build Coastguard Worker
377*7eba2f3bSAndroid Build Coastguard Worker let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
378*7eba2f3bSAndroid Build Coastguard Worker let mut scene = Scene::new();
379*7eba2f3bSAndroid Build Coastguard Worker loop {
380*7eba2f3bSAndroid Build Coastguard Worker select! {
381*7eba2f3bSAndroid Build Coastguard Worker result = nci_listener.accept_split() => {
382*7eba2f3bSAndroid Build Coastguard Worker let (socket_rx, socket_tx, addr) = result?;
383*7eba2f3bSAndroid Build Coastguard Worker info!("Incoming NCI connection from {}", addr);
384*7eba2f3bSAndroid Build Coastguard Worker match scene.add_device(|id| Device::nci(id, socket_rx, socket_tx, rf_tx.clone())) {
385*7eba2f3bSAndroid Build Coastguard Worker Ok(id) => info!("Accepted NCI connection from {} in slot {}", addr, id),
386*7eba2f3bSAndroid Build Coastguard Worker Err(err) => error!("Failed to accept NCI connection from {}: {}", addr, err)
387*7eba2f3bSAndroid Build Coastguard Worker }
388*7eba2f3bSAndroid Build Coastguard Worker },
389*7eba2f3bSAndroid Build Coastguard Worker result = rf_listener.accept_split() => {
390*7eba2f3bSAndroid Build Coastguard Worker let (socket_rx, socket_tx, addr) = result?;
391*7eba2f3bSAndroid Build Coastguard Worker info!("Incoming RF connection from {}", addr);
392*7eba2f3bSAndroid Build Coastguard Worker match scene.add_device(|id| Device::rf(id, socket_rx, socket_tx, rf_tx.clone())) {
393*7eba2f3bSAndroid Build Coastguard Worker Ok(id) => info!("Accepted RF connection from {} in slot {}", addr, id),
394*7eba2f3bSAndroid Build Coastguard Worker Err(err) => error!("Failed to accept RF connection from {}: {}", addr, err)
395*7eba2f3bSAndroid Build Coastguard Worker }
396*7eba2f3bSAndroid Build Coastguard Worker },
397*7eba2f3bSAndroid Build Coastguard Worker _ = &mut scene => (),
398*7eba2f3bSAndroid Build Coastguard Worker result = rf_rx.recv() => {
399*7eba2f3bSAndroid Build Coastguard Worker let packet = result.ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
400*7eba2f3bSAndroid Build Coastguard Worker scene.send(&packet)?
401*7eba2f3bSAndroid Build Coastguard Worker }
402*7eba2f3bSAndroid Build Coastguard Worker }
403*7eba2f3bSAndroid Build Coastguard Worker }
404*7eba2f3bSAndroid Build Coastguard Worker }
405*7eba2f3bSAndroid Build Coastguard Worker
main() -> Result<()>406*7eba2f3bSAndroid Build Coastguard Worker fn main() -> Result<()> {
407*7eba2f3bSAndroid Build Coastguard Worker // Safety: First function call in the `main` function, before any other library calls
408*7eba2f3bSAndroid Build Coastguard Worker unsafe { inherited_fd::init_once()? };
409*7eba2f3bSAndroid Build Coastguard Worker run()
410*7eba2f3bSAndroid Build Coastguard Worker }
411