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())
    }
}