bluez5: protect against NULL transport

The transport can be destroyed at any time, make sure we don't
crash when it does.
This commit is contained in:
Wim Taymans 2020-03-23 13:49:30 +01:00
parent 4c80656a7b
commit c4cf5e6629
4 changed files with 49 additions and 30 deletions

View file

@ -361,6 +361,8 @@ static int send_buffer(struct impl *this)
struct rtp_header *header; struct rtp_header *header;
struct rtp_payload *payload; struct rtp_payload *payload;
spa_return_val_if_fail(this->transport, -EIO);
header = (struct rtp_header *)this->buffer; header = (struct rtp_header *)this->buffer;
payload = (struct rtp_payload *)(this->buffer + sizeof(struct rtp_header)); payload = (struct rtp_payload *)(this->buffer + sizeof(struct rtp_header));
memset(this->buffer, 0, sizeof(struct rtp_header)+sizeof(struct rtp_payload)); memset(this->buffer, 0, sizeof(struct rtp_header)+sizeof(struct rtp_payload));
@ -487,6 +489,8 @@ static int set_bitpool(struct impl *this, int bitpool)
{ {
struct port *port = &this->port; struct port *port = &this->port;
spa_return_val_if_fail(this->transport, -EIO);
if (bitpool < this->min_bitpool) if (bitpool < this->min_bitpool)
bitpool = this->min_bitpool; bitpool = this->min_bitpool;
if (bitpool > this->max_bitpool) if (bitpool > this->max_bitpool)
@ -715,7 +719,11 @@ static void a2dp_on_timeout(struct spa_source *source)
static int init_sbc(struct impl *this) static int init_sbc(struct impl *this)
{ {
struct spa_bt_transport *transport = this->transport; struct spa_bt_transport *transport = this->transport;
a2dp_sbc_t *conf = transport->configuration; a2dp_sbc_t *conf;
spa_return_val_if_fail(transport, -EIO);
conf = transport->configuration;
sbc_init(&this->sbc, 0); sbc_init(&this->sbc, 0);
this->sbc.endian = SBC_LE; this->sbc.endian = SBC_LE;
@ -797,6 +805,8 @@ static int do_start(struct impl *this)
if (this->started) if (this->started)
return 0; return 0;
spa_return_val_if_fail(this->transport, -EIO);
this->following = is_following(this); this->following = is_following(this);
spa_log_debug(this->log, NAME " %p: start following:%d", this, this->following); spa_log_debug(this->log, NAME " %p: start following:%d", this, this->following);
@ -1039,6 +1049,8 @@ impl_node_port_enum_params(void *object, int seq,
case SPA_PARAM_EnumFormat: case SPA_PARAM_EnumFormat:
if (result.index > 0) if (result.index > 0)
return 0; return 0;
if (this->transport == NULL)
return -EIO;
switch (this->transport->codec) { switch (this->transport->codec) {
case A2DP_CODEC_SBC: case A2DP_CODEC_SBC:

View file

@ -408,6 +408,10 @@ static void a2dp_on_ready_read(struct spa_source *source)
spa_log_error(this->log, "source is not an input, rmask=%d", source->rmask); spa_log_error(this->log, "source is not an input, rmask=%d", source->rmask);
goto stop; goto stop;
} }
if (this->transport == NULL) {
spa_log_debug(this->log, "no transport, stop reading");
goto stop;
}
/* update the current pts */ /* update the current pts */
spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now); spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now);
@ -494,11 +498,10 @@ static int do_start(struct impl *this)
if (this->started) if (this->started)
return 0; return 0;
if (this->transport == NULL)
return -EIO;
spa_log_debug(this->log, NAME" %p: start", this); spa_log_debug(this->log, NAME" %p: start", this);
spa_return_val_if_fail(this->transport != NULL, -EIO);
if (this->transport->state >= SPA_BT_TRANSPORT_STATE_PENDING) if (this->transport->state >= SPA_BT_TRANSPORT_STATE_PENDING)
res = transport_start(this); res = transport_start(this);
@ -693,7 +696,6 @@ impl_node_port_enum_params(void *object, int seq,
case SPA_PARAM_EnumFormat: case SPA_PARAM_EnumFormat:
if (result.index > 0) if (result.index > 0)
return 0; return 0;
if (this->transport == NULL) if (this->transport == NULL)
return -EIO; return -EIO;

View file

@ -130,6 +130,7 @@ struct impl {
/* Counts */ /* Counts */
uint64_t sample_count; uint64_t sample_count;
uint32_t write_mtu;
}; };
#define NAME "sco-sink" #define NAME "sco-sink"
@ -347,7 +348,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
static bool write_data(struct impl *this, const uint8_t *data, uint32_t size, uint32_t *total_written) static bool write_data(struct impl *this, const uint8_t *data, uint32_t size, uint32_t *total_written)
{ {
uint32_t local_total_written = 0; uint32_t local_total_written = 0;
const uint32_t mtu_size = this->transport->write_mtu; const uint32_t mtu_size = this->write_mtu;
while (local_total_written <= (size - mtu_size)) { while (local_total_written <= (size - mtu_size)) {
const int bytes_written = write(this->sock_fd, data, mtu_size); const int bytes_written = write(this->sock_fd, data, mtu_size);
@ -414,28 +415,29 @@ static int render_buffers(struct impl *this, uint64_t now_time)
return 0; return 0;
} }
static void fill_socket (struct impl *this) static void fill_socket(struct impl *this)
{ {
struct port *port = &this->port; struct port *port = &this->port;
static const uint8_t zero_buffer[1024 * 4] = { 0, }; static const uint8_t zero_buffer[1024 * 4] = { 0, };
uint32_t fill_size = this->transport->write_mtu; uint32_t fill_size = this->write_mtu;
uint32_t fills = 0; uint32_t fills = 0;
uint32_t total_written = 0; uint32_t total_written = 0;
/* Fill the socked */
while (fills < FILL_FRAMES) {
uint32_t written = 0;
/* Write the data */ /* Fill the socket */
if (!write_data(this, zero_buffer, fill_size, &written)) while (fills < FILL_FRAMES) {
break; uint32_t written = 0;
total_written += written; /* Write the data */
fills++; if (!write_data(this, zero_buffer, fill_size, &written))
} break;
/* Update the sample count */ total_written += written;
this->sample_count += total_written / port->frame_size; fills++;
}
/* Update the sample count */
this->sample_count += total_written / port->frame_size;
} }
static void sco_on_flush(struct spa_source *source) static void sco_on_flush(struct spa_source *source)
@ -479,7 +481,7 @@ static void sco_on_timeout(struct spa_source *source)
/* If this is the first timeout, set the start time and fill the socked */ /* If this is the first timeout, set the start time and fill the socked */
if (this->start_time == 0) { if (this->start_time == 0) {
fill_socket (this); fill_socket(this);
this->start_time = now_time; this->start_time = now_time;
} }
@ -503,7 +505,7 @@ static int do_start(struct impl *this)
return 0; return 0;
/* Make sure the transport is valid */ /* Make sure the transport is valid */
spa_return_val_if_fail (this->transport != NULL, -EIO); spa_return_val_if_fail(this->transport != NULL, -EIO);
/* Set the following flag */ /* Set the following flag */
this->following = is_following(this); this->following = is_following(this);
@ -517,6 +519,7 @@ static int do_start(struct impl *this)
return -1; return -1;
/* Set the write MTU */ /* Set the write MTU */
this->write_mtu = this->transport->write_mtu;
val = FILL_FRAMES * this->transport->write_mtu; val = FILL_FRAMES * this->transport->write_mtu;
if (setsockopt(this->sock_fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0) if (setsockopt(this->sock_fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "sco-sink %p: SO_SNDBUF %m", this); spa_log_warn(this->log, "sco-sink %p: SO_SNDBUF %m", this);

View file

@ -117,6 +117,7 @@ struct impl {
struct timespec now; struct timespec now;
uint32_t sample_count; uint32_t sample_count;
uint32_t read_mtu;
}; };
#define NAME "sco-source" #define NAME "sco-source"
@ -294,8 +295,9 @@ static void reset_buffers(struct port *port)
} }
} }
static bool read_data(struct impl *this, uint8_t *data, uint32_t size, uint32_t *total_read) { static bool read_data(struct impl *this, uint8_t *data, uint32_t size, uint32_t *total_read)
const uint32_t mtu_size = this->transport->read_mtu; {
const uint32_t mtu_size = this->read_mtu;
uint32_t local_total_read = 0; uint32_t local_total_read = 0;
/* Read chunks of mtu_size */ /* Read chunks of mtu_size */
@ -321,7 +323,7 @@ static bool read_data(struct impl *this, uint8_t *data, uint32_t size, uint32_t
done: done:
if (total_read) if (total_read)
*total_read = local_total_read; *total_read = local_total_read;
return true; return true;
} }
@ -428,7 +430,8 @@ static int do_start(struct impl *this)
spa_log_warn(this->log, "sco-source %p: SO_SNDBUF %m", this); spa_log_warn(this->log, "sco-source %p: SO_SNDBUF %m", this);
/* Set the read MTU */ /* Set the read MTU */
val = FILL_FRAMES * this->transport->read_mtu; this->read_mtu = this->transport->read_mtu;
val = FILL_FRAMES * this->read_mtu;
if (setsockopt(this->sock_fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) < 0) if (setsockopt(this->sock_fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "sco-source %p: SO_RCVBUF %m", this); spa_log_warn(this->log, "sco-source %p: SO_RCVBUF %m", this);
@ -644,7 +647,6 @@ impl_node_port_enum_params(void *object, int seq,
case SPA_PARAM_EnumFormat: case SPA_PARAM_EnumFormat:
if (result.index > 0) if (result.index > 0)
return 0; return 0;
if (this->transport == NULL) if (this->transport == NULL)
return -EIO; return -EIO;