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; }
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; }
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; }
static inline bool telnet_handle_command(struct net_pkt *pkt) { struct telnet_simple_command *cmd = (struct telnet_simple_command *)net_pkt_appdata(pkt); if (cmd->iac != NVT_CMD_IAC) { return false; } #ifdef CONFIG_TELNET_CONSOLE_SUPPORT_COMMAND cmd = (struct telnet_simple_command *)l_start; SYS_LOG_DBG("Got a command %u/%u/%u", cmd->iac, cmd->op, cmd->opt); if (!k_sem_take(&cmd_lock, K_NO_WAIT)) { telnet_command_cpy(&telnet_cmd, cmd); k_sem_give(&cmd_lock); k_sem_give(&send_lock); } #endif /* CONFIG_TELNET_CONSOLE_SUPPORT_COMMAND */ return true; }
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; }
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); }
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; }