~vcs-imports/bluez/master

« back to all changes in this revision

Viewing changes to src/gatt-database.c

  • Committer: Luiz Augusto von Dentz
  • Date: 2019-02-06 11:12:00 UTC
  • Revision ID: git-v1:9eb2bf9f24e9b67400a165379113c0d230610897
gatt: Implement Robust Caching handling for server

This detects when a client becomes change-unware returning
DB Out of Sync error when that happens.

Show diffs side-by-side

added added

removed removed

Lines of Context:
180
180
        uint8_t bdaddr_type;
181
181
        unsigned int disc_id;
182
182
        uint8_t cli_feat[1];
 
183
        bool change_aware;
 
184
        bool out_of_sync;
183
185
        struct queue *ccc_states;
184
186
        struct notify *pending;
185
187
};
328
330
        DBG("");
329
331
 
330
332
        state->disc_id = 0;
 
333
        state->out_of_sync = false;
331
334
 
332
335
        device = btd_adapter_find_device(state->db->adapter, &state->bdaddr,
333
336
                                                        state->bdaddr_type);
1119
1122
        /* Shall we reallocate the feat array if bigger? */
1120
1123
        len = MIN(sizeof(state->cli_feat), len);
1121
1124
        while (len) {
1122
 
                state->cli_feat[len - 1] |= value[len -1];
 
1125
                state->cli_feat[len - 1] |= value[len - 1];
1123
1126
                len--;
1124
1127
        }
1125
1128
 
 
1129
        state->cli_feat[0] &= BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING;
 
1130
        state->change_aware = true;
 
1131
 
1126
1132
done:
1127
1133
        gatt_db_attribute_write_result(attrib, id, ecode);
1128
1134
}
1134
1140
{
1135
1141
        struct btd_gatt_database *database = user_data;
1136
1142
        const uint8_t *hash;
 
1143
        struct device_state *state;
 
1144
        bdaddr_t bdaddr;
 
1145
        uint8_t bdaddr_type;
1137
1146
 
1138
1147
        DBG("Database Hash read");
1139
1148
 
1140
1149
        hash = gatt_db_get_hash(database->db);
1141
1150
 
1142
1151
        gatt_db_attribute_read_result(attrib, id, 0, hash, 16);
 
1152
 
 
1153
        if (!get_dst_info(att, &bdaddr, &bdaddr_type))
 
1154
                return;
 
1155
 
 
1156
        state = find_device_state(database, &bdaddr, bdaddr_type);
 
1157
        if (state)
 
1158
                state->change_aware = true;
1143
1159
}
1144
1160
 
1145
1161
static void populate_gatt_service(struct btd_gatt_database *database)
1197
1213
 
1198
1214
static void service_changed_conf(void *user_data)
1199
1215
{
 
1216
        struct device_state *state = user_data;
 
1217
 
1200
1218
        DBG("");
 
1219
 
 
1220
        if (!state)
 
1221
                return;
 
1222
 
 
1223
        state->change_aware = true;
1201
1224
}
1202
1225
 
1203
1226
static void state_set_pending(struct device_state *state, struct notify *notify)
1239
1262
        struct btd_device *device;
1240
1263
        struct bt_gatt_server *server;
1241
1264
 
 
1265
        if (notify->conf == service_changed_conf) {
 
1266
                if (device_state->cli_feat[0] &
 
1267
                                BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING) {
 
1268
                        device_state->change_aware = false;
 
1269
                        notify->user_data = device_state;
 
1270
                }
 
1271
        }
 
1272
 
1242
1273
        ccc = find_ccc_state(device_state, notify->ccc_handle);
1243
1274
        if (!ccc)
1244
1275
                return;
3432
3463
        { }
3433
3464
};
3434
3465
 
 
3466
static uint8_t server_authorize(struct bt_att *att, uint8_t opcode,
 
3467
                                        uint16_t handle, void *user_data)
 
3468
{
 
3469
        struct btd_gatt_database *database = user_data;
 
3470
        struct device_state *state;
 
3471
        bdaddr_t bdaddr;
 
3472
        uint8_t bdaddr_type;
 
3473
 
 
3474
        if (!get_dst_info(att, &bdaddr, &bdaddr_type))
 
3475
                return 0;
 
3476
 
 
3477
        /* Skip if there is no device state */
 
3478
        state = find_device_state(database, &bdaddr, bdaddr_type);
 
3479
        if (!state)
 
3480
                return 0;
 
3481
 
 
3482
        /* Skip if client doesn't support Robust Caching */
 
3483
        if (!(state->cli_feat[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING))
 
3484
                return 0;
 
3485
 
 
3486
        if (state->change_aware)
 
3487
                return 0;
 
3488
 
 
3489
        if (state->out_of_sync) {
 
3490
                state->out_of_sync = false;
 
3491
                state->change_aware = true;
 
3492
                return 0;
 
3493
        }
 
3494
 
 
3495
        state->out_of_sync = true;
 
3496
 
 
3497
        return BT_ATT_ERROR_DB_OUT_OF_SYNC;
 
3498
}
 
3499
 
3435
3500
struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
3436
3501
{
3437
3502
        struct btd_gatt_database *database;
3493
3558
        if (!database->db_id)
3494
3559
                goto fail;
3495
3560
 
3496
 
 
3497
3561
        return database;
3498
3562
 
3499
3563
fail:
3522
3586
        return database->db;
3523
3587
}
3524
3588
 
3525
 
void btd_gatt_database_att_connected(struct btd_gatt_database *database,
3526
 
                                                struct bt_att *att)
 
3589
void btd_gatt_database_server_connected(struct btd_gatt_database *database,
 
3590
                                                struct bt_gatt_server *server)
3527
3591
{
 
3592
        struct bt_att *att = bt_gatt_server_get_att(server);
3528
3593
        struct device_state *state;
3529
3594
        bdaddr_t bdaddr;
3530
3595
        uint8_t bdaddr_type;
3532
3597
        if (!get_dst_info(att, &bdaddr, &bdaddr_type))
3533
3598
                return;
3534
3599
 
 
3600
        bt_gatt_server_set_authorize(server, server_authorize, database);
 
3601
 
3535
3602
        state = find_device_state(database, &bdaddr, bdaddr_type);
3536
3603
        if (!state || !state->pending)
3537
3604
                return;