2013-11-22 15:49:31

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 1/6] android/socket: Check that create_record function exist

From: Andrei Emeltchenko <[email protected]>

---
android/socket.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index daf4370..4f6f02b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -673,7 +673,7 @@ static int handle_listen(void *buf)
return -1;
}

- if (profile)
+ if (profile && profile->create_record)
rfsock->service_handle = sdp_service_register(profile,
cmd->name);

--
1.8.3.2



2013-11-22 15:49:32

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 2/6] android/socket: Use dafault sec_level for listen

From: Andrei Emeltchenko <[email protected]>

Set default security level low for OPP and SPP and medium for PBAP and MAS.
Default security level would be low for listening without profile.
---
android/socket.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index 4f6f02b..fcba1e8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -329,6 +329,7 @@ static struct profile_info {
},
.channel = PBAP_DEFAULT_CHANNEL,
.svc_hint = SVC_HINT_OBEX,
+ .sec_level = BT_IO_SEC_MEDIUM,
.create_record = create_pbap_record
}, {
.uuid = {
@@ -337,13 +338,17 @@ static struct profile_info {
},
.channel = OPP_DEFAULT_CHANNEL,
.svc_hint = SVC_HINT_OBEX,
+ .sec_level = BT_IO_SEC_LOW,
.create_record = create_opp_record
}, {
.uuid = {
0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
- .channel = MAS_DEFAULT_CHANNEL
+ .channel = MAS_DEFAULT_CHANNEL,
+ .svc_hint = 0,
+ .sec_level = BT_IO_SEC_MEDIUM,
+ .create_record = NULL
}, {
.uuid = {
0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
@@ -351,6 +356,7 @@ static struct profile_info {
},
.channel = SPP_DEFAULT_CHANNEL,
.svc_hint = 0,
+ .sec_level = BT_IO_SEC_LOW,
.create_record = create_spp_record
},
};
@@ -624,6 +630,7 @@ static int handle_listen(void *buf)
struct hal_cmd_sock_listen *cmd = buf;
struct profile_info *profile;
struct rfcomm_sock *rfsock;
+ BtIOSecLevel sec_level;
GIOChannel *io;
GError *err = NULL;
int hal_fd;
@@ -635,10 +642,14 @@ static int handle_listen(void *buf)
if (!profile) {
if (!cmd->channel)
return -1;
- else
+ else {
chan = cmd->channel;
- } else
+ sec_level = BT_IO_SEC_LOW;
+ }
+ } else {
chan = profile->channel;
+ sec_level = profile->sec_level;
+ }

DBG("rfcomm channel %d svc_name %s", chan, cmd->name);

@@ -649,6 +660,7 @@ static int handle_listen(void *buf)
io = bt_io_listen(accept_cb, NULL, rfsock, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
BT_IO_OPT_CHANNEL, chan,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
BT_IO_OPT_INVALID);
if (!io) {
error("Failed listen: %s", err->message);
--
1.8.3.2


2013-11-22 15:49:33

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 3/6] android/socket: Add error printing possible close() failure

From: Andrei Emeltchenko <[email protected]>

---
android/socket.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index fcba1e8..07b205d 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -97,9 +97,14 @@ static void cleanup_rfsock(struct rfcomm_sock *rfsock)
rfsock, rfsock->fd, rfsock->real_sock, rfsock->channel);

if (rfsock->fd > 0)
- close(rfsock->fd);
+ if (close(rfsock->fd) < 0)
+ error("close() fd %d failed: %s", rfsock->fd,
+ strerror(errno));
+
if (rfsock->real_sock > 0)
- close(rfsock->real_sock);
+ if (close(rfsock->real_sock) < 0)
+ error("close() fd %d: failed: %s", rfsock->real_sock,
+ strerror(errno));

if (rfsock->rfcomm_watch > 0)
if (!g_source_remove(rfsock->rfcomm_watch))
--
1.8.3.2


2013-11-22 15:49:36

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 6/6] android/socket: Handle Android events for server socket

From: Andrei Emeltchenko <[email protected]>

Add watch for tracking events from Android framework for server socket.
---
android/socket.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index a2996c2..890d91b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -578,6 +578,24 @@ static bool sock_send_accept(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr,
return true;
}

+static gboolean sock_server_stack_event_cb(GIOChannel *io, GIOCondition cond,
+ gpointer data)
+{
+ struct rfcomm_sock *rfsock = data;
+
+ DBG("");
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ error("Socket error: sock %d cond %d",
+ g_io_channel_unix_get_fd(io), cond);
+ cleanup_rfsock(rfsock);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
{
struct rfcomm_sock *rfsock = user_data;
@@ -647,7 +665,8 @@ static int handle_listen(void *buf)
struct profile_info *profile;
struct rfcomm_sock *rfsock;
BtIOSecLevel sec_level;
- GIOChannel *io;
+ GIOChannel *io, *io_stack;
+ GIOCondition cond;
GError *err = NULL;
int hal_fd;
int chan;
@@ -690,6 +709,12 @@ static int handle_listen(void *buf)

rfsock->srv_io = io;

+ /* Handle events from Android */
+ cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+ io_stack = g_io_channel_unix_new(rfsock->fd);
+ g_io_add_watch(io_stack, cond, sock_server_stack_event_cb, rfsock);
+ g_io_channel_unref(io_stack);
+
DBG("real_sock %d fd %d hal_fd %d", rfsock->real_sock, rfsock->fd,
hal_fd);

--
1.8.3.2


2013-11-22 15:49:34

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 4/6] android/socket: Use security level for connect

From: Andrei Emeltchenko <[email protected]>

Use low security level for connections without profile and default
sec_level for others. rfsock now has pointer to profile info for
outcoming connections.
---
android/socket.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index 07b205d..e864c4e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -60,6 +60,8 @@ GList *servers = NULL;
/* Simple list of RFCOMM connected sockets */
GList *connections = NULL;

+struct profile_info;
+
struct rfcomm_sock {
int fd; /* descriptor for communication with Java framework */
int real_sock; /* real RFCOMM socket */
@@ -70,6 +72,8 @@ struct rfcomm_sock {

bdaddr_t dst;
uint32_t service_handle;
+
+ struct profile_info *profile;
};

static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
@@ -770,6 +774,7 @@ fail:
static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
{
struct rfcomm_sock *rfsock = data;
+ BtIOSecLevel sec_level = BT_IO_SEC_LOW;
GError *gerr = NULL;
sdp_list_t *list;
GIOChannel *io;
@@ -810,11 +815,14 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)

DBG("Got RFCOMM channel %d", chan);

+ if (rfsock->profile)
+ sec_level = rfsock->profile->sec_level;
+
io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
BT_IO_OPT_CHANNEL, chan,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
BT_IO_OPT_INVALID);
if (!io) {
error("Failed connect: %s", gerr->message);
@@ -856,6 +864,8 @@ static int handle_connect(void *buf)
uuid.type = SDP_UUID128;
memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));

+ rfsock->profile = get_profile_by_uuid(cmd->uuid);
+
if (bt_search_service(&adapter_addr, &dst, &uuid, sdp_search_cb, rfsock,
NULL) < 0) {
error("Failed to search SDP records");
--
1.8.3.2


2013-11-22 15:49:35

by Andrei Emeltchenko

[permalink] [raw]
Subject: [RFC 5/6] android/socket: Keep server iochannel reference

From: Andrei Emeltchenko <[email protected]>

server io channel reference will be stored in rfsock structure
and might be deleted when Android end closes connection or when
HAL makes cleanup() call.
---
android/socket.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index e864c4e..a2996c2 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -70,6 +70,8 @@ struct rfcomm_sock {
guint rfcomm_watch;
guint stack_watch;

+ GIOChannel *srv_io;
+
bdaddr_t dst;
uint32_t service_handle;

@@ -121,6 +123,11 @@ static void cleanup_rfsock(struct rfcomm_sock *rfsock)
if (rfsock->service_handle)
bt_adapter_remove_record(rfsock->service_handle);

+ if (rfsock->srv_io) {
+ g_io_channel_shutdown(rfsock->srv_io, TRUE, NULL);
+ g_io_channel_unref(rfsock->srv_io);
+ }
+
g_free(rfsock);
}

@@ -681,9 +688,7 @@ static int handle_listen(void *buf)
rfsock->real_sock = g_io_channel_unix_get_fd(io);
servers = g_list_append(servers, rfsock);

- /* TODO: Add server watch */
- g_io_channel_set_close_on_unref(io, TRUE);
- g_io_channel_unref(io);
+ rfsock->srv_io = io;

DBG("real_sock %d fd %d hal_fd %d", rfsock->real_sock, rfsock->fd,
hal_fd);
--
1.8.3.2