accept fragmented packets

This commit is contained in:
Milanka Ringwald 2016-12-12 13:45:36 +01:00
parent 722a11a8c4
commit 43fe00eff9
3 changed files with 81 additions and 54 deletions

View File

@ -198,13 +198,31 @@ static int avdtp_acceptor_send_accept_response(uint16_t cid, uint8_t transactio
return l2cap_send(cid, command, sizeof(command));
}
int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint, uint8_t signal_identifier, uint8_t *packet, uint16_t size){
if (!stream_endpoint) return 0;
int request_to_send = 1;
typedef struct {
uint8_t command[200];
uint16_t size;
uint16_t offset;
} avdtp_signaling_packet_state_t;
static avdtp_signaling_packet_state_t sig_packet;
static int avdtp_acceptor_process_chunk(avdtp_signaling_packet_header_t * signaling_header, uint8_t * packet, uint16_t size){
memcpy(sig_packet.command + sig_packet.size, packet, size);
sig_packet.size += size;
return signaling_header->packet_type == AVDTP_SINGLE_PACKET || signaling_header->packet_type == AVDTP_END_PACKET;
}
int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint, avdtp_signaling_packet_header_t * signaling_header, uint8_t * packet, uint16_t size){
if (!stream_endpoint) return 0;
if (!avdtp_acceptor_process_chunk(signaling_header, packet, size)) return 0;
uint16_t packet_size = sig_packet.size;
sig_packet.size = 0;
int request_to_send = 1;
switch (stream_endpoint->acceptor_config_state){
case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE:
switch (signal_identifier){
switch (signaling_header->signal_identifier){
case AVDTP_SI_GET_ALL_CAPABILITIES:
printf(" ACP: AVDTP_SI_GET_ALL_CAPABILITIES\n");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES;
@ -217,8 +235,8 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION \n");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION;
avdtp_sep_t sep;
sep.seid = packet[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(&sep.capabilities, packet+4, size-4);
sep.seid = sig_packet.command[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(&sep.capabilities, sig_packet.command+4, packet_size-4);
// find or add sep
stream_endpoint->remote_sep_index = 0xFF;
@ -242,7 +260,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
// printf(" ACP: AVDTP_SI_RECONFIGURE, bad state %d \n", stream_endpoint->state);
// stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
// stream_endpoint->error_code = BAD_STATE;
// stream_endpoint->reject_signal_identifier = signal_identifier;
// stream_endpoint->reject_signal_identifier = signaling_header->signal_identifier;
// break;
// }
@ -253,7 +271,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE %p in state %d (AVDTP_STREAM_ENDPOINT_OPENED %d)\n", stream_endpoint, stream_endpoint->state, AVDTP_STREAM_ENDPOINT_OPENED);
avdtp_sep_t sep;
sep.seid = packet[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(&sep.capabilities, packet+4, size-4);
sep.registered_service_categories = avdtp_unpack_service_capabilities(&sep.capabilities, packet+4, packet_size-4);
// find sep or raise error
int i;
@ -267,7 +285,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
printf(" ACP: AVDTP_SI_RECONFIGURE, bad state seid %d not found\n", sep.seid);
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
stream_endpoint->error_code = BAD_ACP_SEID;
stream_endpoint->reject_signal_identifier = signal_identifier;
stream_endpoint->reject_signal_identifier = signaling_header->signal_identifier;
break;
}
@ -316,7 +334,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
printf(" ACP: AVDTP_SI_CLOSE, bad state %d \n", stream_endpoint->state);
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
stream_endpoint->error_code = BAD_STATE;
stream_endpoint->reject_signal_identifier = signal_identifier;
stream_endpoint->reject_signal_identifier = signaling_header->signal_identifier;
break;
}
break;
@ -326,16 +344,16 @@ int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM;
break;
default:
printf(" ACP: NOT IMPLEMENTED, Reject signal_identifier %02x\n", signal_identifier);
printf(" ACP: NOT IMPLEMENTED, Reject signal_identifier %02x\n", signaling_header->signal_identifier);
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD;
stream_endpoint->reject_signal_identifier = signal_identifier;
stream_endpoint->reject_signal_identifier = signaling_header->signal_identifier;
break;
}
break;
default:
return 0;
}
if (!request_to_send){
printf(" ACP: NOT IMPLEMENTED\n");
}

View File

@ -51,7 +51,7 @@
extern "C" {
#endif
int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint, uint8_t signal_identifier, uint8_t *packet, uint16_t size);
int avdtp_acceptor_stream_config_subsm(avdtp_stream_endpoint_t * stream_endpoint, avdtp_signaling_packet_header_t * signaling_header, uint8_t *packet, uint16_t size);
int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint);
#if defined __cplusplus

View File

@ -455,7 +455,7 @@ static int handle_l2cap_data_packet_for_stream_endpoint(avdtp_connection_t * con
avdtp_read_signaling_header(&signaling_header, packet, size);
if (signaling_header.message_type == AVDTP_CMD_MSG){
if (avdtp_acceptor_stream_config_subsm(stream_endpoint, signaling_header.signal_identifier, packet, size)){
if (avdtp_acceptor_stream_config_subsm(stream_endpoint, &signaling_header, packet, size)){
avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
return 1;
}
@ -468,7 +468,7 @@ static int handle_l2cap_data_packet_for_stream_endpoint(avdtp_connection_t * con
return 0;
}
static int handle_l2cap_data_packet_for_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size){
static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size){
if (size < 2) {
log_error("l2cap data packet too small");
return 0;
@ -562,48 +562,57 @@ static int handle_l2cap_data_packet_for_connection(avdtp_connection_t * connecti
break;
}
printf(" handle_l2cap_data_packet_for_connection 3, signal %d\n", signaling_header.signal_identifier);
printf(" handle_l2cap_data_packet_for_signaling_connection 3, signal %d\n", signaling_header.signal_identifier);
return 0;
}
static void handle_hci_event_packet_for_stream_endpoint(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t event, uint8_t *packet, uint16_t size){
static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t packet_type, uint8_t event, uint8_t *packet, uint16_t size){
uint16_t local_cid;
switch (event){
case L2CAP_EVENT_CHANNEL_OPENED:
if (stream_endpoint->l2cap_media_cid == 0){
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
stream_endpoint->connection = connection;
stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);;
printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection);
break;
}
switch (packet_type){
case L2CAP_DATA_PACKET:
handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
if (stream_endpoint->l2cap_media_cid == local_cid){
stream_endpoint->l2cap_media_cid = 0;
printf(" -> AVDTP_STREAM_ENDPOINT_IDLE\n");
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
}
case HCI_EVENT_PACKET:
switch (event){
case L2CAP_EVENT_CHANNEL_OPENED:
if (stream_endpoint->l2cap_media_cid == 0){
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
stream_endpoint->connection = connection;
stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);;
printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection);
break;
}
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
if (stream_endpoint->l2cap_media_cid == local_cid){
stream_endpoint->l2cap_media_cid = 0;
printf(" -> AVDTP_STREAM_ENDPOINT_IDLE\n");
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
}
if (stream_endpoint->l2cap_recovery_cid == local_cid){
log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid);
stream_endpoint->l2cap_recovery_cid = 0;
break;
}
if (stream_endpoint->l2cap_reporting_cid == local_cid){
log_info("L2CAP_EVENT_CHANNEL_CLOSED reporting cid 0x%0x", local_cid);
stream_endpoint->l2cap_reporting_cid = 0;
break;
}
if (stream_endpoint->l2cap_recovery_cid == local_cid){
log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid);
stream_endpoint->l2cap_recovery_cid = 0;
break;
}
if (stream_endpoint->l2cap_reporting_cid == local_cid){
log_info("L2CAP_EVENT_CHANNEL_CLOSED reporting cid 0x%0x", local_cid);
stream_endpoint->l2cap_reporting_cid = 0;
break;
}
break;
default:
break;
}
break;
default:
break;
}
}
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
@ -618,7 +627,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case L2CAP_DATA_PACKET:
connection = get_avdtp_connection_for_l2cap_signaling_cid(channel);
if (connection){
if (handle_l2cap_data_packet_for_connection(connection, packet, size)) return;
if (handle_l2cap_data_packet_for_signaling_connection(connection, packet, size)) return;
}
stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(channel);
@ -628,8 +637,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
if (channel == stream_endpoint->connection->l2cap_signaling_cid){
printf(" handle_l2cap_data_packet_for_connection 1\n");
handle_l2cap_data_packet_for_stream_endpoint(stream_endpoint->connection, stream_endpoint, packet, size);
printf(" handle_l2cap_data_packet_for_signaling_connection 1\n");
stream_endpoint_state_machine(stream_endpoint->connection, stream_endpoint, L2CAP_DATA_PACKET, 0, packet, size);
break;
}
@ -717,7 +726,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found");
return;
}
handle_hci_event_packet_for_stream_endpoint(connection, stream_endpoint, L2CAP_EVENT_CHANNEL_OPENED, packet, size);
stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_OPENED, packet, size);
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
@ -745,7 +754,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(local_cid);
if (!stream_endpoint) return;
handle_hci_event_packet_for_stream_endpoint(connection, stream_endpoint, L2CAP_EVENT_CHANNEL_CLOSED, packet, size);
stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_CLOSED, packet, size);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE: