hci: release outgoing buffer on disconnect if waiting to send another ACL fragment

This commit is contained in:
Matthias Ringwald 2019-01-17 19:21:00 +01:00
parent 88949f8443
commit 81d2bdb29c
2 changed files with 14 additions and 4 deletions

View File

@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- HCI: validate advertisement data length field when generating GAP_EVENT_ADVERTISING_REPORT - HCI: validate advertisement data length field when generating GAP_EVENT_ADVERTISING_REPORT
- ad_parser: validate data element length fields in ad_iterator_has_more - ad_parser: validate data element length fields in ad_iterator_has_more
### Fixed
- HCI: release outgoing buffer on disconnect if waiting to send another ACL fragment
## Changes December 2018 ## Changes December 2018
### Added ### Added

View File

@ -668,6 +668,7 @@ static int hci_send_acl_packet_fragments(hci_connection_t *connection){
uint8_t * packet = &hci_stack->hci_packet_buffer[acl_header_pos]; uint8_t * packet = &hci_stack->hci_packet_buffer[acl_header_pos];
const int size = current_acl_data_packet_length + 4; const int size = current_acl_data_packet_length + 4;
hci_dump_packet(HCI_ACL_DATA_PACKET, 0, packet, size); hci_dump_packet(HCI_ACL_DATA_PACKET, 0, packet, size);
hci_stack->acl_fragmentation_tx_active = 1;
err = hci_stack->hci_transport->send_packet(HCI_ACL_DATA_PACKET, packet, size); err = hci_stack->hci_transport->send_packet(HCI_ACL_DATA_PACKET, packet, size);
log_debug("hci_send_acl_packet_fragments loop after send (more fragments %d)", more_fragments); log_debug("hci_send_acl_packet_fragments loop after send (more fragments %d)", more_fragments);
@ -683,6 +684,7 @@ static int hci_send_acl_packet_fragments(hci_connection_t *connection){
// release buffer now for synchronous transport // release buffer now for synchronous transport
if (hci_transport_synchronous()){ if (hci_transport_synchronous()){
hci_stack->acl_fragmentation_tx_active = 0;
hci_release_packet_buffer(); hci_release_packet_buffer();
hci_emit_transport_packet_sent(); hci_emit_transport_packet_sent();
} }
@ -2251,12 +2253,16 @@ static void event_handler(uint8_t *packet, int size){
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
if (packet[2]) break; // status != 0 if (packet[2]) break; // status != 0
handle = little_endian_read_16(packet, 3); handle = little_endian_read_16(packet, 3);
// drop outgoing ACL fragments if it is for closed connection // drop outgoing ACL fragments if it is for closed connection and release buffer if tx not active
if (hci_stack->acl_fragmentation_total_size > 0) { if (hci_stack->acl_fragmentation_total_size > 0) {
if (handle == READ_ACL_CONNECTION_HANDLE(hci_stack->hci_packet_buffer)){ if (handle == READ_ACL_CONNECTION_HANDLE(hci_stack->hci_packet_buffer)){
log_info("hci: drop fragmented ACL data for closed connection"); int release_buffer = hci_stack->acl_fragmentation_tx_active == 0;
log_info("drop fragmented ACL data for closed connection, release buffer %u", release_buffer);
hci_stack->acl_fragmentation_total_size = 0; hci_stack->acl_fragmentation_total_size = 0;
hci_stack->acl_fragmentation_pos = 0; hci_stack->acl_fragmentation_pos = 0;
if (release_buffer){
hci_release_packet_buffer();
}
} }
} }
@ -2301,6 +2307,7 @@ static void event_handler(uint8_t *packet, int size){
log_error("Synchronous HCI Transport shouldn't send HCI_EVENT_TRANSPORT_PACKET_SENT"); log_error("Synchronous HCI Transport shouldn't send HCI_EVENT_TRANSPORT_PACKET_SENT");
return; // instead of break: to avoid re-entering hci_run() return; // instead of break: to avoid re-entering hci_run()
} }
hci_stack->acl_fragmentation_tx_active = 0;
if (hci_stack->acl_fragmentation_total_size) break; if (hci_stack->acl_fragmentation_total_size) break;
hci_release_packet_buffer(); hci_release_packet_buffer();