1fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson/****************************************************************************** 2fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * 3fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * Copyright (C) 2014 Google, Inc. 4fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * 5fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * Licensed under the Apache License, Version 2.0 (the "License"); 6fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * you may not use this file except in compliance with the License. 7fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * You may obtain a copy of the License at: 8fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * 9fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * http://www.apache.org/licenses/LICENSE-2.0 10fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * 11fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * Unless required by applicable law or agreed to in writing, software 12fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * distributed under the License is distributed on an "AS IS" BASIS, 13fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * See the License for the specific language governing permissions and 15fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * limitations under the License. 16fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson * 17fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson ******************************************************************************/ 18fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 194a04780fd423d3c6673e9355af90ab60f31d9533Zach Johnson#define LOG_TAG "bt_hci_packet_fragmenter" 20fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 21fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include <assert.h> 223e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6Etan Cohen#include <string.h> 23fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 24bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "buffer_allocator.h" 2579ecab5d0418fde77e9afcdd451bd713af73e180Chris Manton#include "device/include/controller.h" 260f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/hash_map.h" 27fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include "hci_internals.h" 28fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include "hci_layer.h" 29fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include "packet_fragmenter.h" 300f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/osi.h" 3105d0366413bedc16b4189b9e74395fe4b11ba41aZach Johnson#include "osi/include/hash_functions.h" 3244802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 33fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 34fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define APPLY_CONTINUATION_FLAG(handle) (((handle) & 0xCFFF) | 0x1000) 35fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define APPLY_START_FLAG(handle) (((handle) & 0xCFFF) | 0x2000) 36fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define SUB_EVENT(event) ((event) & MSG_SUB_EVT_MASK) 37fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003) 38fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 39fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define HANDLE_MASK 0x0FFF 40fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define START_PACKET_BOUNDARY 2 41fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define CONTINUATION_PACKET_BOUNDARY 1 42fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define L2CAP_HEADER_SIZE 4 43fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 44fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson// TODO(zachoverflow): find good value for this 45fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#define NUMBER_OF_BUCKETS 42 46fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 47fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson// Our interface and callbacks 48bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const packet_fragmenter_t interface; 49bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const allocator_t *buffer_allocator; 50bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const controller_t *controller; 51fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnsonstatic const packet_fragmenter_callbacks_t *callbacks; 52fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 53fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnsonstatic hash_map_t *partial_packets; 54fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 55bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic void init(const packet_fragmenter_callbacks_t *result_callbacks) { 56fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson callbacks = result_callbacks; 57aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson partial_packets = hash_map_new(NUMBER_OF_BUCKETS, hash_function_naive, NULL, NULL, NULL); 581e0ede7f5522a853fc39d4f183e508ed38f01636Zach Johnson} 591e0ede7f5522a853fc39d4f183e508ed38f01636Zach Johnson 601e0ede7f5522a853fc39d4f183e508ed38f01636Zach Johnsonstatic void cleanup() { 61fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (partial_packets) 62fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson hash_map_free(partial_packets); 63fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson} 64fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 65fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnsonstatic void fragment_and_dispatch(BT_HDR *packet) { 66fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson assert(packet != NULL); 67fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 68fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t event = packet->event & MSG_EVT_MASK; 6943b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson uint8_t *stream = packet->data + packet->offset; 7043b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 7143b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson // We only fragment ACL packets 7243b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson if (event != MSG_STACK_TO_HC_HCI_ACL) { 7343b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson callbacks->fragmented(packet, true); 7443b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson return; 7543b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson } 7643b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 77bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson uint16_t max_data_size = 78bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ? 7930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson controller->get_acl_data_size_classic() : 8030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson controller->get_acl_data_size_ble(); 8143b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 82fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE; 8343b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson uint16_t remaining_length = packet->len; 84fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 8543b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson uint16_t continuation_handle; 8643b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson STREAM_TO_UINT16(continuation_handle, stream); 8743b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle); 8843b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 8943b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson while (remaining_length > max_packet_size) { 9043b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson // Make sure we use the right ACL packet size 9143b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson stream = packet->data + packet->offset; 9243b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson STREAM_SKIP_UINT16(stream); 9343b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson UINT16_TO_STREAM(stream, max_data_size); 9443b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 9543b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson packet->len = max_packet_size; 9643b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson callbacks->fragmented(packet, false); 9743b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 9843b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson packet->offset += max_data_size; 9943b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson remaining_length -= max_data_size; 10043b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson packet->len = remaining_length; 10143b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 10243b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson // Write the ACL header for the next fragment 10343b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson stream = packet->data + packet->offset; 10443b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson UINT16_TO_STREAM(stream, continuation_handle); 10543b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE); 10643b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson 10743b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson // Apparently L2CAP can set layer_specific to a max number of segments to transmit 10843b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson if (packet->layer_specific) { 10943b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson packet->layer_specific--; 110fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 11143b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson if (packet->layer_specific == 0) { 11243b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT; 11343b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson callbacks->transmit_finished(packet, false); 11443b9ddb63f2efac8b3113df975e479663301a5b7Zach Johnson return; 115fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 116fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 117fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 118fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 119fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson callbacks->fragmented(packet, true); 120fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson} 121fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 122fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnsonstatic void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) { 123fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) { 124fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint8_t *stream = packet->data; 125fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t handle; 126fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t l2cap_length; 127fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t acl_length; 128fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 129fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson STREAM_TO_UINT16(handle, stream); 130fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson STREAM_TO_UINT16(acl_length, stream); 131fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson STREAM_TO_UINT16(l2cap_length, stream); 132fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 133fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE); 134fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 135fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle); 136fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson handle = handle & HANDLE_MASK; 137fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 138fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle); 139fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 140fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (boundary_flag == START_PACKET_BOUNDARY) { 141fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (partial_packet) { 14244802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_WARN("%s found unfinished packet for handle with start packet. Dropping old.", __func__); 143fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 144fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson hash_map_erase(partial_packets, (void *)(uintptr_t)handle); 145bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator->free(partial_packet); 146fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 147fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 148fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; 149fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (full_length <= packet->len) { 150fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (full_length < packet->len) 15144802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_WARN("%s found l2cap full length %d less than the hci length %d.", __func__, l2cap_length, packet->len); 152fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 153fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson callbacks->reassembled(packet); 154fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson return; 155fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 156fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 157bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR)); 158fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->event = packet->event; 159fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->len = full_length; 160fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->offset = packet->len; 161fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 162fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson memcpy(partial_packet->data, packet->data, packet->len); 163fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 164fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson // Update the ACL data size to indicate the full expected length 165fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson stream = partial_packet->data; 166fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson STREAM_SKIP_UINT16(stream); // skip the handle 167fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE); 168fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 169fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet); 170fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson // Free the old packet buffer, since we don't need it anymore 171bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator->free(packet); 172fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } else { 173fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (!partial_packet) { 17444802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_WARN("%s got continuation for unknown packet. Dropping it.", __func__); 175bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator->free(packet); 176fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson return; 177fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 178fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 179fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson packet->offset = HCI_ACL_PREAMBLE_SIZE; 180fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson uint16_t projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE); 181fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (projected_offset > partial_packet->len) { // len stores the expected length 18244802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_WARN("%s got packet which would exceed expected length of %d. Truncating.", __func__, partial_packet->len); 183fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson packet->len = partial_packet->len - partial_packet->offset; 184fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson projected_offset = partial_packet->len; 185fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 186fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 187fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson memcpy( 188fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->data + partial_packet->offset, 189fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson packet->data + packet->offset, 190fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson packet->len - packet->offset 191fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson ); 192fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 193fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson // Free the old packet buffer, since we don't need it anymore 194bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator->free(packet); 195fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->offset = projected_offset; 196fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 197fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson if (partial_packet->offset == partial_packet->len) { 198fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson hash_map_erase(partial_packets, (void *)(uintptr_t)handle); 199fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson partial_packet->offset = 0; 200fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson callbacks->reassembled(partial_packet); 201fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 202fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 203fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } else { 204fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson callbacks->reassembled(packet); 205fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson } 206fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson} 207fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 208bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const packet_fragmenter_t interface = { 209fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson init, 2101e0ede7f5522a853fc39d4f183e508ed38f01636Zach Johnson cleanup, 211fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 212fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson fragment_and_dispatch, 213fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson reassemble_and_dispatch 214fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson}; 215fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson 216bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonconst packet_fragmenter_t *packet_fragmenter_get_interface() { 217bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson controller = controller_get_interface(); 218bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator = buffer_allocator_get_interface(); 219bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson return &interface; 220bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson} 221bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 222bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonconst packet_fragmenter_t *packet_fragmenter_get_test_interface( 223bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson const controller_t *controller_interface, 224bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson const allocator_t *buffer_allocator_interface) { 225bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson controller = controller_interface; 226bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson buffer_allocator = buffer_allocator_interface; 227fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson return &interface; 228fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson} 229