static void beacon_send(struct k_work *work) { /* Don't send anything if we have an active provisioning link */ if (IS_ENABLED(CONFIG_BT_MESH_PROV) && bt_prov_active()) { k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL); return; } BT_DBG(""); if (bt_mesh_is_provisioned()) { update_beacon_observation(); secure_beacon_send(); /* Only resubmit if beaconing is still enabled */ if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED || bt_mesh.ivu_initiator) { k_delayed_work_submit(&beacon_timer, PROVISIONED_INTERVAL); } } else { unprovisioned_beacon_send(); k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL); } }
void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *ev) { struct bt_conn *conn; BT_DBG("handle %u role %u", ev->conn_handle, ev->role_slave); conn = conn_get(&ev->peer_bda); if (!conn) { BT_ERR("Unable to get bt_conn object"); return; } conn->handle = ev->conn_handle; conn->role = ev->role_slave ? BT_CONN_ROLE_SLAVE : BT_CONN_ROLE_MASTER; conn->interval = ev->conn_values.interval; conn->latency = ev->conn_values.latency; conn->timeout = ev->conn_values.supervision_to; bt_addr_le_copy(&conn->dst, &ev->peer_bda); k_delayed_work_init(&conn->update_work, le_conn_update); conn->state = BT_CONN_CONNECTED; notify_connected(conn); /* * Core 4.2 Vol 3, Part C, 9.3.12.2 * The Peripheral device should not perform a Connection Parameter * Update procedure within 5 s after establishing a connection. */ k_delayed_work_submit(&conn->update_work, conn->role == BT_HCI_ROLE_MASTER ? K_NO_WAIT : CONN_UPDATE_TIMEOUT); }
static int sm_do_deregister(int index) { struct zoap_packet request; struct net_pkt *pkt = NULL; struct zoap_pending *pending = NULL; struct zoap_reply *reply = NULL; int ret; ret = lwm2m_init_message(clients[index].net_ctx, &request, &pkt, ZOAP_TYPE_CON, ZOAP_METHOD_DELETE, 0, NULL, 0); if (ret) { goto cleanup; } zoap_add_option(&request, ZOAP_OPTION_URI_PATH, clients[index].server_ep, strlen(clients[index].server_ep)); pending = lwm2m_init_message_pending(&request, &clients[index].reg_server, pendings, NUM_PENDINGS); if (!pending) { ret = -ENOMEM; goto cleanup; } reply = zoap_reply_next_unused(replies, NUM_REPLIES); if (!reply) { SYS_LOG_ERR("No resources for waiting for replies."); ret = -ENOMEM; goto cleanup; } zoap_reply_init(reply, &request); reply->reply = do_deregister_reply_cb; SYS_LOG_INF("Deregister from '%s'", clients[index].server_ep); ret = lwm2m_udp_sendto(pkt, &clients[index].reg_server); if (ret < 0) { SYS_LOG_ERR("Error sending LWM2M packet (err:%d).", ret); goto cleanup; } zoap_pending_cycle(pending); k_delayed_work_submit(&retransmit_work, pending->timeout); set_sm_state(index, ENGINE_DEREGISTER_SENT); return ret; cleanup: lwm2m_init_message_cleanup(pkt, pending, reply); return ret; }
static void l2cap_chan_send_req(struct bt_l2cap_le_chan *chan, struct net_buf *buf, int32_t timeout) { /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part A] page 126: * * The value of this timer is implementation-dependent but the minimum * initial value is 1 second and the maximum initial value is 60 * seconds. One RTX timer shall exist for each outstanding signaling * request, including each Echo Request. The timer disappears on the * final expiration, when the response is received, or the physical * link is lost. */ if (timeout) { k_delayed_work_submit(&chan->chan.rtx_work, timeout); } else { k_delayed_work_cancel(&chan->chan.rtx_work); } bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_LE_SIG, buf); }
/* Prepare DHCPv4 Message request and send it to peer */ static void send_request(struct net_if *iface, bool renewal) { struct net_buf *buf; buf = prepare_message(iface, DHCPV4_MSG_TYPE_REQUEST); if (!buf) { goto fail; } if (!add_server_id(buf) || !add_req_ipaddr(buf) || !add_end(buf)) { goto fail; } setup_header(buf); if (net_send_data(buf) < 0) { goto fail; } if (renewal) { iface->dhcpv4.state = NET_DHCPV4_RENEWAL; } else { iface->dhcpv4.state = NET_DHCPV4_REQUEST; } iface->dhcpv4.attempts++; k_delayed_work_init(&iface->dhcpv4_timeout, dhcpv4_timeout); k_delayed_work_submit(&iface->dhcpv4_timeout, get_dhcpv4_timeout()); return; fail: NET_DBG("Message preparation failed"); if (!buf) { net_nbuf_unref(buf); } }
static void tx_thread(void) { BT_DBG(""); /* FIXME: make periodic sending */ h5_send(sync_req, HCI_3WIRE_LINK_PKT, sizeof(sync_req)); while (true) { struct net_buf *buf; u8_t type; BT_DBG("link_state %u", h5.link_state); switch (h5.link_state) { case UNINIT: /* FIXME: send sync */ k_sleep(100); break; case INIT: /* FIXME: send conf */ k_sleep(100); break; case ACTIVE: buf = net_buf_get(&h5.tx_queue, K_FOREVER); type = h5_get_type(buf); h5_send(buf->data, type, buf->len); /* buf is dequeued from tx_queue and queued to unack * queue. */ net_buf_put(&h5.unack_queue, buf); unack_queue_len++; k_delayed_work_submit(&retx_work, H5_TX_ACK_TIMEOUT); break; } } }
static void h5_process_complete_packet(u8_t *hdr) { struct net_buf *buf; BT_DBG(""); /* rx_ack should be in every packet */ h5.rx_ack = H5_HDR_ACK(hdr); if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) { /* For reliable packet increment next transmit ack number */ h5.tx_ack = (h5.tx_ack + 1) % 8; /* Submit delayed work to ack the packet */ k_delayed_work_submit(&ack_work, H5_RX_ACK_TIMEOUT); } h5_print_header(hdr, "RX: >"); process_unack(); buf = h5.rx_buf; h5.rx_buf = NULL; switch (H5_HDR_PKT_TYPE(hdr)) { case HCI_3WIRE_ACK_PKT: net_buf_unref(buf); break; case HCI_3WIRE_LINK_PKT: net_buf_put(&h5.rx_queue, buf); break; case HCI_EVENT_PKT: case HCI_ACLDATA_PKT: hexdump("=> ", buf->data, buf->len); bt_recv(buf); break; } }
/* Prepare DHCPv4 Discover message and broadcast it */ static void send_discover(struct net_if *iface) { struct net_buf *buf; iface->dhcpv4.xid++; buf = prepare_message(iface, DHCPV4_MSG_TYPE_DISCOVER); if (!buf) { goto fail; } if (!add_req_options(buf) || !add_end(buf)) { goto fail; } setup_header(buf); if (net_send_data(buf) < 0) { goto fail; } iface->dhcpv4.state = NET_DHCPV4_DISCOVER; k_delayed_work_init(&iface->dhcpv4_timeout, dhcpv4_timeout); k_delayed_work_submit(&iface->dhcpv4_timeout, get_dhcpv4_timeout()); return; fail: NET_DBG("Message preparation failed"); if (!buf) { net_nbuf_unref(buf); } }
/* TODO: Handles only DHCPv4 OFFER and ACK messages */ static inline void handle_dhcpv4_reply(struct net_if *iface, uint8_t msg_type) { /* * Check for previous state, reason behind this check is, if client * receives multiple OFFER messages, first one will be handled. * Rest of the replies are discarded. */ if (iface->dhcpv4.state == NET_DHCPV4_DISCOVER) { if (msg_type != NET_DHCPV4_OFFER) { NET_DBG("Reply not handled %d", msg_type); return; } /* Send DHCPv4 Request Message */ k_delayed_work_cancel(&iface->dhcpv4_timeout); send_request(iface, false); } else if (iface->dhcpv4.state == NET_DHCPV4_REQUEST || iface->dhcpv4.state == NET_DHCPV4_RENEWAL) { if (msg_type != NET_DHCPV4_ACK) { NET_DBG("Reply not handled %d", msg_type); return; } k_delayed_work_cancel(&iface->dhcpv4_timeout); switch (iface->dhcpv4.state) { case NET_DHCPV4_REQUEST: NET_INFO("Received: %s", net_sprint_ipv4_addr( &iface->dhcpv4.requested_ip)); if (!net_if_ipv4_addr_add(iface, &iface->dhcpv4.requested_ip, NET_ADDR_DHCP, iface->dhcpv4.lease_time)) { NET_DBG("Failed to add IPv4 addr to iface %p", iface); return; } break; case NET_DHCPV4_RENEWAL: /* TODO: if the renewal is success, update only * vlifetime on iface */ break; default: break; } iface->dhcpv4.attempts = 0; iface->dhcpv4.state = NET_DHCPV4_ACK; /* Start renewal time */ k_delayed_work_init(&iface->dhcpv4_t1_timer, dhcpv4_t1_timeout); k_delayed_work_submit(&iface->dhcpv4_t1_timer, get_dhcpv4_renewal_time(iface)); } }
static int sm_bootstrap_done(int index) { /* TODO: Fix this */ /* check that we should still use bootstrap */ if (clients[index].use_bootstrap) { #ifdef CONFIG_LWM2M_SECURITY_OBJ_SUPPORT int i; SYS_LOG_DBG("*** Bootstrap - checking for server info ..."); /* get the server URI */ if (sec_data->server_uri_len > 0) { /* TODO: Write endpoint parsing function */ #if 0 if (!parse_endpoint(sec_data->server_uri, sec_data->server_uri_len, &clients[index].reg_server)) { #else if (true) { #endif SYS_LOG_ERR("Failed to parse URI!"); } else { clients[index].has_registration_info = 1; clients[index].registered = 0; clients[index].bootstrapped++; } } else { SYS_LOG_ERR("** failed to parse URI"); } /* if we did not register above - then fail this and restart */ if (clients[index].bootstrapped == 0) { /* Not ready - Retry with the bootstrap server again */ set_sm_state(index, ENGINE_DO_BOOTSTRAP); } else { set_sm_state(index, ENGINE_DO_REGISTRATION); } } else { #endif set_sm_state(index, ENGINE_DO_REGISTRATION); } return 0; } static int sm_send_registration(int index, bool send_obj_support_data, zoap_reply_t reply_cb) { struct zoap_packet request; struct net_pkt *pkt = NULL; struct zoap_pending *pending = NULL; struct zoap_reply *reply = NULL; u8_t *payload; u16_t client_data_len, len; int ret = 0; /* remember the last reg time */ clients[index].last_update = k_uptime_get(); ret = lwm2m_init_message(clients[index].net_ctx, &request, &pkt, ZOAP_TYPE_CON, ZOAP_METHOD_POST, 0, NULL, 0); if (ret) { goto cleanup; } zoap_add_option(&request, ZOAP_OPTION_URI_PATH, LWM2M_RD_CLIENT_URI, strlen(LWM2M_RD_CLIENT_URI)); if (!clients[index].registered) { /* include client endpoint in URI QUERY on 1st registration */ zoap_add_option_int(&request, ZOAP_OPTION_CONTENT_FORMAT, LWM2M_FORMAT_APP_LINK_FORMAT); snprintf(query_buffer, sizeof(query_buffer) - 1, "lwm2m=%s", LWM2M_PROTOCOL_VERSION); zoap_add_option(&request, ZOAP_OPTION_URI_QUERY, query_buffer, strlen(query_buffer)); snprintf(query_buffer, sizeof(query_buffer) - 1, "ep=%s", clients[index].ep_name); zoap_add_option(&request, ZOAP_OPTION_URI_QUERY, query_buffer, strlen(query_buffer)); } else { /* include server endpoint in URI PATH otherwise */ zoap_add_option(&request, ZOAP_OPTION_URI_PATH, clients[index].server_ep, strlen(clients[index].server_ep)); } snprintf(query_buffer, sizeof(query_buffer) - 1, "lt=%d", clients[index].lifetime); zoap_add_option(&request, ZOAP_OPTION_URI_QUERY, query_buffer, strlen(query_buffer)); /* TODO: add supported binding query string */ if (send_obj_support_data) { /* generate the rd data */ client_data_len = lwm2m_get_rd_data(client_data, sizeof(client_data)); payload = zoap_packet_get_payload(&request, &len); if (!payload) { ret = -EINVAL; goto cleanup; } memcpy(payload, client_data, client_data_len); ret = zoap_packet_set_used(&request, client_data_len); if (ret) { goto cleanup; } } pending = lwm2m_init_message_pending(&request, &clients[index].reg_server, pendings, NUM_PENDINGS); if (!pending) { ret = -ENOMEM; goto cleanup; } reply = zoap_reply_next_unused(replies, NUM_REPLIES); if (!reply) { SYS_LOG_ERR("No resources for waiting for replies."); ret = -ENOMEM; goto cleanup; } zoap_reply_init(reply, &request); reply->reply = reply_cb; /* log the registration attempt */ SYS_LOG_DBG("registration sent [%s]", lwm2m_sprint_ip_addr(&clients[index].reg_server)); ret = lwm2m_udp_sendto(pkt, &clients[index].reg_server); if (ret < 0) { SYS_LOG_ERR("Error sending LWM2M packet (err:%d).", ret); goto cleanup; } zoap_pending_cycle(pending); k_delayed_work_submit(&retransmit_work, pending->timeout); return ret; cleanup: lwm2m_init_message_cleanup(pkt, pending, reply); return ret; } static int sm_do_registration(int index) { int ret = 0; if (clients[index].use_registration && !clients[index].registered && clients[index].has_registration_info) { ret = sm_send_registration(index, true, do_registration_reply_cb); if (!ret) { set_sm_state(index, ENGINE_REGISTRATION_SENT); } else { SYS_LOG_ERR("Registration err: %d", ret); } } return ret; }
static int sm_do_bootstrap(int index) { struct zoap_packet request; struct net_pkt *pkt = NULL; struct zoap_pending *pending = NULL; struct zoap_reply *reply = NULL; int ret = 0; if (clients[index].use_bootstrap && clients[index].bootstrapped == 0 && clients[index].has_bs_server_info) { ret = lwm2m_init_message(clients[index].net_ctx, &request, &pkt, ZOAP_TYPE_CON, ZOAP_METHOD_POST, 0, NULL, 0); if (ret) { goto cleanup; } zoap_add_option(&request, ZOAP_OPTION_URI_PATH, "bs", strlen("bs")); snprintf(query_buffer, sizeof(query_buffer) - 1, "ep=%s", clients[index].ep_name); zoap_add_option(&request, ZOAP_OPTION_URI_QUERY, query_buffer, strlen(query_buffer)); pending = lwm2m_init_message_pending(&request, &clients[index].bs_server, pendings, NUM_PENDINGS); if (!pending) { ret = -ENOMEM; goto cleanup; } reply = zoap_reply_next_unused(replies, NUM_REPLIES); if (!reply) { SYS_LOG_ERR("No resources for waiting for replies."); ret = -ENOMEM; goto cleanup; } zoap_reply_init(reply, &request); reply->reply = do_bootstrap_reply_cb; /* log the bootstrap attempt */ SYS_LOG_DBG("Register ID with bootstrap server [%s] as '%s'", lwm2m_sprint_ip_addr(&clients[index].bs_server), query_buffer); ret = lwm2m_udp_sendto(pkt, &clients[index].bs_server); if (ret < 0) { SYS_LOG_ERR("Error sending LWM2M packet (err:%d).", ret); goto cleanup; } zoap_pending_cycle(pending); k_delayed_work_submit(&retransmit_work, pending->timeout); set_sm_state(index, ENGINE_BOOTSTRAP_SENT); } return ret; cleanup: lwm2m_init_message_cleanup(pkt, pending, reply); return ret; }