Return-Path: MIME-Version: 1.0 In-Reply-To: References: <1415933393-28902-1-git-send-email-armansito@chromium.org> <1415933393-28902-4-git-send-email-armansito@chromium.org> Date: Fri, 14 Nov 2014 11:48:44 -0800 Message-ID: Subject: Re: [PATCH BlueZ v2 3/7] tools/btgatt-server: Accept incoming connection and initialize server. From: Arman Uguray To: Arman Uguray Cc: Luiz Augusto von Dentz , "linux-bluetooth@vger.kernel.org" Content-Type: text/plain; charset=UTF-8 Sender: linux-bluetooth-owner@vger.kernel.org List-ID: Hi Luiz, > On Fri, Nov 14, 2014 at 8:32 AM, Arman Uguray wrote: > Hi Luiz, > >> On Fri, Nov 14, 2014 at 5:31 AM, Luiz Augusto von Dentz wrote: >> Hi Arman, >> >> On Fri, Nov 14, 2014 at 4:49 AM, Arman Uguray wrote: >>> This patch adds code that listens for incoming connections and creates a >>> bt_gatt_server and bt_att structure once a connection is accepted. >>> --- >>> tools/btgatt-server.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++- >>> 1 file changed, 209 insertions(+), 2 deletions(-) >>> >>> diff --git a/tools/btgatt-server.c b/tools/btgatt-server.c >>> index 4508de2..e185413 100644 >>> --- a/tools/btgatt-server.c >>> +++ b/tools/btgatt-server.c >>> @@ -25,6 +25,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> >>> #include >>> #include >>> @@ -32,8 +33,131 @@ >>> #include >>> #include "lib/uuid.h" >>> >>> +#include "monitor/mainloop.h" >>> +#include "src/shared/util.h" >>> +#include "src/shared/att.h" >>> +#include "src/shared/queue.h" >>> +#include "src/shared/gatt-db.h" >>> +#include "src/shared/gatt-server.h" >>> + >>> +#define ATT_CID 4 >>> + >>> +#define PRLOG(...) \ >>> + do { \ >>> + printf(__VA_ARGS__); \ >>> + print_prompt(); \ >>> + } while (0) >>> + >>> +#define COLOR_OFF "\x1B[0m" >>> +#define COLOR_RED "\x1B[0;91m" >>> +#define COLOR_GREEN "\x1B[0;92m" >>> +#define COLOR_YELLOW "\x1B[0;93m" >>> +#define COLOR_BLUE "\x1B[0;94m" >>> +#define COLOR_MAGENTA "\x1B[0;95m" >>> +#define COLOR_BOLDGRAY "\x1B[1;30m" >>> +#define COLOR_BOLDWHITE "\x1B[1;37m" >>> + >>> static bool verbose = false; >>> >>> +struct server { >>> + int fd; >>> + struct gatt_db *db; >>> + struct bt_gatt_server *gatt; >>> +}; >>> + >>> +static void print_prompt(void) >>> +{ >>> + printf(COLOR_BLUE "[GATT server]" COLOR_OFF "# "); >>> + fflush(stdout); >>> +} >>> + >>> +static void att_disconnect_cb(void *user_data) >>> +{ >>> + printf("Device disconnected\n"); >>> + >>> + mainloop_quit(); >>> +} >>> + >>> +static void att_debug_cb(const char *str, void *user_data) >>> +{ >>> + const char *prefix = user_data; >>> + >>> + PRLOG(COLOR_BOLDGRAY "%s" COLOR_BOLDWHITE "%s\n" COLOR_OFF, prefix, >>> + str); >>> +} >>> + >>> +static void gatt_debug_cb(const char *str, void *user_data) >>> +{ >>> + const char *prefix = user_data; >>> + >>> + PRLOG(COLOR_GREEN "%s%s\n" COLOR_OFF, prefix, str); >>> +} >>> + >>> +static struct server *server_create(int fd, uint16_t mtu) >>> +{ >>> + struct server *server; >>> + struct bt_att *att; >>> + >>> + server = new0(struct server, 1); >>> + if (!server) { >>> + fprintf(stderr, "Failed to allocate memory for server\n"); >>> + return NULL; >>> + } >>> + >>> + att = bt_att_new(fd); >>> + if (!att) { >>> + fprintf(stderr, "Failed to initialze ATT transport layer\n"); >>> + goto fail; >>> + } >>> + >>> + if (!bt_att_set_close_on_unref(att, true)) { >>> + fprintf(stderr, "Failed to set up ATT transport layer\n"); >>> + goto fail; >>> + } >>> + >>> + if (!bt_att_register_disconnect(att, att_disconnect_cb, NULL, NULL)) { >>> + fprintf(stderr, "Failed to set ATT disconnect handler\n"); >>> + goto fail; >>> + } >>> + >>> + server->fd = fd; >>> + server->db = gatt_db_new(); >>> + if (!server->db) { >>> + fprintf(stderr, "Failed to create GATT database\n"); >>> + goto fail; >>> + } >>> + >>> + server->gatt = bt_gatt_server_new(server->db, att, mtu); >>> + if (!server->gatt) { >>> + fprintf(stderr, "Failed to create GATT server\n"); >>> + goto fail; >>> + } >>> + >>> + if (verbose) { >>> + bt_att_set_debug(att, att_debug_cb, "att: ", NULL); >>> + bt_gatt_server_set_debug(server->gatt, gatt_debug_cb, >>> + "server: ", NULL); >>> + } >>> + >>> + /* bt_gatt_server already holds a reference */ >>> + bt_att_unref(att); >>> + >>> + return server; >>> + >>> +fail: >>> + gatt_db_destroy(server->db); >>> + bt_att_unref(att); >>> + free(server); >>> + >>> + return NULL; >>> +} >>> + >>> +static void server_destroy(struct server *server) >>> +{ >>> + bt_gatt_server_unref(server->gatt); >>> + gatt_db_destroy(server->db); >>> +} >>> + >>> static void usage(void) >>> { >>> printf("btgatt-server\n"); >>> @@ -57,6 +181,67 @@ static struct option main_options[] = { >>> { } >>> }; >>> >>> +static int l2cap_le_att_listen_and_accept(bdaddr_t *src, int sec) >>> +{ >>> + int sk, nsk; >>> + struct sockaddr_l2 srcaddr, addr; >>> + socklen_t optlen; >>> + struct bt_security btsec; >>> + char ba[18]; >>> + >>> + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); >>> + if (sk < 0) { >>> + perror("Failed to create L2CAP socket"); >>> + return -1; >>> + } >>> + >>> + /* Set up source address */ >>> + memset(&srcaddr, 0, sizeof(srcaddr)); >>> + srcaddr.l2_family = AF_BLUETOOTH; >>> + srcaddr.l2_cid = htobs(ATT_CID); >>> + srcaddr.l2_bdaddr_type = 0; >>> + bacpy(&srcaddr.l2_bdaddr, src); >>> + >>> + if (bind(sk, (struct sockaddr *)&srcaddr, sizeof(srcaddr)) < 0) { >>> + perror("Failed to bind L2CAP socket"); >>> + goto fail; >>> + } >>> + >>> + /* Set the security level */ >>> + memset(&btsec, 0, sizeof(btsec)); >>> + btsec.level = sec; >>> + if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &btsec, >>> + sizeof(btsec)) != 0) { >>> + fprintf(stderr, "Failed to set L2CAP security level\n"); >>> + goto fail; >>> + } >>> + >>> + if (listen(sk, 10) < 0) { >>> + perror("Listening on socket failed"); >>> + goto fail; >>> + } >>> + >>> + printf("Started listening on ATT channel. Waiting for connections\n"); >>> + >>> + memset(&addr, 0, sizeof(addr)); >>> + optlen = sizeof(addr); >>> + nsk = accept(sk, (struct sockaddr *)&addr, &optlen); >>> + if (nsk < 0) { >>> + perror("Accept failed"); >>> + goto fail; >>> + } >>> + >>> + ba2str(&addr.l2_bdaddr, ba); >>> + printf("Connect from %s\n", ba); >>> + close(sk); >>> + >>> + return nsk; >>> + >>> +fail: >>> + close(sk); >>> + return -1; >>> +} >>> + >>> int main(int argc, char *argv[]) >>> { >>> int opt; >>> @@ -64,6 +249,8 @@ int main(int argc, char *argv[]) >>> uint16_t mtu = 0; >>> bdaddr_t src_addr; >>> int dev_id = -1; >>> + int fd; >>> + struct server *server; >>> >>> while ((opt = getopt_long(argc, argv, "+hvs:m:i:", >>> main_options, NULL)) != -1) { >>> @@ -133,7 +320,27 @@ int main(int argc, char *argv[]) >>> return EXIT_FAILURE; >>> } >>> >>> - /* TODO: Set up mainloop and listening LE socket */ >>> + fd = l2cap_le_att_listen_and_accept(&src_addr, sec); >>> + if (fd < 0) { >>> + fprintf(stderr, "Failed to accept L2CAP ATT connection\n"); >>> + return EXIT_FAILURE; >>> + } >>> + >>> + mainloop_init(); >>> + >>> + server = server_create(fd, mtu); >>> + if (!server) { >>> + close(fd); >>> + return EXIT_FAILURE; >>> + } >>> + >>> + printf("Running GATT server\n"); >>> + >>> + mainloop_run(); >>> + >>> + printf("\n\nShutting down...\n"); >>> + >>> + server_destroy(server); >>> >>> - return 0; >>> + return EXIT_SUCCESS; >>> } >>> -- >>> 2.1.0.rc2.206.gedb03e5 >> >> This one fails to link which is quite strange since if I continue with >> the next patch apparently fix it but it doesn't actually touch >> anything to change the build so maybe it is a symbol resolution thing. >> > > Yeah, I've hit this before but ignored it once it "fixed itself". I > can make that patch compile by adding lib/uuid.h and lib/uuid.c to the > libshared sources (since they all internally depend on it, I guess it > makes sense to put these there?) but I'm really curious why the > following patch fixes the issue. > Changing the order of the static libraries in the tools_btgatt_server_LDADD statement fixed the issue (i.e. first src/libshared-mainloop.la followed by lib/libbluetooth-internal.la). >> >> -- >> Luiz Augusto von Dentz > > Cheers, > Arman Cheers, Arman