summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2008-10-10 11:16:17 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2008-10-10 11:16:17 +0200
commita1f8f9870457b213682328da441ba4aeeba2cad1 (patch)
tree26bd845c28bbdd10dac97b73247ade741d1c33be
parent1613e8c2180952a5f312071acc9076772a3e2556 (diff)
Fix situation where avctp_disconnect is called while connecting
Previously the avctp session would be free'd and the connect callback would try to access this free'd memory. Now we detect this situation properly but the fundamental problem remains that the bt_l2cap_connect API doesn't allow aborting the connect procedure.
-rw-r--r--audio/control.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/audio/control.c b/audio/control.c
index c8480197..3e4e776a 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -755,12 +755,20 @@ static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master)
static void avctp_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src,
const bdaddr_t *dst, gpointer data)
{
- struct avctp *session = data;
+ struct control *control = data;
+ struct avctp *session = control->session;
struct l2cap_options l2o;
socklen_t len;
int sk;
char address[18];
+ if (!session) {
+ debug("avctp_connect_cb: session removed while connecting");
+ g_io_channel_close(chan);
+ g_io_channel_unref(chan);
+ return;
+ }
+
ba2str(&session->dst, address);
if (err < 0) {
@@ -780,6 +788,7 @@ static void avctp_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src,
len = sizeof(l2o);
if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
err = errno;
+ g_io_channel_unref(chan);
avctp_unref(session);
error("getsockopt(L2CAP_OPTIONS): %s (%d)", strerror(err),
err);
@@ -797,6 +806,7 @@ static void avctp_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src,
session->io = g_io_add_watch(chan,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_cb, session);
+ g_io_channel_unref(chan);
}
gboolean avrcp_connect(struct audio_device *dev)
@@ -818,7 +828,7 @@ gboolean avrcp_connect(struct audio_device *dev)
session->state = AVCTP_STATE_CONNECTING;
err = bt_l2cap_connect(&dev->src, &dev->dst, AVCTP_PSM, 0,
- avctp_connect_cb, session);
+ avctp_connect_cb, control);
if (err < 0) {
avctp_unref(session);
error("Connect failed. %s(%d)", strerror(-err), -err);