Пример #1
0
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);
    }

}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
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);
}
Пример #5
0
/* 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);
	}
}
Пример #6
0
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;
		}
	}
}
Пример #7
0
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;
	}
}
Пример #8
0
/* 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);
	}
}
Пример #9
0
/* 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));
	}
}
Пример #10
0
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;
}
Пример #11
0
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;
}