Home | History | Annotate | Download | only in src
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014 Google, Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #define LOG_TAG "bt_hci_packet_fragmenter"
     20 
     21 #include "packet_fragmenter.h"
     22 
     23 #include <assert.h>
     24 #include <string.h>
     25 
     26 #include "bt_target.h"
     27 #include "buffer_allocator.h"
     28 #include "device/include/controller.h"
     29 #include "hci_internals.h"
     30 #include "osi/include/hash_functions.h"
     31 #include "osi/include/hash_map.h"
     32 #include "osi/include/log.h"
     33 #include "osi/include/osi.h"
     34 
     35 #define APPLY_CONTINUATION_FLAG(handle) (((handle) & 0xCFFF) | 0x1000)
     36 #define APPLY_START_FLAG(handle) (((handle) & 0xCFFF) | 0x2000)
     37 #define SUB_EVENT(event) ((event) & MSG_SUB_EVT_MASK)
     38 #define GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
     39 
     40 #define HANDLE_MASK 0x0FFF
     41 #define START_PACKET_BOUNDARY 2
     42 #define CONTINUATION_PACKET_BOUNDARY 1
     43 #define L2CAP_HEADER_SIZE       4
     44 
     45 // TODO(zachoverflow): find good value for this
     46 #define NUMBER_OF_BUCKETS 42
     47 
     48 // Our interface and callbacks
     49 static const packet_fragmenter_t interface;
     50 static const allocator_t *buffer_allocator;
     51 static const controller_t *controller;
     52 static const packet_fragmenter_callbacks_t *callbacks;
     53 
     54 static hash_map_t *partial_packets;
     55 
     56 static void init(const packet_fragmenter_callbacks_t *result_callbacks) {
     57   callbacks = result_callbacks;
     58   partial_packets = hash_map_new(NUMBER_OF_BUCKETS, hash_function_naive, NULL, NULL, NULL);
     59 }
     60 
     61 static void cleanup() {
     62   if (partial_packets)
     63     hash_map_free(partial_packets);
     64 }
     65 
     66 static void fragment_and_dispatch(BT_HDR *packet) {
     67   assert(packet != NULL);
     68 
     69   uint16_t event = packet->event & MSG_EVT_MASK;
     70   uint8_t *stream = packet->data + packet->offset;
     71 
     72   // We only fragment ACL packets
     73   if (event != MSG_STACK_TO_HC_HCI_ACL) {
     74     callbacks->fragmented(packet, true);
     75     return;
     76   }
     77 
     78   uint16_t max_data_size =
     79     SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
     80       controller->get_acl_data_size_classic() :
     81       controller->get_acl_data_size_ble();
     82 
     83   uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
     84   uint16_t remaining_length = packet->len;
     85 
     86   uint16_t continuation_handle;
     87   STREAM_TO_UINT16(continuation_handle, stream);
     88   continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);
     89 
     90   while (remaining_length > max_packet_size) {
     91     // Make sure we use the right ACL packet size
     92     stream = packet->data + packet->offset;
     93     STREAM_SKIP_UINT16(stream);
     94     UINT16_TO_STREAM(stream, max_data_size);
     95 
     96     packet->len = max_packet_size;
     97     callbacks->fragmented(packet, false);
     98 
     99     packet->offset += max_data_size;
    100     remaining_length -= max_data_size;
    101     packet->len = remaining_length;
    102 
    103     // Write the ACL header for the next fragment
    104     stream = packet->data + packet->offset;
    105     UINT16_TO_STREAM(stream, continuation_handle);
    106     UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);
    107 
    108     // Apparently L2CAP can set layer_specific to a max number of segments to transmit
    109     if (packet->layer_specific) {
    110       packet->layer_specific--;
    111 
    112       if (packet->layer_specific == 0) {
    113         packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
    114         callbacks->transmit_finished(packet, false);
    115         return;
    116       }
    117     }
    118   }
    119 
    120   callbacks->fragmented(packet, true);
    121 }
    122 
    123 static bool check_uint16_overflow(uint16_t a, uint16_t b) {
    124   return (UINT16_MAX - a) < b;
    125 }
    126 
    127 static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) {
    128   if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
    129     uint8_t *stream = packet->data;
    130     uint16_t handle;
    131     uint16_t l2cap_length;
    132     uint16_t acl_length;
    133 
    134     STREAM_TO_UINT16(handle, stream);
    135     STREAM_TO_UINT16(acl_length, stream);
    136     STREAM_TO_UINT16(l2cap_length, stream);
    137 
    138     assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
    139 
    140     uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle);
    141     handle = handle & HANDLE_MASK;
    142 
    143     BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle);
    144 
    145     if (boundary_flag == START_PACKET_BOUNDARY) {
    146       if (partial_packet) {
    147         LOG_WARN(LOG_TAG, "%s found unfinished packet for handle with start packet. Dropping old.", __func__);
    148 
    149         hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
    150         buffer_allocator->free(partial_packet);
    151       }
    152 
    153       if (acl_length < L2CAP_HEADER_SIZE) {
    154         LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.", __func__, packet->len, L2CAP_HEADER_SIZE);
    155         buffer_allocator->free(packet);
    156         return;
    157       }
    158 
    159       uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;
    160 
    161       // Check for buffer overflow and that the full packet size + BT_HDR size is less than
    162       // the max buffer size
    163       if (check_uint16_overflow(l2cap_length, (L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE)) ||
    164           ((full_length + sizeof(BT_HDR)) > BT_DEFAULT_BUFFER_SIZE)) {
    165         LOG_ERROR(LOG_TAG, "%s L2CAP packet has invalid length (%d). Dropping it.", __func__, l2cap_length);
    166         buffer_allocator->free(packet);
    167         return;
    168       }
    169 
    170       if (full_length <= packet->len) {
    171         if (full_length < packet->len)
    172           LOG_WARN(LOG_TAG, "%s found l2cap full length %d less than the hci length %d.", __func__, l2cap_length, packet->len);
    173 
    174         callbacks->reassembled(packet);
    175         return;
    176       }
    177 
    178       partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR));
    179       partial_packet->event = packet->event;
    180       partial_packet->len = full_length;
    181       partial_packet->offset = packet->len;
    182 
    183       memcpy(partial_packet->data, packet->data, packet->len);
    184 
    185       // Update the ACL data size to indicate the full expected length
    186       stream = partial_packet->data;
    187       STREAM_SKIP_UINT16(stream); // skip the handle
    188       UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE);
    189 
    190       hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet);
    191       // Free the old packet buffer, since we don't need it anymore
    192       buffer_allocator->free(packet);
    193     } else {
    194       if (!partial_packet) {
    195         LOG_WARN(LOG_TAG, "%s got continuation for unknown packet. Dropping it.", __func__);
    196         buffer_allocator->free(packet);
    197         return;
    198       }
    199 
    200       packet->offset = HCI_ACL_PREAMBLE_SIZE;
    201       uint16_t projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE);
    202       if (projected_offset > partial_packet->len) { // len stores the expected length
    203         LOG_WARN(LOG_TAG, "%s got packet which would exceed expected length of %d. Truncating.", __func__, partial_packet->len);
    204         packet->len = partial_packet->len - partial_packet->offset;
    205         projected_offset = partial_packet->len;
    206       }
    207 
    208       memcpy(
    209         partial_packet->data + partial_packet->offset,
    210         packet->data + packet->offset,
    211         packet->len - packet->offset
    212       );
    213 
    214       // Free the old packet buffer, since we don't need it anymore
    215       buffer_allocator->free(packet);
    216       partial_packet->offset = projected_offset;
    217 
    218       if (partial_packet->offset == partial_packet->len) {
    219         hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
    220         partial_packet->offset = 0;
    221         callbacks->reassembled(partial_packet);
    222       }
    223     }
    224   } else {
    225     callbacks->reassembled(packet);
    226   }
    227 }
    228 
    229 static const packet_fragmenter_t interface = {
    230   init,
    231   cleanup,
    232 
    233   fragment_and_dispatch,
    234   reassemble_and_dispatch
    235 };
    236 
    237 const packet_fragmenter_t *packet_fragmenter_get_interface() {
    238   controller = controller_get_interface();
    239   buffer_allocator = buffer_allocator_get_interface();
    240   return &interface;
    241 }
    242 
    243 const packet_fragmenter_t *packet_fragmenter_get_test_interface(
    244     const controller_t *controller_interface,
    245     const allocator_t *buffer_allocator_interface) {
    246   controller = controller_interface;
    247   buffer_allocator = buffer_allocator_interface;
    248   return &interface;
    249 }
    250