• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::convert::TryFrom;
2 use std::future::Future;
3 use std::pin::Pin;
4 use std::task::{self, Poll};
5 
6 use crate::ec::PrivateKey;
7 use crate::packets::{hci, lmp};
8 
9 pub trait Context {
poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C>10     fn poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C>;
poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P>11     fn poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P>;
12 
send_hci_event<E: Into<hci::EventPacket>>(&self, event: E)13     fn send_hci_event<E: Into<hci::EventPacket>>(&self, event: E);
send_lmp_packet<P: Into<lmp::PacketPacket>>(&self, packet: P)14     fn send_lmp_packet<P: Into<lmp::PacketPacket>>(&self, packet: P);
15 
peer_address(&self) -> hci::Address16     fn peer_address(&self) -> hci::Address;
peer_handle(&self) -> u1617     fn peer_handle(&self) -> u16;
18 
peer_extended_features(&self, _features_page: u8) -> Option<u64>19     fn peer_extended_features(&self, _features_page: u8) -> Option<u64> {
20         None
21     }
22 
extended_features(&self, features_page: u8) -> u6423     fn extended_features(&self, features_page: u8) -> u64;
24 
receive_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> ReceiveFuture<'_, Self, C>25     fn receive_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> ReceiveFuture<'_, Self, C> {
26         ReceiveFuture(Self::poll_hci_command, self)
27     }
28 
receive_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> ReceiveFuture<'_, Self, P>29     fn receive_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> ReceiveFuture<'_, Self, P> {
30         ReceiveFuture(Self::poll_lmp_packet, self)
31     }
32 
send_accepted_lmp_packet<P: Into<lmp::PacketPacket>>( &self, packet: P, ) -> SendAcceptedLmpPacketFuture<'_, Self>33     fn send_accepted_lmp_packet<P: Into<lmp::PacketPacket>>(
34         &self,
35         packet: P,
36     ) -> SendAcceptedLmpPacketFuture<'_, Self> {
37         let packet = packet.into();
38         let opcode = packet.get_opcode();
39         self.send_lmp_packet(packet);
40 
41         SendAcceptedLmpPacketFuture(self, opcode)
42     }
43 
get_private_key(&self) -> Option<PrivateKey>44     fn get_private_key(&self) -> Option<PrivateKey> {
45         None
46     }
47 
set_private_key(&self, _key: &PrivateKey)48     fn set_private_key(&self, _key: &PrivateKey) {}
49 }
50 
51 /// Future for Context::receive_hci_command and Context::receive_lmp_packet
52 pub struct ReceiveFuture<'a, C: ?Sized, P>(fn(&'a C) -> Poll<P>, &'a C);
53 
54 impl<'a, C, O> Future for ReceiveFuture<'a, C, O>
55 where
56     C: Context,
57 {
58     type Output = O;
59 
poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output>60     fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
61         (self.0)(self.1)
62     }
63 }
64 
65 /// Future for Context::receive_hci_command and Context::receive_lmp_packet
66 pub struct SendAcceptedLmpPacketFuture<'a, C: ?Sized>(&'a C, lmp::Opcode);
67 
68 impl<'a, C> Future for SendAcceptedLmpPacketFuture<'a, C>
69 where
70     C: Context,
71 {
72     type Output = Result<(), u8>;
73 
poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output>74     fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
75         let accepted = self.0.poll_lmp_packet::<lmp::AcceptedPacket>();
76         if let Poll::Ready(accepted) = accepted {
77             if accepted.get_accepted_opcode() == self.1 {
78                 return Poll::Ready(Ok(()));
79             }
80         }
81 
82         let not_accepted = self.0.poll_lmp_packet::<lmp::NotAcceptedPacket>();
83         if let Poll::Ready(not_accepted) = not_accepted {
84             if not_accepted.get_not_accepted_opcode() == self.1 {
85                 return Poll::Ready(Err(not_accepted.get_error_code()));
86             }
87         }
88 
89         Poll::Pending
90     }
91 }
92 
93 pub mod authentication;
94 mod encryption;
95 pub mod features;
96 pub mod legacy_pairing;
97 pub mod secure_simple_pairing;
98 
99 macro_rules! run_procedures {
100     ($(
101         $idx:tt { $procedure:expr }
102     )+) => {{
103         $(
104             let $idx = async { loop { $procedure.await; } };
105             crate::future::pin!($idx);
106         )+
107 
108         use std::future::Future;
109         use std::pin::Pin;
110         use std::task::{Poll, Context};
111 
112         #[allow(non_camel_case_types)]
113         struct Join<'a, $($idx),+> {
114             $($idx: Pin<&'a mut $idx>),+
115         }
116 
117         #[allow(non_camel_case_types)]
118         impl<'a, $($idx: Future<Output = ()>),+> Future for Join<'a, $($idx),+> {
119             type Output = ();
120 
121             fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
122                 $(assert!(self.$idx.as_mut().poll(cx).is_pending());)+
123                 Poll::Pending
124             }
125         }
126 
127         Join {
128             $($idx),+
129         }.await
130     }}
131 }
132 
run(ctx: impl Context)133 pub async fn run(ctx: impl Context) {
134     run_procedures! {
135         a { authentication::initiate(&ctx) }
136         b { authentication::respond(&ctx) }
137         c { encryption::initiate(&ctx) }
138         d { encryption::respond(&ctx) }
139         e { features::respond(&ctx) }
140     }
141 }
142