obexd: Fix not closing socket when connection attempt fails

When connection attempt fails the socket were left opened as it is not
assigned to the session, also when the connection does succeed the socket
is closed twice when the session is removed.

To fix those issues session now holds a reference to the GIOChannel
returned bt bt_io_connect so that the connection can properly close when
releasing, in addiction to that it also is marked to not close the socket
when the connection succeeds so that when removing the session it doesn't
close the socket twice.

Thanks for Vitja Makarov <vitja.makarov@gmail.com> for reporting this.
This commit is contained in:
Luiz Augusto von Dentz 2010-07-29 14:15:50 +03:00 committed by Marcel Holtmann
parent ef84cfa6e2
commit 27906878d9
2 changed files with 26 additions and 15 deletions

View File

@ -173,8 +173,10 @@ static void session_free(struct session_data *session)
if (session->obex != NULL)
gw_obex_close(session->obex);
if (session->sock > 2)
close(session->sock);
if (session->io != NULL) {
g_io_channel_shutdown(session->io, TRUE, NULL);
g_io_channel_unref(session->io);
}
if (session->path)
session_unregistered(session);
@ -215,13 +217,17 @@ static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
goto done;
}
/* do not close when gw_obex is using the fd */
g_io_channel_set_close_on_unref(session->io, FALSE);
g_io_channel_unref(session->io);
session->io = NULL;
fd = g_io_channel_unix_get_fd(io);
obex = gw_obex_setup_fd(fd, session->target,
session->target_len, NULL, NULL);
callback->session->sock = fd;
callback->session->obex = obex;
session->obex = obex;
done:
callback->func(callback->session, callback->data);
@ -231,9 +237,9 @@ done:
g_free(callback);
}
static int rfcomm_connect(const bdaddr_t *src,
const bdaddr_t *dst, uint8_t channel,
BtIOConnect function, gpointer user_data)
static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
uint8_t channel, BtIOConnect function,
gpointer user_data)
{
GIOChannel *io;
GError *err = NULL;
@ -245,11 +251,11 @@ static int rfcomm_connect(const bdaddr_t *src,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
if (io != NULL)
return 0;
return io;
error("%s", err->message);
g_error_free(err);
return -EIO;
return NULL;
}
static void search_callback(uint8_t type, uint16_t status,
@ -309,8 +315,11 @@ static void search_callback(uint8_t type, uint16_t status,
callback->session->channel = channel;
if (rfcomm_connect(&callback->session->src, &callback->session->dst,
channel, rfcomm_callback, callback) == 0) {
callback->session->io = rfcomm_connect(&callback->session->src,
&callback->session->dst,
channel, rfcomm_callback,
callback);
if (callback->session->io != NULL) {
sdp_close(callback->sdp);
return;
}
@ -418,7 +427,6 @@ struct session_data *session_create(const char *source,
return NULL;
session->refcount = 1;
session->sock = -1;
session->channel = channel;
session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
@ -465,8 +473,11 @@ struct session_data *session_create(const char *source,
callback->data = user_data;
if (session->channel > 0) {
err = rfcomm_connect(&session->src, &session->dst,
session->channel, rfcomm_callback, callback);
session->io = rfcomm_connect(&session->src, &session->dst,
session->channel,
rfcomm_callback,
callback);
err = (session->io == NULL) ? -EINVAL : 0;
} else {
callback->sdp = service_connect(&session->src, &session->dst,
service_callback, callback);

View File

@ -40,10 +40,10 @@ struct session_data {
int target_len;
uuid_t uuid; /* Bluetooth Service Class */
gchar *path; /* Session path */
int sock;
DBusConnection *conn;
DBusMessage *msg;
GwObex *obex;
GIOChannel *io;
struct agent_data *agent;
struct session_callback *callback;
gchar *owner; /* Session owner */