1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
//! The Logical Link Control and Adaptation Protocol (L2CAP). //! //! Note that LE and Classic Bluetooth differ quite a bit on this layer, even though they're //! supposed to share L2CAP. We're only implementing the LE bits. //! //! L2CAP provides "channels" to the upper layers that are mapped to the physical transport below //! the L2CAP layer (the LE Link Layer or whatever Classic Bluetooth does). A channel is identified //! by a 16-bit ID (also see [`Channel`]), a few of which are reserved. //! //! A minimal implementation for Classic Bluetooth must support the L2CAP signaling channel //! (`0x0001`). A minimal implementation for BLE has to support the L2CAP LE signaling channel //! (`0x0005`), the Attribute Protocol channel (`0x0004`), and the LE Security Manager channel //! (`0x0006`). //! //! Establishing new connection-oriented channels, as well as transferring data over the //! connectionless channel (`0x0002`) makes use of *Protocol/Service Multiplexers* (PSMs), which are //! numbers identifying the protocol or service to use. These numbers are either defined by the //! Bluetooth SIG or allocated dynamically for use with the Service Discovery Protocol (SDP). The //! preallocated numbers are hosted online [here][l2c]. //! //! [`Channel`]: struct.Channel.html //! [l2c]: https://www.bluetooth.com/specifications/assigned-numbers/logical-link-control use { crate::{ att::{AttributeProvider, AttributeServer, NoAttributes}, bytes::*, link::{ data::Llid, queue::{Consume, Producer}, MIN_PAYLOAD_BUF, }, security_manager::{NoSecurity, SecurityLevel, SecurityManager}, utils::HexSlice, Error, }, core::fmt, }; /// An L2CAP channel identifier (CID). /// /// Channels are basically like TCP ports. A `Protocol` can listen on a channel and is connected to /// a channel on the other device to which all responses are addressed. /// /// A number of channel identifiers are reserved for predefined functions: /// /// * `0x0000`: The null identifier. Must never be used as a destination endpoint. /// * `0x0001`: L2CAP signaling channel (Classic Bluetooth only). /// * `0x0002`: Connectionless channel (Classic Bluetooth only). /// * `0x0003`: AMP manager (not relevant for Classic and LE Bluetooth). /// * `0x0004`: Attribute protocol (ATT). BLE only. /// * `0x0005`: LE L2CAP signaling channel. /// * `0x0006`: LE Security Manager protocol. /// * `0x0007`: Classic Bluetooth Security Manager protocol. /// * `0x0008`-`0x003E`: Reserved. /// * `0x003F`: AMP test manager (not relevant for Classic and LE Bluetooth). /// /// For BLE, channels `0x0040`-`0x007F` are dynamically allocated, while `0x0080` and beyond are /// reserved and should not be used (as of *Bluetooth 4.2*). /// /// For classic Bluetooth, all channels `0x0040`-`0xFFFF` are available for dynamic allocation. #[derive(PartialEq, Eq, Hash, Copy, Clone)] pub struct Channel(u16); impl Channel { /// The null channel identifier. Must not be used as a destination endpoint. pub const NULL: Self = Channel(0x0000); /// The channel used by the Attribute Protocol (ATT). pub const ATT: Self = Channel(0x0004); /// LE L2CAP signaling channel (connectionless). pub const LE_SIGNALING: Self = Channel(0x0005); /// LE Security Manager channel. pub const LE_SECURITY_MANAGER: Self = Channel(0x0006); /// Returns the channel identifier (CID) as a raw `u16`. pub fn as_raw(&self) -> u16 { self.0 } /// Returns whether this channel is connection-oriented. /// /// L2CAP PDUs addressed to connection-oriented channels are called *B-frames* if the channel is /// in "Basic Mode", and can be either *S-frames* or *I-frames* if the channel is in /// retransmission/flow control/streaming modes. pub fn is_connection_oriented(&self) -> bool { !self.is_connectionless() } /// Returns whether this channel is connectionless. /// /// L2CAP PDUs addressed to connectionless channels are called *G-frames*. pub fn is_connectionless(&self) -> bool { match self.0 { 0x0002 | 0x0001 | 0x0005 => true, _ => false, } } } impl fmt::Debug for Channel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:#06X}", self.0) } } impl FromBytes<'_> for Channel { fn from_bytes(bytes: &mut ByteReader) -> Result<Self, Error> { Ok(Channel(bytes.read_u16_le()?)) } } impl ToBytes for Channel { fn to_bytes(&self, writer: &mut ByteWriter) -> Result<(), Error> { writer.write_u16_le(self.0) } } /// Trait for L2CAP channel mappers that provide access to the protocol or service behind a CID. pub trait ChannelMapper { /// Look up what's connected to `channel` (eg. the `Protocol` to which to forward). fn lookup(&mut self, channel: Channel) -> Option<ChannelData>; } /// Data associated with a connected L2CAP channel. pub struct ChannelData<'a> { /// Channel to which responses should be addressed. /// /// For fixed, predefined channels, this is always the same value for both devices, but /// dynamically allocated channels can have different CIDs on both devices. response_channel: Channel, /// The protocol listening on this channel. protocol: &'a mut ProtocolObj, rsp_pdu: u8, } impl<'a> ChannelData<'a> { fn new<P: Protocol>(response_channel: Channel, protocol: &'a mut P) -> Self { assert!( usize::from(P::RSP_PDU_SIZE + Header::SIZE) <= MIN_PAYLOAD_BUF, "protocol min PDU is smaller than data channel PDU (L2CAP reassembly NYI)" ); ChannelData { response_channel, rsp_pdu: P::RSP_PDU_SIZE, protocol, } } /// Returns the `Channel` to which the response should be sent. pub fn response_channel(&self) -> Channel { self.response_channel } /// Returns the protocol response size in Bytes. /// /// This is the minimal size in Bytes the protocol needs to have provided for its responses. /// `Protocol` implementations may make use of additional space as well, but this is the very /// minimum. /// /// The L2CAP implementation will not forward PDUs to the protocol unless this amount of space /// is available in the TX buffer. pub fn response_pdu_size(&self) -> u8 { self.rsp_pdu } /// Returns the protocol connected to the channel. pub fn protocol(&mut self) -> &mut ProtocolObj { self.protocol } } /// A fixed BLE channel map that provides only the required channel endpoints and does not allow /// dynamic channels. /// /// The channels are mapped as follows (no other channels are supported): /// /// * `0x0004`: Attribute protocol (ATT). /// * `0x0005`: LE L2CAP signaling channel. /// * `0x0006`: LE Security Manager protocol. pub struct BleChannelMap<A: AttributeProvider, S: SecurityLevel> { att: AttributeServer<A>, sm: SecurityManager<S>, } impl BleChannelMap<NoAttributes, NoSecurity> { /// Creates a new channel map with no backing data for the connected protocols. /// /// This means: /// * The attribute server on channel `0x0004` will host an empty attribute set. /// * The security manager on channel `0x0006` will not support pairing or any security. pub fn empty() -> Self { Self { att: AttributeServer::new(NoAttributes), sm: SecurityManager::no_security(), } } } impl<A: AttributeProvider> BleChannelMap<A, NoSecurity> { pub fn with_attributes(att: A) -> Self { Self { att: AttributeServer::new(att), sm: SecurityManager::no_security(), } } } impl<A: AttributeProvider, S: SecurityLevel> ChannelMapper for BleChannelMap<A, S> { fn lookup(&mut self, channel: Channel) -> Option<ChannelData> { match channel { Channel::ATT => Some(ChannelData::new(Channel::ATT, &mut self.att)), Channel::LE_SECURITY_MANAGER => { Some(ChannelData::new(Channel::LE_SECURITY_MANAGER, &mut self.sm)) } // FIXME implement the LE Signaling Channel _ => None, } } } /// Trait for protocols that sit on top of L2CAP (object-safe part). /// /// A protocol can be connected to an L2CAP channel via a `ChannelMapper`. pub trait ProtocolObj { /// Process a message sent to the protocol. /// /// The message is reassembled by L2CAP already, and the `responder` is guaranteed to fit a /// protocol payload of at least `Protocol::RSP_PDU_SIZE` Bytes, as defined by the protocol. /// /// # Errors /// /// This method should only return an error when a critical problem occurs that can not be /// recovered from and that can not be reported back to the connected device using the protocol. /// This means that only things like unrecoverable protocol parsing errors should return an /// error here. fn process_message(&mut self, message: &[u8], responder: L2CAPResponder) -> Result<(), Error>; } /// Trait for protocols that sit on top of L2CAP (non-object-safe part). /// /// This extends the `ProtocolObj` trait with other protocol properties. pub trait Protocol: ProtocolObj { /// Minimum size needed by PDUs sent by this protocol. /// /// Incoming PDUs will only be forwarded to the protocol if there is at least this much space in /// the TX buffer. const RSP_PDU_SIZE: u8; } /// Header used by *all* L2CAP PDUs. #[derive(Debug)] struct Header { /// Length of the payload following the length and channel fields (after reassembly). length: u16, /// Destination endpoint of the PDU. channel: Channel, } impl Header { /// The size of an L2CAP message header in Bytes. const SIZE: u8 = 2 + 2; } impl<'a> FromBytes<'a> for Header { fn from_bytes(bytes: &mut ByteReader<'a>) -> Result<Self, Error> { let length = bytes.read_u16_le()?; let channel = Channel::from_bytes(bytes)?; Ok(Self { length, channel }) } } impl ToBytes for Header { fn to_bytes(&self, writer: &mut ByteWriter) -> Result<(), Error> { writer.write_u16_le(self.length)?; writer.write_u16_le(self.channel.as_raw())?; Ok(()) } } struct Message<P> { header: Header, payload: P, } impl<'a, P: FromBytes<'a>> FromBytes<'a> for Message<P> { fn from_bytes(bytes: &mut ByteReader<'a>) -> Result<Self, Error> { let header = Header::from_bytes(bytes)?; assert_eq!( header.length as usize, bytes.bytes_left(), "L2CAP reassembly not yet implemented" ); Ok(Self { header, payload: P::from_bytes(bytes)?, }) } } impl<P: ToBytes> ToBytes for Message<P> { fn to_bytes(&self, writer: &mut ByteWriter) -> Result<(), Error> { self.header.to_bytes(writer)?; self.payload.to_bytes(writer)?; Ok(()) } } /// L2CAP channel manager and responder. pub struct L2CAPState<M: ChannelMapper> { mapper: M, } impl<M: ChannelMapper> L2CAPState<M> { pub fn new(mapper: M) -> Self { Self { mapper } } /// Dispatches a fully reassembled L2CAP message to the protocol listening on the addressed /// channel. fn dispatch(&mut self, channel: Channel, payload: &[u8], tx: &mut Producer) -> Consume<()> { if let Some(mut chdata) = self.mapper.lookup(channel) { let free = tx.free_space(); let needed = usize::from(chdata.response_pdu_size() + Header::SIZE); if free < needed { debug!("{} free bytes, need {}; waiting", free, needed); return Consume::never(Ok(())); } let resp_channel = chdata.response_channel(); Consume::always(chdata.protocol().process_message( payload, L2CAPResponder { tx, channel: resp_channel, }, )) } else { warn!( "ignoring message sent to unconnected channel {:?}: {:?}", channel, HexSlice(payload) ); Consume::always(Ok(())) } } /// Process the start of a new L2CAP message (or a complete, unfragmented message). pub fn process_start(&mut self, message: &[u8], tx: &mut Producer) -> Consume<()> { let msg = match Message::<&[u8]>::from_bytes(&mut ByteReader::new(message)) { Ok(msg) => msg, Err(e) => return Consume::always(Err(e)), }; if usize::from(msg.header.length) != msg.payload.len() { // Lengths mismatch => Reassembly needed unimplemented!("L2CAP reassembly"); } self.dispatch(msg.header.channel, msg.payload, tx) } /// Process continuation of an L2CAP message. pub fn process_cont(&mut self, _data: &[u8], _tx: &mut Producer) -> Consume<()> { unimplemented!("reassembly") } } pub struct L2CAPResponder<'a> { /// Data PDU channel. tx: &'a mut Producer, /// Channel to which the response will be addressed. channel: Channel, } impl<'a> L2CAPResponder<'a> { /// Enqueues an L2CAP message to be sent over the data connection. /// /// L2CAP header (including the destination endpoint's channel) and the data channel PDU header /// will be added automatically. /// /// This will fail if there's not enough space left in the TX queue. pub fn respond<P: ToBytes>(&mut self, payload: P) -> Result<(), Error> { self.respond_with(|writer| payload.to_bytes(writer)) } /// Respond with an L2CAP message encoded by a closure. /// /// L2CAP header and data channel PDU header will be added automatically. The closure `f` only /// has to write the protocol PDU to transmit over L2CAP. /// /// The L2CAP implementation will ensure that there are at least `Protocol::RSP_PDU_SIZE` Bytes /// available in the `ByteWriter` passed to the closure. pub fn respond_with<T, E>( &mut self, f: impl FnOnce(&mut ByteWriter) -> Result<T, E>, ) -> Result<T, E> where E: From<Error>, { // FIXME automatic fragmentation is not implemented // The payload length goes into the header, so we have to skip that part and write it later let channel = self.channel; let mut r = None; self.tx.produce_with(|writer| -> Result<_, E> { let mut header_writer = writer.split_off(usize::from(Header::SIZE))?; let left = writer.space_left(); r = Some(f(writer)?); let used = left - writer.space_left(); assert!(used < 0xFFFF); Header { length: used as u16, channel: channel, } .to_bytes(&mut header_writer)?; assert_eq!(header_writer.space_left(), 0); Ok(Llid::DataStart) })?; Ok(r.unwrap()) } }