Exemplo n.º 1
0
static void tcp_received(struct net_app_ctx *ctx,
			 struct net_pkt *pkt,
			 int status,
			 void *user_data)
{
	struct data *data = ctx->user_data;

	ARG_UNUSED(user_data);
	ARG_UNUSED(status);

	if (!pkt || net_pkt_appdatalen(pkt) == 0) {
		if (pkt) {
			net_pkt_unref(pkt);
		}

		return;
	}

	NET_DBG("Sent %d bytes, received %u bytes",
		data->expecting_tcp, net_pkt_appdatalen(pkt));

	if (!compare_tcp_data(pkt, data->expecting_tcp, data->received_tcp)) {
		NET_DBG("Data mismatch");
	} else {
		data->received_tcp += net_pkt_appdatalen(pkt);
	}

	if (data->expecting_tcp <= data->received_tcp) {
		/* Send more data */
		send_tcp_data(ctx, data);
	}

	net_pkt_unref(pkt);
}
Exemplo n.º 2
0
int udp_rx(void *context, unsigned char *buf, size_t size)
{
	struct udp_context *ctx = context;
	struct net_context *net_ctx = ctx->net_ctx;
	struct net_pkt *rx_pkt = NULL;
	struct net_buf *rx_buf;
	u16_t read_bytes;
	u8_t *ptr;
	int pos;
	int len;
	int rc;

	k_sem_take(&ctx->rx_sem, K_FOREVER);

	read_bytes = net_pkt_appdatalen(ctx->rx_pkt);
	if (read_bytes > size) {
		return -ENOMEM;
	}

	rx_pkt = ctx->rx_pkt;

	set_client_address(&net_ctx->remote, rx_pkt);

	ptr = net_pkt_appdata(rx_pkt);
	rx_buf = rx_pkt->frags;
	len = rx_buf->len - (ptr - rx_buf->data);
	pos = 0;

	while (rx_buf) {
		memcpy(buf + pos, ptr, len);
		pos += len;

		rx_buf = rx_buf->frags;
		if (!rx_buf) {
			break;
		}

		ptr = rx_buf->data;
		len = rx_buf->len;
	}

	net_pkt_unref(ctx->rx_pkt);
	ctx->rx_pkt = NULL;

	if (read_bytes != pos) {
		return -EIO;
	}

	rc = read_bytes;
	ctx->remaining = 0;

	return rc;
}
Exemplo n.º 3
0
static bool compare_tcp_data(struct net_pkt *pkt, int expecting_len,
			     int received_len)
{
	u8_t *ptr = net_pkt_appdata(pkt);
	const char *start;
	int pos = 0;
	struct net_buf *frag;
	int len;

	/* frag will point to first fragment with IP header in it.
	 */
	frag = pkt->frags;

	/* Do not include the protocol headers for the first fragment.
	 * The remaining fragments contain only data so the user data
	 * length is directly the fragment len.
	 */
	len = frag->len - (ptr - frag->data);

	start = lorem_ipsum + received_len;

	while (frag) {
		if (memcmp(ptr, start + pos, len)) {
			NET_DBG("Invalid data received");
			return false;
		}

		pos += len;

		frag = frag->frags;
		if (!frag) {
			break;
		}

		ptr = frag->data;
		len = frag->len;
	}

	NET_DBG("Compared %d bytes, all ok", net_pkt_appdatalen(pkt));

	return true;
}
Exemplo n.º 4
0
/* Receive encrypted data from network. Put that data into fifo
 * that will be read by https thread.
 */
static void ssl_received(struct net_context *context,
			 struct net_pkt *pkt,
			 int status,
			 void *user_data)
{
	struct http_client_ctx *http_ctx = user_data;
	struct rx_fifo_block *rx_data = NULL;
	struct k_mem_block block;
	int ret;

	ARG_UNUSED(context);
	ARG_UNUSED(status);

	if (pkt && !net_pkt_appdatalen(pkt)) {
		net_pkt_unref(pkt);
		return;
	}

	ret = k_mem_pool_alloc(http_ctx->https.pool, &block,
			       sizeof(struct rx_fifo_block),
			       BUF_ALLOC_TIMEOUT);
	if (ret < 0) {
		if (pkt) {
			net_pkt_unref(pkt);
		}

		return;
	}

	rx_data = block.data;
	rx_data->pkt = pkt;

	/* For freeing memory later */
	memcpy(&rx_data->block, &block, sizeof(struct k_mem_block));

	k_fifo_put(&http_ctx->https.mbedtls.ssl_ctx.rx_fifo, (void *)rx_data);

	/* Let the ssl_rx() to run */
	k_yield();
}
Exemplo n.º 5
0
static void recv_cb(struct net_context *net_ctx, struct net_pkt *pkt,
		    int status, void *data)
{
	struct http_client_ctx *ctx = data;

	ARG_UNUSED(net_ctx);

	if (status) {
		return;
	}

	if (!pkt || net_pkt_appdatalen(pkt) == 0) {
		/*
		 * This block most likely handles a TCP_FIN message.
		 * (this means the connection is now closed)
		 * If we get here, and req.wait.count is still 0 this means
		 * http client is still waiting to parse a response body.
		 * This will will never happen now.  Instead of generating
		 * an ETIMEDOUT error in the future, let's unlock the
		 * req.wait semaphore and let the app deal with whatever
		 * data was parsed in the header (IE: http status, etc).
		 */
		if (ctx->req.wait.count == 0) {
			k_sem_give(&ctx->req.wait);
		}

		goto out;
	}

	/* receive_cb must take ownership of the received packet */
	if (ctx->tcp.receive_cb) {
		ctx->tcp.receive_cb(ctx, pkt);
		return;
	}

out:
	if (pkt) {
		net_pkt_unref(pkt);
	}
}
Exemplo n.º 6
0
static inline void telnet_handle_input(struct net_pkt *pkt)
{
	struct console_input *input;
	u16_t len, offset, pos;

	len = net_pkt_appdatalen(pkt);
	if (len > CONSOLE_MAX_LINE_LEN || len < TELNET_MIN_MSG) {
		return;
	}

	if (telnet_handle_command(pkt)) {
		return;
	}

	if (!avail_queue || !input_queue) {
		return;
	}

	input = k_fifo_get(avail_queue, K_NO_WAIT);
	if (!input) {
		return;
	}

	offset = net_pkt_get_len(pkt) - len;
	net_frag_read(pkt->frags, offset, &pos, len, input->line);

	/* LF/CR will be removed if only the line is not NUL terminated */
	if (input->line[len-1] != NVT_NUL) {
		if (input->line[len-1] == NVT_LF) {
			input->line[len-1] = NVT_NUL;
		}

		if (input->line[len-2] == NVT_CR) {
			input->line[len-2] = NVT_NUL;
		}
	}

	k_fifo_put(input_queue, input);
}
Exemplo n.º 7
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *tmp;
	int header_len, recv_len, reply_len;

	printk("%s received %d bytes", name,
	      net_pkt_appdatalen(pkt));

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;
	/* Remove frag link so original pkt can be unrefed */
	pkt->frags = NULL;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	/* Add the entire chain into reply */
	net_pkt_frag_add(reply_pkt, tmp);

	reply_len = net_pkt_get_len(reply_pkt);

	printk("Received %d bytes, sending %d bytes", recv_len - header_len,
	       reply_len);

	return reply_pkt;
}
Exemplo n.º 8
0
int ssl_rx(void *context, unsigned char *buf, size_t size)
{
	struct http_client_ctx *ctx = context;
	struct rx_fifo_block *rx_data;
	u16_t read_bytes;
	u8_t *ptr;
	int pos;
	int len;
	int ret = 0;

	if (!ctx->https.mbedtls.ssl_ctx.frag) {
		rx_data = k_fifo_get(&ctx->https.mbedtls.ssl_ctx.rx_fifo,
				     K_FOREVER);
		if (!rx_data || !rx_data->pkt) {
			NET_DBG("Closing %p connection", ctx);

			if (rx_data) {
				k_mem_pool_free(&rx_data->block);
			}

			return MBEDTLS_ERR_SSL_CONN_EOF;
		}

		ctx->https.mbedtls.ssl_ctx.rx_pkt = rx_data->pkt;

		k_mem_pool_free(&rx_data->block);

		read_bytes = net_pkt_appdatalen(
					ctx->https.mbedtls.ssl_ctx.rx_pkt);

		ctx->https.mbedtls.ssl_ctx.remaining = read_bytes;
		ctx->https.mbedtls.ssl_ctx.frag =
			ctx->https.mbedtls.ssl_ctx.rx_pkt->frags;

		ptr = net_pkt_appdata(ctx->https.mbedtls.ssl_ctx.rx_pkt);
		len = ptr - ctx->https.mbedtls.ssl_ctx.frag->data;

		if (len > ctx->https.mbedtls.ssl_ctx.frag->size) {
			NET_ERR("Buf overflow (%d > %u)", len,
				ctx->https.mbedtls.ssl_ctx.frag->size);
			return -EINVAL;
		}

		/* This will get rid of IP header */
		net_buf_pull(ctx->https.mbedtls.ssl_ctx.frag, len);
	} else {
		read_bytes = ctx->https.mbedtls.ssl_ctx.remaining;
		ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
	}

	len = ctx->https.mbedtls.ssl_ctx.frag->len;
	pos = 0;
	if (read_bytes > size) {
		while (ctx->https.mbedtls.ssl_ctx.frag) {
			read_bytes = len < (size - pos) ? len : (size - pos);

#if RX_EXTRA_DEBUG == 1
			NET_DBG("Copying %d bytes", read_bytes);
#endif

			memcpy(buf + pos, ptr, read_bytes);

			pos += read_bytes;
			if (pos < size) {
				ctx->https.mbedtls.ssl_ctx.frag =
					ctx->https.mbedtls.ssl_ctx.frag->frags;
				ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
				len = ctx->https.mbedtls.ssl_ctx.frag->len;
			} else {
				if (read_bytes == len) {
					ctx->https.mbedtls.ssl_ctx.frag =
					ctx->https.mbedtls.ssl_ctx.frag->frags;
				} else {
					net_buf_pull(
					       ctx->https.mbedtls.ssl_ctx.frag,
					       read_bytes);
				}

				ctx->https.mbedtls.ssl_ctx.remaining -= size;
				return size;
			}
		}
	} else {
		while (ctx->https.mbedtls.ssl_ctx.frag) {
#if RX_EXTRA_DEBUG == 1
			NET_DBG("Copying all %d bytes", len);
#endif

			memcpy(buf + pos, ptr, len);

			pos += len;
			ctx->https.mbedtls.ssl_ctx.frag =
				ctx->https.mbedtls.ssl_ctx.frag->frags;
			if (!ctx->https.mbedtls.ssl_ctx.frag) {
				break;
			}

			ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
			len = ctx->https.mbedtls.ssl_ctx.frag->len;
		}

		net_pkt_unref(ctx->https.mbedtls.ssl_ctx.rx_pkt);
		ctx->https.mbedtls.ssl_ctx.rx_pkt = NULL;
		ctx->https.mbedtls.ssl_ctx.frag = NULL;
		ctx->https.mbedtls.ssl_ctx.remaining = 0;

		if (read_bytes != pos) {
			return -EIO;
		}

		ret = read_bytes;
	}

	return ret;
}
Exemplo n.º 9
0
static void http_receive_cb(struct http_client_ctx *ctx,
			    struct net_pkt *pkt)
{
	size_t start = ctx->rsp.data_len;
	size_t len = 0;
	struct net_buf *frag;
	int header_len;

	if (!pkt) {
		return;
	}

	/* Get rid of possible IP headers in the first fragment. */
	frag = pkt->frags;

	header_len = net_pkt_appdata(pkt) - frag->data;

	NET_DBG("Received %d bytes data", net_pkt_appdatalen(pkt));

	/* After this pull, the frag->data points directly to application data.
	 */
	net_buf_pull(frag, header_len);

	while (frag) {
		/* If this fragment cannot be copied to result buf,
		 * then parse what we have which will cause the callback to be
		 * called in function on_body(), and continue copying.
		 */
		if (ctx->rsp.data_len + frag->len > ctx->rsp.response_buf_len) {

			/* If the caller has not supplied a callback, then
			 * we cannot really continue if the response buffer
			 * overflows. Set the data_len to mark how many bytes
			 * should be needed in the response_buf.
			 */
			if (!ctx->rsp.cb) {
				ctx->rsp.data_len = net_pkt_get_len(pkt);
				goto out;
			}

			http_parser_execute(&ctx->parser,
					    &ctx->settings,
					    ctx->rsp.response_buf + start,
					    len);

			ctx->rsp.data_len = 0;
			len = 0;
			start = 0;
		}

		memcpy(ctx->rsp.response_buf + ctx->rsp.data_len,
		       frag->data, frag->len);

		ctx->rsp.data_len += frag->len;
		len += frag->len;
		frag = frag->frags;
	}

out:
	/* The parser's error can be catched outside, reading the
	 * http_errno struct member
	 */
	http_parser_execute(&ctx->parser, &ctx->settings,
			    ctx->rsp.response_buf + start, len);

	net_pkt_unref(pkt);
}
Exemplo n.º 10
0
/* This gets plain data and it sends encrypted one to peer */
static int https_send(struct net_pkt *pkt,
		      net_context_send_cb_t cb,
		      s32_t timeout,
		      void *token,
		      void *user_data)
{
	struct http_client_ctx *ctx = user_data;
	int ret;
	u16_t len;

	if (!ctx->rsp.response_buf || ctx->rsp.response_buf_len == 0) {
		NET_DBG("Response buf not setup");
		return -EINVAL;
	}

	len = net_pkt_appdatalen(pkt);
	if (len == 0) {
		NET_DBG("No application data to send");
		return -EINVAL;
	}

	ret = net_frag_linearize(ctx->rsp.response_buf,
				 ctx->rsp.response_buf_len,
				 pkt,
				 net_pkt_ip_hdr_len(pkt) +
				 net_pkt_ipv6_ext_opt_len(pkt),
				 len);
	if (ret < 0) {
		NET_DBG("Cannot linearize send data (%d)", ret);
		return ret;
	}

	if (ret != len) {
		NET_DBG("Linear copy error (%u vs %d)", len, ret);
		return -EINVAL;
	}

	do {
		ret = mbedtls_ssl_write(&ctx->https.mbedtls.ssl,
					ctx->rsp.response_buf, len);
		if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
			NET_ERR("peer closed the connection -0x%x", ret);
			goto out;
		}

		if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
		    ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
			if (ret < 0) {
				print_error("mbedtls_ssl_write returned -0x%x",
					    ret);
				goto out;
			}
		}
	} while (ret <= 0);

out:
	if (cb) {
		cb(net_pkt_context(pkt), ret, token, user_data);
	}

	return ret;
}
Exemplo n.º 11
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *frag, *tmp;
	int header_len, recv_len, reply_len;

	NET_INFO("%s received %d bytes", name,
		 net_pkt_appdatalen(pkt));

	if (net_pkt_appdatalen(pkt) == 0) {
		return NULL;
	}

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	NET_ASSERT(reply_pkt);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	NET_ASSERT(header_len < CONFIG_NET_BUF_DATA_SIZE);

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	while (tmp) {
		frag = net_pkt_get_data(context, K_FOREVER);

		if (!net_buf_headroom(tmp)) {
			/* If there is no link layer headers in the
			 * received fragment, then get rid of that also
			 * in the sending fragment. We end up here
			 * if MTU is larger than fragment size, this
			 * is typical for ethernet.
			 */
			net_buf_push(frag, net_buf_headroom(frag));

			frag->len = 0; /* to make fragment empty */

			/* Make sure to set the reserve so that
			 * in sending side we add the link layer
			 * header if needed.
			 */
			net_pkt_set_ll_reserve(reply_pkt, 0);
		}

		NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);

		memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);

		net_pkt_frag_add(reply_pkt, frag);

		tmp = net_pkt_frag_del(pkt, NULL, tmp);
	}

	reply_len = net_pkt_get_len(reply_pkt);

	NET_ASSERT_INFO((recv_len - header_len) == reply_len,
			"Received %d bytes, sending %d bytes",
			recv_len - header_len, reply_len);

	return reply_pkt;
}
Exemplo n.º 12
0
void http_rx_tx(struct net_context *net_ctx, struct net_pkt *rx, int status,
		void *user_data)
{
	struct http_server_ctx *http_ctx = NULL;
	struct net_buf *data = NULL;
	u16_t rcv_len;
	u16_t offset;
	int parsed_len;
	int rc;

	if (status) {
		printf("[%s:%d] Status code: %d, <%s>\n",
			__func__, __LINE__, status, RC_STR(status));
		goto lb_exit;
	}

	if (!user_data) {
		printf("[%s:%d] User data is null\n", __func__, __LINE__);
		goto lb_exit;
	}

	http_ctx = (struct http_server_ctx *)user_data;
	if (http_ctx->net_ctx != net_ctx) {
		printf("[%s:%d] Wrong network context received\n",
		       __func__, __LINE__);
		goto lb_exit;
	}

	if (!rx) {
		printf("[%s:%d] Connection closed by peer\n",
		       __func__, __LINE__);
		goto lb_exit;
	}

	rcv_len = net_pkt_appdatalen(rx);
	if (rcv_len == 0) {
		/* don't print info about zero-length app data buffers */
		goto lb_exit;
	}

	data = net_buf_alloc(&http_msg_pool, APP_SLEEP_MSECS);
	if (data == NULL) {
		printf("[%s:%d] Data buffer alloc error\n", __func__, __LINE__);
		goto lb_exit;
	}

	offset = net_pkt_get_len(rx) - rcv_len;
	rc = net_frag_linear_copy(data, rx->frags, offset, rcv_len);
	if (rc != 0) {
		printf("[%s:%d] Linear copy error\n", __func__, __LINE__);
		goto lb_exit;
	}

	data->data[min(data->size - 1, rcv_len)] = 0;

	parser_init(http_ctx);
	parsed_len = parser_parse_request(http_ctx, data);
	if (parsed_len <= 0) {
		printf("[%s:%d] Received: %u bytes, only parsed: %d bytes\n",
		       __func__, __LINE__, rcv_len, parsed_len);
	}

	if (http_ctx->parser.http_errno != HPE_OK) {
		http_response_400(http_ctx, NULL);
	} else {
		http_tx(http_ctx);
	}

lb_exit:
	net_pkt_frag_unref(data);
	net_pkt_unref(rx);

	http_ctx_release(http_ctx);
}