/ components / bt / esp_ble_mesh / mesh_core / proxy_client.c
proxy_client.c
   1  // Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  
   7  //     http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  #include <string.h>
  16  #include <errno.h>
  17  
  18  #include "mesh.h"
  19  #include "access.h"
  20  #include "beacon.h"
  21  #include "transport.h"
  22  #include "mesh_common.h"
  23  #include "foundation.h"
  24  #include "proxy_client.h"
  25  #include "provisioner_prov.h"
  26  #include "provisioner_main.h"
  27  #include "mesh_bearer_adapt.h"
  28  
  29  #define PDU_TYPE(data)      (data[0] & BIT_MASK(6))
  30  #define PDU_SAR(data)       (data[0] >> 6)
  31  
  32  #define PROXY_SAR_TIMEOUT   K_SECONDS(20)
  33  
  34  #define SAR_COMPLETE        0x00
  35  #define SAR_FIRST           0x01
  36  #define SAR_CONT            0x02
  37  #define SAR_LAST            0x03
  38  
  39  #define PDU_HDR(sar, type)  (sar << 6 | (type & BIT_MASK(6)))
  40  
  41  #define SERVER_BUF_SIZE     68
  42  
  43  #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
  44      CONFIG_BLE_MESH_GATT_PROXY_CLIENT
  45  
  46  static struct bt_mesh_proxy_server {
  47      struct bt_mesh_conn *conn;
  48      enum __packed {
  49          NONE,
  50          PROV,
  51          PROXY,
  52      } conn_type;
  53  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
  54      u16_t net_idx;
  55  #endif
  56      u8_t msg_type;
  57      struct k_delayed_work sar_timer;
  58      struct net_buf_simple buf;
  59  } servers[BLE_MESH_MAX_CONN];
  60  
  61  static u8_t server_buf_data[SERVER_BUF_SIZE * BLE_MESH_MAX_CONN];
  62  
  63  static struct bt_mesh_proxy_server *find_server(struct bt_mesh_conn *conn)
  64  {
  65      int i;
  66  
  67      for (i = 0; i < ARRAY_SIZE(servers); i++) {
  68          if (servers[i].conn == conn) {
  69              return &servers[i];
  70          }
  71      }
  72  
  73      return NULL;
  74  }
  75  
  76  static void proxy_sar_timeout(struct k_work *work)
  77  {
  78      struct bt_mesh_proxy_server *server = NULL;
  79  
  80      BT_WARN("%s", __func__);
  81  
  82      server = CONTAINER_OF(work, struct bt_mesh_proxy_server, sar_timer.work);
  83      if (!server || !server->conn) {
  84          BT_ERR("Invalid proxy server parameter");
  85          return;
  86      }
  87  
  88      net_buf_simple_reset(&server->buf);
  89      bt_mesh_gattc_disconnect(server->conn);
  90  }
  91  
  92  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
  93  /**
  94   * The following callbacks are used to notify proper information
  95   * to the application layer.
  96   */
  97  static proxy_client_recv_adv_cb_t proxy_client_adv_recv_cb;
  98  static proxy_client_connect_cb_t proxy_client_connect_cb;
  99  static proxy_client_disconnect_cb_t proxy_client_disconnect_cb;
 100  static proxy_client_recv_filter_status_cb_t proxy_client_filter_status_recv_cb;
 101  
 102  void bt_mesh_proxy_client_set_adv_recv_cb(proxy_client_recv_adv_cb_t cb)
 103  {
 104      proxy_client_adv_recv_cb = cb;
 105  }
 106  
 107  void bt_mesh_proxy_client_set_conn_cb(proxy_client_connect_cb_t cb)
 108  {
 109      proxy_client_connect_cb = cb;
 110  }
 111  
 112  void bt_mesh_proxy_client_set_disconn_cb(proxy_client_disconnect_cb_t cb)
 113  {
 114      proxy_client_disconnect_cb = cb;
 115  }
 116  
 117  void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_cb_t cb)
 118  {
 119      proxy_client_filter_status_recv_cb = cb;
 120  }
 121  
 122  static void filter_status(struct bt_mesh_proxy_server *server,
 123                            struct bt_mesh_net_rx *rx,
 124                            struct net_buf_simple *buf)
 125  {
 126      u8_t filter_type = 0U;
 127      u16_t list_size = 0U;
 128  
 129      if (buf->len != 3) {
 130          BT_ERR("Invalid Proxy Filter Status length %d", buf->len);
 131          return;
 132      }
 133  
 134      filter_type = net_buf_simple_pull_u8(buf);
 135      if (filter_type > 0x01) {
 136          BT_ERR("Invalid proxy filter type 0x%02x", filter_type);
 137          return;
 138      }
 139  
 140      list_size = net_buf_simple_pull_be16(buf);
 141  
 142      BT_INFO("filter_type 0x%02x, list_size %d", filter_type, list_size);
 143  
 144      if (proxy_client_filter_status_recv_cb) {
 145          proxy_client_filter_status_recv_cb(server - servers, rx->ctx.addr, server->net_idx, filter_type, list_size);
 146      }
 147  
 148      return;
 149  }
 150  
 151  static void proxy_cfg(struct bt_mesh_proxy_server *server)
 152  {
 153      NET_BUF_SIMPLE_DEFINE(buf, 29);
 154      struct bt_mesh_net_rx rx = {0};
 155      u8_t opcode = 0U;
 156      int err = 0;
 157  
 158      if (server->buf.len > 29) {
 159          BT_ERR("Too large proxy cfg pdu (len %d)", server->buf.len);
 160          return;
 161      }
 162  
 163      err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG,
 164                               &rx, &buf);
 165      if (err) {
 166          BT_ERR("Failed to decode Proxy Configuration (err %d)", err);
 167          return;
 168      }
 169  
 170      if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.addr)) {
 171          BT_ERR("Proxy Configuration from non-unicast addr 0x%04x", rx.ctx.addr);
 172          return;
 173      }
 174  
 175      rx.local_match = 1U;
 176  
 177      if (bt_mesh_rpl_check(&rx, NULL)) {
 178          BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
 179                  rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
 180          return;
 181      }
 182  
 183      /* Remove network headers */
 184      net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN);
 185  
 186      BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len));
 187  
 188      if (buf.len < 3) {
 189          BT_WARN("Too short proxy configuration PDU");
 190          return;
 191      }
 192  
 193      opcode = net_buf_simple_pull_u8(&buf);
 194  
 195      switch (opcode) {
 196      case BLE_MESH_PROXY_CFG_FILTER_STATUS:
 197          filter_status(server, &rx, &buf);
 198          break;
 199      default:
 200          BT_WARN("Unknown Proxy Configuration OpCode 0x%02x", opcode);
 201          break;
 202      }
 203  }
 204  #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
 205  
 206  static void proxy_complete_pdu(struct bt_mesh_proxy_server *server)
 207  {
 208      switch (server->msg_type) {
 209  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 210      case BLE_MESH_PROXY_NET_PDU:
 211          BT_DBG("Mesh Network PDU");
 212          bt_mesh_net_recv(&server->buf, 0, BLE_MESH_NET_IF_PROXY);
 213          break;
 214      case BLE_MESH_PROXY_BEACON:
 215          BT_DBG("Mesh Beacon PDU");
 216          bt_mesh_beacon_recv(&server->buf, 0);
 217          break;
 218      case BLE_MESH_PROXY_CONFIG:
 219          BT_DBG("Mesh Configuration PDU");
 220          proxy_cfg(server);
 221          break;
 222  #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
 223  #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
 224      case BLE_MESH_PROXY_PROV:
 225          BT_DBG("Mesh Provisioning PDU");
 226          bt_mesh_provisioner_pb_gatt_recv(server->conn, &server->buf);
 227          break;
 228  #endif
 229      default:
 230          BT_WARN("Unhandled Message Type 0x%02x", server->msg_type);
 231          break;
 232      }
 233  
 234      net_buf_simple_reset(&server->buf);
 235  }
 236  
 237  #define ATTR_IS_PROV(uuid) (uuid == BLE_MESH_UUID_MESH_PROV_VAL)
 238  
 239  static ssize_t proxy_recv(struct bt_mesh_conn *conn,
 240                            const struct bt_mesh_gatt_attr *attr, const void *buf,
 241                            u16_t len, u16_t offset, u8_t flags)
 242  {
 243      struct bt_mesh_proxy_server *server = find_server(conn);
 244      const u8_t *data = buf;
 245      u16_t srvc_uuid = 0U;
 246  
 247      if (!server) {
 248          BT_ERR("No Proxy Server object found");
 249          return -ENOTCONN;
 250      }
 251  
 252      if (len < 1) {
 253          BT_WARN("Too small Proxy PDU");
 254          return -EINVAL;
 255      }
 256  
 257      srvc_uuid = bt_mesh_gattc_get_service_uuid(conn);
 258      if (!srvc_uuid) {
 259          BT_ERR("No service uuid found");
 260          return -ENOTCONN;
 261      }
 262  
 263      if (ATTR_IS_PROV(srvc_uuid) != (PDU_TYPE(data) == BLE_MESH_PROXY_PROV)) {
 264          BT_WARN("Proxy PDU type doesn't match GATT service uuid");
 265          return -EINVAL;
 266      }
 267  
 268      if (len - 1 > net_buf_simple_tailroom(&server->buf)) {
 269          BT_WARN("Too big proxy PDU");
 270          return -EINVAL;
 271      }
 272  
 273      switch (PDU_SAR(data)) {
 274      case SAR_COMPLETE:
 275          if (server->buf.len) {
 276              BT_WARN("Complete PDU while a pending incomplete one");
 277              return -EINVAL;
 278          }
 279  
 280          server->msg_type = PDU_TYPE(data);
 281          net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
 282          proxy_complete_pdu(server);
 283          break;
 284  
 285      case SAR_FIRST:
 286          if (server->buf.len) {
 287              BT_WARN("First PDU while a pending incomplete one");
 288              return -EINVAL;
 289          }
 290  
 291          k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT);
 292          server->msg_type = PDU_TYPE(data);
 293          net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
 294          break;
 295  
 296      case SAR_CONT:
 297          if (!server->buf.len) {
 298              BT_WARN("Continuation with no prior data");
 299              return -EINVAL;
 300          }
 301  
 302          if (server->msg_type != PDU_TYPE(data)) {
 303              BT_WARN("Unexpected message type in continuation");
 304              return -EINVAL;
 305          }
 306  
 307          k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT);
 308          net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
 309          break;
 310  
 311      case SAR_LAST:
 312          if (!server->buf.len) {
 313              BT_WARN("Last SAR PDU with no prior data");
 314              return -EINVAL;
 315          }
 316  
 317          if (server->msg_type != PDU_TYPE(data)) {
 318              BT_WARN("Unexpected message type in last SAR PDU");
 319              return -EINVAL;
 320          }
 321  
 322          k_delayed_work_cancel(&server->sar_timer);
 323          net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
 324          proxy_complete_pdu(server);
 325          break;
 326      }
 327  
 328      return len;
 329  }
 330  
 331  
 332  static int proxy_send(struct bt_mesh_conn *conn, const void *data, u16_t len)
 333  {
 334      BT_DBG("%u bytes: %s", len, bt_hex(data, len));
 335  
 336      return bt_mesh_gattc_write_no_rsp(conn, NULL, data, len);
 337  }
 338  
 339  static int proxy_segment_and_send(struct bt_mesh_conn *conn, u8_t type,
 340                                    struct net_buf_simple *msg)
 341  {
 342      u16_t mtu = 0U;
 343      int err = 0;
 344  
 345      if (conn == NULL) {
 346          BT_ERR("%s, Invalid parameter", __func__);
 347          return -EINVAL;
 348      }
 349  
 350      BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len,
 351             bt_hex(msg->data, msg->len));
 352  
 353      mtu = bt_mesh_gattc_get_mtu_info(conn);
 354      if (!mtu) {
 355          BT_ERR("Conn %p used to get mtu not exists", conn);
 356          return -ENOTCONN;
 357      }
 358  
 359      /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
 360      mtu -= 3;
 361      if (mtu > msg->len) {
 362          net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
 363          return proxy_send(conn, msg->data, msg->len);
 364      }
 365  
 366      net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
 367      err = proxy_send(conn, msg->data, mtu);
 368      net_buf_simple_pull(msg, mtu);
 369  
 370      while (msg->len) {
 371          if (msg->len + 1 < mtu) {
 372              net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
 373              err = proxy_send(conn, msg->data, msg->len);
 374              break;
 375          }
 376  
 377          net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
 378          err = proxy_send(conn, msg->data, mtu);
 379          net_buf_simple_pull(msg, mtu);
 380      }
 381  
 382      return err;
 383  }
 384  
 385  int bt_mesh_proxy_client_send(struct bt_mesh_conn *conn, u8_t type,
 386                                struct net_buf_simple *msg)
 387  {
 388      struct bt_mesh_proxy_server *server = find_server(conn);
 389  
 390      if (!server) {
 391          BT_ERR("No Proxy Server object found");
 392          return -ENOTCONN;
 393      }
 394  
 395      if ((server->conn_type == PROV) != (type == BLE_MESH_PROXY_PROV)) {
 396          BT_ERR("Invalid PDU type for Proxy Server");
 397          return -EINVAL;
 398      }
 399  
 400      return proxy_segment_and_send(conn, type, msg);
 401  }
 402  
 403  static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int id)
 404  {
 405      struct bt_mesh_proxy_server *server = NULL;
 406  
 407      if (!servers[id].conn) {
 408          server = &servers[id];
 409      }
 410  
 411      if (!server) {
 412          BT_ERR("No free Proxy Server objects");
 413          /** Disconnect current connection, clear part of prov_link
 414           *  information, like uuid, dev_addr, linking flag, etc.
 415           */
 416          bt_mesh_gattc_disconnect(conn);
 417          return;
 418      }
 419  
 420      server->conn = bt_mesh_conn_ref(conn);
 421      server->conn_type = NONE;
 422      net_buf_simple_reset(&server->buf);
 423  
 424      bt_mesh_gattc_exchange_mtu(id);
 425      return;
 426  }
 427  
 428  static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, u8_t reason)
 429  {
 430      struct bt_mesh_proxy_server *server = find_server(conn);
 431  
 432      BT_DBG("conn %p, handle is %d, reason 0x%02x", conn, conn->handle, reason);
 433  
 434      if (!server) {
 435          BT_ERR("No Proxy Server object found");
 436          return;
 437      }
 438  
 439  #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
 440      if (server->conn_type == PROV) {
 441          bt_mesh_provisioner_pb_gatt_close(conn, reason);
 442      }
 443  #endif
 444  
 445  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 446      if (server->conn_type == PROXY) {
 447          if (proxy_client_disconnect_cb) {
 448              proxy_client_disconnect_cb(addr, server - servers, server->net_idx, reason);
 449          }
 450      }
 451  #endif
 452  
 453      k_delayed_work_cancel(&server->sar_timer);
 454      server->conn = NULL;
 455      server->conn_type = NONE;
 456  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 457      server->net_idx = BLE_MESH_KEY_UNUSED;
 458  #endif
 459  
 460      return;
 461  }
 462  
 463  #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
 464  static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn)
 465  {
 466      struct bt_mesh_proxy_server *server = find_server(conn);
 467  
 468      if (!server) {
 469          BT_ERR("No Proxy Server object found");
 470          return -ENOTCONN;
 471      }
 472  
 473      if (server->conn_type == NONE) {
 474          server->conn_type = PROV;
 475  
 476          if (bt_mesh_provisioner_set_prov_conn(addr->val, server->conn)) {
 477              bt_mesh_gattc_disconnect(server->conn);
 478              return -EIO;
 479          }
 480          return bt_mesh_provisioner_pb_gatt_open(conn, addr->val);
 481      }
 482  
 483      return -ENOMEM;
 484  }
 485  
 486  static ssize_t prov_recv_ntf(struct bt_mesh_conn *conn, u8_t *data, u16_t len)
 487  {
 488      struct bt_mesh_proxy_server *server = find_server(conn);
 489  
 490      if (!server) {
 491          BT_ERR("No Proxy Server object found");
 492          return -ENOTCONN;
 493      }
 494  
 495      if (server->conn_type == PROV) {
 496          return proxy_recv(conn, NULL, data, len, 0, 0);
 497      }
 498  
 499      return -EINVAL;
 500  }
 501  
 502  int bt_mesh_proxy_client_prov_enable(void)
 503  {
 504      int i;
 505  
 506      BT_DBG("%s", __func__);
 507  
 508      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 509          if (servers[i].conn) {
 510              servers[i].conn_type = PROV;
 511          }
 512      }
 513  
 514      return 0;
 515  }
 516  
 517  int bt_mesh_proxy_client_prov_disable(void)
 518  {
 519      int i;
 520  
 521      BT_DBG("%s", __func__);
 522  
 523      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 524          struct bt_mesh_proxy_server *server = &servers[i];
 525  
 526          if (server->conn && server->conn_type == PROV) {
 527              bt_mesh_gattc_disconnect(server->conn);
 528              server->conn_type = NONE;
 529          }
 530      }
 531  
 532      return 0;
 533  }
 534  #endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */
 535  
 536  #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
 537  static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn)
 538  {
 539      struct bt_mesh_proxy_server *server = find_server(conn);
 540  
 541      if (!server) {
 542          BT_ERR("No Proxy Server object found");
 543          return -ENOTCONN;
 544      }
 545  
 546      if (server->conn_type == NONE) {
 547          server->conn_type = PROXY;
 548  
 549          if (proxy_client_connect_cb) {
 550              proxy_client_connect_cb(addr, server - servers, server->net_idx);
 551          }
 552          return 0;
 553      }
 554  
 555      return -EINVAL;
 556  }
 557  
 558  static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, u8_t *data, u16_t len)
 559  {
 560      struct bt_mesh_proxy_server *server = find_server(conn);
 561  
 562      if (!server) {
 563          BT_ERR("No Proxy Server object found");
 564          return -ENOTCONN;
 565      }
 566  
 567      if (server->conn_type == PROXY) {
 568          return proxy_recv(conn, NULL, data, len, 0, 0);
 569      }
 570  
 571      return -EINVAL;
 572  }
 573  
 574  /**
 575   * Currently proxy client doesn't need bt_mesh_proxy_client_gatt_enable()
 576   * and bt_mesh_proxy_client_gatt_disable() functions, and once they are
 577   * used, proxy client can be enabled to parse node_id_adv and net_id_adv
 578   * in order to support proxy client role.
 579   * And if gatt proxy is disabled, proxy client can stop handling these
 580   * two kinds of connectable advertising packets.
 581   */
 582  int bt_mesh_proxy_client_gatt_enable(void)
 583  {
 584      int i;
 585  
 586      BT_DBG("%s", __func__);
 587  
 588      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 589          if (servers[i].conn) {
 590              servers[i].conn_type = PROXY;
 591          }
 592      }
 593  
 594      /**
 595       * TODO:
 596       * Once at least one device has been provisioned, proxy client can be
 597       * set to allow receiving and parsing node_id & net_id adv packets,
 598       * and we may use a global flag to indicate this.
 599       */
 600  
 601      return 0;
 602  }
 603  
 604  int bt_mesh_proxy_client_gatt_disable(void)
 605  {
 606      int i;
 607  
 608      BT_DBG("%s", __func__);
 609  
 610      /**
 611       * TODO:
 612       * Once this function is invoked, proxy client shall stop handling
 613       * node_id & net_id adv packets, and if proxy connection exists,
 614       * it should be disconnected.
 615       */
 616  
 617      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 618          struct bt_mesh_proxy_server *server = &servers[i];
 619  
 620          if (server->conn && server->conn_type == PROXY) {
 621              bt_mesh_gattc_disconnect(server->conn);
 622              server->conn_type = NONE;
 623          }
 624      }
 625  
 626      return 0;
 627  }
 628  #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
 629  
 630  static struct bt_mesh_prov_conn_cb conn_callbacks = {
 631      .connected = proxy_connected,
 632      .disconnected = proxy_disconnected,
 633  #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
 634      .prov_write_descr = prov_write_ccc,
 635      .prov_notify = prov_recv_ntf,
 636  #endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */
 637  #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
 638      .proxy_write_descr = proxy_write_ccc,
 639      .proxy_notify = proxy_recv_ntf,
 640  #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
 641  };
 642  
 643  #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
 644  static struct bt_mesh_subnet *bt_mesh_is_net_id_exist(const u8_t net_id[8])
 645  {
 646      struct bt_mesh_subnet *sub = NULL;
 647      size_t size = 0U, i = 0U;
 648  
 649      size = bt_mesh_rx_netkey_size();
 650  
 651      for (i = 0U; i < size; i++) {
 652          sub = bt_mesh_rx_netkey_get(i);
 653          if (sub && !memcmp(sub->keys[sub->kr_flag].net_id, net_id, 8)) {
 654              return sub;
 655          }
 656      }
 657  
 658      return NULL;
 659  }
 660  
 661  void bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple *buf,
 662                                          const bt_mesh_addr_t *addr, s8_t rssi)
 663  {
 664      bt_mesh_proxy_adv_ctx_t ctx = {0};
 665      u8_t type = 0U;
 666  
 667      /* Check if connection reaches the maximum limitation */
 668      if (bt_mesh_gattc_get_free_conn_count() == 0) {
 669          BT_INFO("BLE connections for mesh reach max limit");
 670          return;
 671      }
 672  
 673      type = net_buf_simple_pull_u8(buf);
 674  
 675      switch (type) {
 676      case BLE_MESH_PROXY_ADV_NET_ID: {
 677          if (buf->len != sizeof(ctx.net_id.net_id)) {
 678              BT_WARN("Malformed Network ID");
 679              return;
 680          }
 681  
 682          struct bt_mesh_subnet *sub = NULL;
 683          sub = bt_mesh_is_net_id_exist(buf->data);
 684          if (!sub) {
 685              return;
 686          }
 687  
 688          memcpy(ctx.net_id.net_id, buf->data, buf->len);
 689          ctx.net_id.net_idx = sub->net_idx;
 690          break;
 691      }
 692      case BLE_MESH_PROXY_ADV_NODE_ID:
 693          /* Gets node identity information.
 694           * hash = aes-ecb(identity key, 16 octets(padding + random + src)) mod 2^64,
 695           * If Proxy Client wants to get src, it may encrypts multiple times and compare
 696           * the hash value (8 octets) with the received one.
 697           */
 698          return;
 699      default:
 700          BT_DBG("Unknown Mesh Proxy adv type 0x%02x", type);
 701          return;
 702      }
 703  
 704      if (proxy_client_adv_recv_cb) {
 705          proxy_client_adv_recv_cb(addr, type, &ctx, rssi);
 706      }
 707  }
 708  
 709  int bt_mesh_proxy_client_connect(const u8_t addr[6], u8_t addr_type, u16_t net_idx)
 710  {
 711      bt_mesh_addr_t remote_addr = {0};
 712      int result = 0;
 713  
 714      if (!addr || addr_type > BLE_MESH_ADDR_RANDOM) {
 715          BT_ERR("%s, Invalid parameter", __func__);
 716          return -EINVAL;
 717      }
 718  
 719      memcpy(remote_addr.val, addr, BLE_MESH_ADDR_LEN);
 720      remote_addr.type = addr_type;
 721  
 722      result = bt_mesh_gattc_conn_create(&remote_addr, BLE_MESH_UUID_MESH_PROXY_VAL);
 723      if (result < 0) {
 724          return result;
 725      }
 726  
 727      /* Store corresponding net_idx which can be used for sending Proxy Configuration */
 728      servers[result].net_idx = net_idx;
 729      return 0;
 730  }
 731  
 732  int bt_mesh_proxy_client_disconnect(u8_t conn_handle)
 733  {
 734      struct bt_mesh_conn *conn = NULL;
 735  
 736      if (conn_handle >= BLE_MESH_MAX_CONN) {
 737          BT_ERR("%s, Invalid parameter", __func__);
 738          return -EINVAL;
 739      }
 740  
 741      BT_DBG("conn_handle %d", conn_handle);
 742  
 743      conn = servers[conn_handle].conn;
 744      if (!conn) {
 745          BT_ERR("Not connected, conn handle %d", conn_handle);
 746          return -ENOTCONN;
 747      }
 748  
 749      bt_mesh_gattc_disconnect(conn);
 750      return 0;
 751  }
 752  
 753  bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, u16_t dst)
 754  {
 755      bool send = false;
 756      int err = 0;
 757      int i;
 758  
 759      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 760          struct bt_mesh_proxy_server *server = &servers[i];
 761          NET_BUF_SIMPLE_DEFINE(msg, 32);
 762  
 763          if (!server->conn || server->conn_type != PROXY) {
 764              continue;
 765          }
 766  
 767          /* Proxy PDU sending modifies the original buffer,
 768           * so we need to make a copy.
 769           */
 770          net_buf_simple_init(&msg, 1);
 771          net_buf_simple_add_mem(&msg, buf->data, buf->len);
 772  
 773          err = bt_mesh_proxy_client_send(server->conn, BLE_MESH_PROXY_NET_PDU, &msg);
 774          if (err) {
 775              BT_ERR("Failed to send proxy network message (err %d)", err);
 776          } else {
 777              BT_INFO("%u bytes to dst 0x%04x", buf->len, dst);
 778              send = true;
 779          }
 780      }
 781  
 782      return send;
 783  }
 784  
 785  static int beacon_send(struct bt_mesh_conn *conn, struct bt_mesh_subnet *sub)
 786  {
 787      NET_BUF_SIMPLE_DEFINE(buf, 23);
 788  
 789      net_buf_simple_init(&buf, 1);
 790      bt_mesh_beacon_create(sub, &buf);
 791  
 792      return bt_mesh_proxy_client_send(conn, BLE_MESH_PROXY_BEACON, &buf);
 793  }
 794  
 795  bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub)
 796  {
 797      bool send = false;
 798      int err = 0;
 799      int i;
 800  
 801      /* NULL means we send Secure Network Beacon on all subnets */
 802      if (!sub) {
 803  #if CONFIG_BLE_MESH_NODE
 804          if (bt_mesh_is_provisioned()) {
 805              for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
 806                  if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
 807                      send = bt_mesh_proxy_client_beacon_send(&bt_mesh.sub[i]);
 808                  }
 809              }
 810              return send;
 811          }
 812  #endif /* CONFIG_BLE_MESH_NODE */
 813  #if CONFIG_BLE_MESH_PROVISIONER
 814          if (bt_mesh_is_provisioner_en()) {
 815              for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
 816                  if (bt_mesh.p_sub[i] && bt_mesh.p_sub[i]->net_idx != BLE_MESH_KEY_UNUSED) {
 817                      send = bt_mesh_proxy_client_beacon_send(bt_mesh.p_sub[i]);
 818                  }
 819              }
 820              return send;
 821          }
 822  #endif /* CONFIG_BLE_MESH_PROVISIONER */
 823          return send;
 824      }
 825  
 826      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 827          if (servers[i].conn && servers[i].conn_type == PROXY) {
 828              err = beacon_send(servers[i].conn, sub);
 829              if (err) {
 830                  BT_ERR("Failed to send proxy beacon message (err %d)", err);
 831              } else {
 832                  send = true;
 833              }
 834          }
 835      }
 836  
 837      return send;
 838  }
 839  
 840  static int send_proxy_cfg(struct bt_mesh_conn *conn, u16_t net_idx, struct bt_mesh_proxy_cfg_pdu *cfg)
 841  {
 842      struct bt_mesh_msg_ctx ctx = {
 843          .net_idx  = net_idx,
 844          .app_idx  = BLE_MESH_KEY_UNUSED,        /* CTL shall be set to 1 */
 845          .addr     = BLE_MESH_ADDR_UNASSIGNED,   /* DST shall be set to the unassigned address */
 846          .send_ttl = 0U,                         /* TTL shall be set to 0 */
 847      };
 848      struct bt_mesh_net_tx tx = {
 849          .ctx = &ctx,
 850          .src = bt_mesh_primary_addr(),
 851      };
 852      struct net_buf_simple *buf = NULL;
 853      u16_t alloc_len = 0U;
 854      int err = 0;
 855  
 856      if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
 857          tx.sub = bt_mesh_subnet_get(net_idx);
 858      } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
 859          tx.sub = bt_mesh_provisioner_subnet_get(net_idx);
 860      }
 861      if (!tx.sub) {
 862          BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
 863          return -EIO;
 864      }
 865  
 866      switch (cfg->opcode) {
 867      case BLE_MESH_PROXY_CFG_FILTER_SET:
 868          if (cfg->set.filter_type > 0x01) {
 869              BT_ERR("Invalid proxy filter type 0x%02x", cfg->set.filter_type);
 870              return -EINVAL;
 871          }
 872  
 873          alloc_len = sizeof(cfg->opcode) + sizeof(cfg->set.filter_type);
 874          break;
 875      case BLE_MESH_PROXY_CFG_FILTER_ADD:
 876          if (cfg->add.addr == NULL || cfg->add.addr_num == 0) {
 877              BT_ERR("Empty proxy addr list to add");
 878              return -EINVAL;
 879          }
 880  
 881          alloc_len = sizeof(cfg->opcode) + (cfg->add.addr_num << 1);
 882          break;
 883      case BLE_MESH_PROXY_CFG_FILTER_REMOVE:
 884          if (cfg->remove.addr == NULL || cfg->remove.addr_num == 0) {
 885              BT_ERR("Empty proxy addr list to remove");
 886              return -EINVAL;
 887          }
 888  
 889          alloc_len = sizeof(cfg->opcode) + (cfg->remove.addr_num << 1);
 890          break;
 891      default:
 892          BT_ERR("Unknown Proxy Configuration opcode 0x%02x", cfg->opcode);
 893          return -EINVAL;
 894      }
 895  
 896      /**
 897       * For Proxy Configuration PDU:
 898       * 1 octet Proxy PDU type + 9 octets network pdu header + Tranport PDU + 8 octets NetMIC
 899       */
 900      buf = bt_mesh_alloc_buf(1 + BLE_MESH_NET_HDR_LEN + alloc_len + 8);
 901      if (!buf) {
 902          return -ENOMEM;
 903      }
 904  
 905      net_buf_simple_reset(buf);
 906      net_buf_simple_reserve(buf, 10);
 907  
 908      net_buf_simple_add_u8(buf, cfg->opcode);
 909      switch (cfg->opcode) {
 910      case BLE_MESH_PROXY_CFG_FILTER_SET:
 911          net_buf_simple_add_u8(buf, cfg->set.filter_type);
 912          break;
 913      case BLE_MESH_PROXY_CFG_FILTER_ADD:
 914          for (u16_t i = 0U; i < cfg->add.addr_num; i++) {
 915              net_buf_simple_add_le16(buf, cfg->add.addr[i]);
 916          }
 917          break;
 918      case BLE_MESH_PROXY_CFG_FILTER_REMOVE:
 919          for (u16_t i = 0U; i < cfg->remove.addr_num; i++) {
 920              net_buf_simple_add_le16(buf, cfg->remove.addr[i]);
 921          }
 922          break;
 923      }
 924  
 925      BT_DBG("len %u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
 926  
 927      err = bt_mesh_net_encode(&tx, buf, true);
 928      if (err) {
 929          BT_ERR("Encoding proxy message failed (err %d)", err);
 930          bt_mesh_free_buf(buf);
 931          return err;
 932      }
 933  
 934      err = bt_mesh_proxy_client_send(conn, BLE_MESH_PROXY_CONFIG, buf);
 935      if (err) {
 936          BT_ERR("Failed to send proxy cfg message (err %d)", err);
 937      }
 938  
 939      bt_mesh_free_buf(buf);
 940      return err;
 941  }
 942  
 943  int bt_mesh_proxy_client_cfg_send(u8_t conn_handle, u16_t net_idx,
 944                                    struct bt_mesh_proxy_cfg_pdu *pdu)
 945  {
 946      struct bt_mesh_conn *conn = NULL;
 947  
 948      if (conn_handle >= BLE_MESH_MAX_CONN || !pdu || pdu->opcode > BLE_MESH_PROXY_CFG_FILTER_REMOVE) {
 949          BT_ERR("%s, Invalid parameter", __func__);
 950          return -EINVAL;
 951      }
 952  
 953      BT_DBG("conn_handle %d, net_idx 0x%04x", conn_handle, net_idx);
 954  
 955      conn = servers[conn_handle].conn;
 956      if (!conn) {
 957          BT_ERR("Not connected, conn handle %d", conn_handle);
 958          return -ENOTCONN;
 959      }
 960  
 961      /**
 962       * Check if net_idx used to encrypt Proxy Configuration are the same
 963       * with the one added when creating proxy connection.
 964       */
 965      if (servers[conn_handle].net_idx != net_idx) {
 966          BT_ERR("NetKeyIndex 0x%04x mismatch, expect 0x%04x",
 967                  net_idx, servers[conn_handle].net_idx);
 968          return -EIO;
 969      }
 970  
 971      return send_proxy_cfg(conn, net_idx, pdu);
 972  }
 973  #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
 974  
 975  int bt_mesh_proxy_client_init(void)
 976  {
 977      int i;
 978  
 979      /* Initialize the server receive buffers */
 980      for (i = 0; i < ARRAY_SIZE(servers); i++) {
 981          struct bt_mesh_proxy_server *server = &servers[i];
 982  
 983          k_delayed_work_init(&server->sar_timer, proxy_sar_timeout);
 984          server->buf.size = SERVER_BUF_SIZE;
 985          server->buf.__buf = server_buf_data + (i * SERVER_BUF_SIZE);
 986  #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 987          server->net_idx = BLE_MESH_KEY_UNUSED;
 988  #endif
 989      }
 990  
 991      bt_mesh_gattc_conn_cb_register(&conn_callbacks);
 992  
 993  #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN && CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 994      bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD,
 995                                      BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV, NULL);
 996  #endif
 997  
 998      return 0;
 999  }
1000  
1001  #if CONFIG_BLE_MESH_DEINIT
1002  int bt_mesh_proxy_client_deinit(void)
1003  {
1004      int i;
1005  
1006      /* Initialize the server receive buffers */
1007      for (i = 0; i < ARRAY_SIZE(servers); i++) {
1008          struct bt_mesh_proxy_server *server = &servers[i];
1009          k_delayed_work_free(&server->sar_timer);
1010          memset(server, 0, sizeof(struct bt_mesh_proxy_server));
1011      }
1012  
1013      memset(server_buf_data, 0, sizeof(server_buf_data));
1014  
1015      bt_mesh_gattc_conn_cb_deregister();
1016  
1017      return 0;
1018  }
1019  #endif /* CONFIG_BLE_MESH_DEINIT */
1020  
1021  #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */