static struct client *client_create(int fd, uint16_t mtu) { struct client *cli; struct bt_att *att; cli = new0(struct client, 1); if (!cli) { fprintf(stderr, "Failed to allocate memory for client\n"); return NULL; } att = bt_att_new(fd); if (!att) { fprintf(stderr, "Failed to initialze ATT transport layer\n"); bt_att_unref(att); free(cli); return NULL; } if (!bt_att_set_close_on_unref(att, true)) { fprintf(stderr, "Failed to set up ATT transport layer\n"); bt_att_unref(att); free(cli); return NULL; } if (!bt_att_register_disconnect(att, att_disconnect_cb, NULL, NULL)) { fprintf(stderr, "Failed to set ATT disconnect handler\n"); bt_att_unref(att); free(cli); return NULL; } cli->fd = fd; cli->gatt = bt_gatt_client_new(att, mtu); if (!cli->gatt) { fprintf(stderr, "Failed to create GATT client\n"); bt_att_unref(att); free(cli); return NULL; } if (verbose) { bt_att_set_debug(att, att_debug_cb, "att: ", NULL); bt_gatt_client_set_debug(cli->gatt, gatt_debug_cb, "gatt: ", NULL); } bt_gatt_client_set_ready_handler(cli->gatt, ready_cb, cli, NULL); bt_gatt_client_set_service_changed(cli->gatt, service_changed_cb, cli, NULL); /* bt_gatt_client already holds a reference */ bt_att_unref(att); return cli; }
GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu, bool ext_signed) { gint fd; GAttrib *attr; if (!io) return NULL; fd = g_io_channel_unix_get_fd(io); attr = new0(GAttrib, 1); if (!attr) return NULL; g_io_channel_ref(io); attr->io = io; attr->att = bt_att_new(fd, ext_signed); if (!attr->att) goto fail; bt_att_set_close_on_unref(attr->att, true); g_io_channel_set_close_on_unref(io, FALSE); if (!bt_att_set_mtu(attr->att, mtu)) goto fail; attr->buf = malloc0(mtu); attr->buflen = mtu; if (!attr->buf) goto fail; attr->callbacks = queue_new(); if (!attr->callbacks) goto fail; attr->track_ids = queue_new(); if (!attr->track_ids) goto fail; return g_attrib_ref(attr); fail: free(attr->buf); bt_att_unref(attr->att); g_io_channel_unref(io); free(attr); return NULL; }
static struct gatt_conn *gatt_conn_new(int fd) { struct gatt_conn *conn; uint16_t mtu = 0; conn = new0(struct gatt_conn, 1); if (!conn) return NULL; conn->att = bt_att_new(fd, false); if (!conn->att) { fprintf(stderr, "Failed to initialze ATT transport layer\n"); free(conn); return NULL; } bt_att_set_close_on_unref(conn->att, true); bt_att_register_disconnect(conn->att, gatt_conn_disconnect, conn, NULL); bt_att_set_security(conn->att, BT_SECURITY_MEDIUM); conn->gatt = bt_gatt_server_new(gatt_db, conn->att, mtu); if (!conn->gatt) { fprintf(stderr, "Failed to create GATT server\n"); bt_att_unref(conn->att); free(conn); return NULL; } conn->client = bt_gatt_client_new(gatt_cache, conn->att, mtu); if (!conn->gatt) { fprintf(stderr, "Failed to create GATT client\n"); bt_gatt_server_unref(conn->gatt); bt_att_unref(conn->att); free(conn); return NULL; } bt_gatt_client_set_ready_handler(conn->client, client_ready_callback, conn, NULL); bt_gatt_client_set_service_changed(conn->client, client_service_changed_callback, conn, NULL); return conn; }
static struct server *server_create(int fd, uint16_t mtu, bool hr_visible) { struct server *server; size_t name_len = strlen(test_device_name); server = new0(struct server, 1); if (!server) { fprintf(stderr, "Failed to allocate memory for server\n"); return NULL; } server->att = bt_att_new(fd, false); if (!server->att) { fprintf(stderr, "Failed to initialze ATT transport layer\n"); goto fail; } if (!bt_att_set_close_on_unref(server->att, true)) { fprintf(stderr, "Failed to set up ATT transport layer\n"); goto fail; } if (!bt_att_register_disconnect(server->att, att_disconnect_cb, NULL, NULL)) { fprintf(stderr, "Failed to set ATT disconnect handler\n"); goto fail; } server->name_len = name_len + 1; server->device_name = malloc(name_len + 1); if (!server->device_name) { fprintf(stderr, "Failed to allocate memory for device name\n"); goto fail; } memcpy(server->device_name, test_device_name, name_len); server->device_name[name_len] = '\0'; 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, server->att, mtu); if (!server->gatt) { fprintf(stderr, "Failed to create GATT server\n"); goto fail; } server->hr_visible = hr_visible; if (verbose) { bt_att_set_debug(server->att, att_debug_cb, "att: ", NULL); bt_gatt_server_set_debug(server->gatt, gatt_debug_cb, "server: ", NULL); } /* Random seed for generating fake Heart Rate measurements */ srand(time(NULL)); /* bt_gatt_server already holds a reference */ populate_db(server); return server; fail: gatt_db_unref(server->db); free(server->device_name); bt_att_unref(server->att); free(server); return NULL; }