You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/12/24 00:34:35 UTC

[6/6] incubator-mynewt-larva git commit: Fix bug: ATT server silent when read-type done!

Fix bug: ATT server silent when read-type done!


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/ba4a7ed2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/ba4a7ed2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/ba4a7ed2

Branch: refs/heads/master
Commit: ba4a7ed2b053c74533e1f7c4e8a5c60c2938c893
Parents: 51bd2b4
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Dec 23 14:50:30 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Dec 23 15:33:49 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_att_svr.c           |  20 +-
 net/nimble/host/src/test/ble_att_svr_test.c | 252 ++++++++++++++++++++++-
 2 files changed, 256 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ba4a7ed2/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 932e064..4975d65 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -961,14 +961,16 @@ ble_att_svr_tx_read_type_rsp(struct ble_hs_conn *conn,
     struct ble_att_svr_entry *entry;
     struct os_mbuf *txom;
     uint8_t *dptr;
+    int entry_written;
     int txomlen;
     int prev_attr_len;
     int attr_len;
     int rc;
 
     *att_err = 0;    /* Silence unnecessary warning. */
-    *err_handle = 0; /* Silence unnecessary warning. */
 
+    *err_handle = req->batq_start_handle;
+    entry_written = 0;
     prev_attr_len = 0;
 
     txom = ble_att_get_pkthdr();
@@ -1006,9 +1008,7 @@ ble_att_svr_tx_read_type_rsp(struct ble_hs_conn *conn,
             break;
         }
 
-        if (entry->ha_handle_id >= req->batq_start_handle &&
-            entry->ha_handle_id <= req->batq_end_handle) {
-
+        if (entry->ha_handle_id >= req->batq_start_handle) {
             rc = entry->ha_cb(entry->ha_handle_id, entry->ha_uuid,
                               BLE_ATT_ACCESS_OP_READ, &arg, entry->ha_cb_arg);
             if (rc != 0) {
@@ -1044,11 +1044,12 @@ ble_att_svr_tx_read_type_rsp(struct ble_hs_conn *conn,
 
             htole16(dptr + 0, entry->ha_handle_id);
             memcpy(dptr + 2, arg.ahc_read.attr_data, attr_len);
+            entry_written = 1;
         }
     }
 
 done:
-    if (OS_MBUF_PKTLEN(txom) == 0) {
+    if (!entry_written) {
         /* No matching attributes. */
         if (*att_err == 0) {
             *att_err = BLE_ATT_ERR_ATTR_NOT_FOUND;
@@ -1098,6 +1099,15 @@ ble_att_svr_rx_read_type(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
     rc = ble_att_read_type_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
     assert(rc == 0);
 
+    if (req.batq_start_handle > req.batq_end_handle ||
+        req.batq_start_handle == 0) {
+
+        att_err = BLE_ATT_ERR_INVALID_HANDLE;
+        err_handle = req.batq_start_handle;
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+
     switch ((*rxom)->om_len) {
     case BLE_ATT_READ_TYPE_REQ_SZ_16:
         uuid16 = le16toh((*rxom)->om_data + 5);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ba4a7ed2/net/nimble/host/src/test/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c
index 3562210..4b7372f 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -102,21 +102,21 @@ ble_att_svr_test_misc_attr_fn_r_group(uint16_t handle_id, uint8_t *uuid128,
 
     static uint8_t vals[20][16] = {
         [1] =   { 0x22, 0x11 },
-        [2] =   { 0xdd, 0xdd },
-        [3] =   { 0xdd, 0xdd },
-        [4] =   { 0xdd, 0xdd },
-        [5] =   { 0xdd, 0xdd },
+        [2] =   { 0x01, 0x11 },
+        [3] =   { 0x02, 0x11 },
+        [4] =   { 0x03, 0x11 },
+        [5] =   { 0x04, 0x11 },
         [6] =   { 0x33, 0x22 },
-        [7] =   { 0xee, 0xee },
-        [8] =   { 0xee, 0xee },
-        [9] =   { 0xee, 0xee },
-        [10] =  { 0xee, 0xee },
+        [7] =   { 0x01, 0x22 },
+        [8] =   { 0x02, 0x22 },
+        [9] =   { 0x03, 0x22 },
+        [10] =  { 0x04, 0x22 },
         [11] =  { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
-        [12] =  { 0xdd, 0xdd },
+        [12] =  { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
         [13] =  { 0xdd, 0xdd },
-        [14] =  { 0xdd, 0xdd },
+        [14] =  { 0x55, 0x55 },
         [15] =  { 0xdd, 0xdd },
-        [16] =  { 0xdd, 0xdd },
+        [16] =  { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
         [17] =  { 0xdd, 0xdd },
         [18] =  { 0xdd, 0xdd },
         [19] =  { 0xdd, 0xdd },
@@ -544,6 +544,56 @@ ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
     TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
 }
 
+struct ble_att_svr_test_type_entry {
+    uint16_t handle;  /* 0 on last entry */
+    void *value;
+    int value_len;
+};
+
+/** Returns the number of entries successfully verified. */
+static void
+ble_att_svr_test_misc_verify_tx_read_type_rsp(
+    struct ble_l2cap_chan *chan,
+    struct ble_att_svr_test_type_entry *entries)
+{
+    struct ble_att_svr_test_type_entry *entry;
+    struct ble_att_read_type_rsp rsp;
+    struct os_mbuf *om;
+    uint16_t handle;
+    uint8_t buf[512];
+    int off;
+    int rc;
+
+    ble_hs_process_tx_data_queue();
+
+    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
+                        BLE_ATT_READ_TYPE_RSP_BASE_SZ);
+    TEST_ASSERT_FATAL(om != NULL);
+
+    rc = ble_att_read_type_rsp_parse(om->om_data, om->om_len, &rsp);
+    TEST_ASSERT(rc == 0);
+
+    off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
+    for (entry = entries; entry->handle != 0; entry++) {
+        TEST_ASSERT_FATAL(rsp.batp_length ==
+                          BLE_ATT_READ_TYPE_ADATA_BASE_SZ + entry->value_len);
+
+        rc = os_mbuf_copydata(om, off, 2, &handle);
+        TEST_ASSERT(rc == 0);
+        handle = le16toh(&handle);
+        TEST_ASSERT(handle == entry->handle);
+        off += 2;
+
+        rc = os_mbuf_copydata(om, off, entry->value_len, buf);
+        TEST_ASSERT(rc == 0);
+        TEST_ASSERT(memcmp(entry->value, buf, entry->value_len) == 0);
+        off += entry->value_len;
+    }
+
+    /* Ensure there is no extra data in the response. */
+    TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
+}
+
 static void
 ble_att_svr_test_misc_verify_tx_prep_write_rsp(struct ble_l2cap_chan *chan,
                                                uint16_t attr_handle,
@@ -1140,6 +1190,185 @@ TEST_CASE(ble_att_svr_test_find_type_value)
         } }));
 }
 
+TEST_CASE(ble_att_svr_test_read_type)
+{
+    struct ble_att_read_type_req req;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    uint8_t buf[BLE_ATT_READ_TYPE_REQ_SZ_16];
+    int rc;
+
+    ble_att_svr_test_misc_init(&conn, &chan);
+
+    /* Increase the MTU to 128 bytes to allow testing of long responses. */
+    chan->blc_my_mtu = 128;
+    chan->blc_peer_mtu = 128;
+    chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
+
+    /*** Start handle of 0. */
+    req.batq_start_handle = 0;
+    req.batq_end_handle = 0;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_PRIMARY_SERVICE);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc != 0);
+    ble_att_svr_test_misc_verify_tx_err_rsp(
+        chan, BLE_ATT_OP_READ_TYPE_REQ, 0,
+        BLE_ATT_ERR_INVALID_HANDLE);
+
+    /*** Start handle > end handle. */
+    req.batq_start_handle = 101;
+    req.batq_end_handle = 100;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_PRIMARY_SERVICE);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc != 0);
+    ble_att_svr_test_misc_verify_tx_err_rsp(
+        chan, BLE_ATT_OP_READ_TYPE_REQ, 101,
+        BLE_ATT_ERR_INVALID_HANDLE);
+
+    /*** No attributes. */
+    req.batq_start_handle = 1;
+    req.batq_end_handle = 0xffff;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_PRIMARY_SERVICE);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc != 0);
+    ble_att_svr_test_misc_verify_tx_err_rsp(
+        chan, BLE_ATT_OP_READ_TYPE_REQ, 1,
+        BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+    /*** Range too late. */
+    ble_att_svr_test_misc_register_group_attrs();
+    req.batq_start_handle = 200;
+    req.batq_end_handle = 300;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_PRIMARY_SERVICE);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc != 0);
+    ble_att_svr_test_misc_verify_tx_err_rsp(
+        chan, BLE_ATT_OP_READ_TYPE_REQ, 200,
+        BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+    /*** One characteristic from one service. */
+    req.batq_start_handle = 1;
+    req.batq_end_handle = 2;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_CHARACTERISTIC);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+    ble_att_svr_test_misc_verify_tx_read_type_rsp(chan,
+        ((struct ble_att_svr_test_type_entry[]) { {
+            .handle = 2,
+            .value = (uint8_t[]){ 0x01, 0x11 },
+            .value_len = 2,
+        }, {
+            .handle = 0,
+        } }));
+
+    /*** Both characteristics from one service. */
+    req.batq_start_handle = 1;
+    req.batq_end_handle = 10;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_CHARACTERISTIC);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+    ble_att_svr_test_misc_verify_tx_read_type_rsp(chan,
+        ((struct ble_att_svr_test_type_entry[]) { {
+            .handle = 2,
+            .value = (uint8_t[]){ 0x01, 0x11 },
+            .value_len = 2,
+        }, {
+            .handle = 4,
+            .value = (uint8_t[]){ 0x03, 0x11 },
+            .value_len = 2,
+        }, {
+            .handle = 0,
+        } }));
+
+    /*** Ensure 16-bit and 128-bit values are retrieved separately. */
+    req.batq_start_handle = 11;
+    req.batq_end_handle = 0xffff;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_CHARACTERISTIC);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+    ble_att_svr_test_misc_verify_tx_read_type_rsp(chan,
+        ((struct ble_att_svr_test_type_entry[]) { {
+            .handle = 12,
+            .value = (uint8_t[]){ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
+            .value_len = 16,
+        }, {
+            .handle = 0,
+        } }));
+
+    req.batq_start_handle = 13;
+    req.batq_end_handle = 0xffff;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_CHARACTERISTIC);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+    ble_att_svr_test_misc_verify_tx_read_type_rsp(chan,
+        ((struct ble_att_svr_test_type_entry[]) { {
+            .handle = 14,
+            .value = (uint8_t[]){ 0x55, 0x55 },
+            .value_len = 2,
+        }, {
+            .handle = 0,
+        } }));
+
+    req.batq_start_handle = 15;
+    req.batq_end_handle = 0xffff;
+
+    rc = ble_att_read_type_req_write(buf, sizeof buf, &req);
+    TEST_ASSERT(rc == 0);
+    htole16(buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ,
+            BLE_ATT_UUID_CHARACTERISTIC);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+    ble_att_svr_test_misc_verify_tx_read_type_rsp(chan,
+        ((struct ble_att_svr_test_type_entry[]) { {
+            .handle = 16,
+            .value = (uint8_t[]){ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
+            .value_len = 16,
+        }, {
+            .handle = 0,
+        } }));
+}
+
 TEST_CASE(ble_att_svr_test_read_group_type)
 {
     struct ble_att_read_group_type_req req;
@@ -1443,6 +1672,7 @@ TEST_SUITE(ble_att_svr_suite)
     ble_att_svr_test_write();
     ble_att_svr_test_find_info();
     ble_att_svr_test_find_type_value();
+    ble_att_svr_test_read_type();
     ble_att_svr_test_read_group_type();
     ble_att_svr_test_prep_write();
 }