static void test_ipv6_multi_frags(void) { struct net_pkt *pkt; struct net_buf *frag; struct ipv6_hdr *ipv6; struct udp_hdr *udp; int bytes, remaining = strlen(example_data), pos = 0; /* Example of multi fragment scenario with IPv6 */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); /* Place the IP + UDP header in the first fragment */ if (!net_buf_tailroom(frag)) { ipv6 = (struct ipv6_hdr *)(frag->data); udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6)); if (net_buf_tailroom(frag) < sizeof(ipv6)) { printk("Not enough space for IPv6 header, " "needed %zd bytes, has %zd bytes\n", sizeof(ipv6), net_buf_tailroom(frag)); zassert_true(false, "No space for IPv6 header"); } net_buf_add(frag, sizeof(ipv6)); if (net_buf_tailroom(frag) < sizeof(udp)) { printk("Not enough space for UDP header, " "needed %zd bytes, has %zd bytes\n", sizeof(udp), net_buf_tailroom(frag)); zassert_true(false, "No space for UDP header"); } net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp)); net_pkt_set_appdatalen(pkt, 0); } net_pkt_frag_add(pkt, frag); /* Put some data to rest of the fragments */ frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); if (net_buf_tailroom(frag) - (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) { printk("Invalid number of bytes available in the buf, " "should be 0 but was %zd - %d\n", net_buf_tailroom(frag), CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE); zassert_true(false, "Invalid byte count"); } if (((int)net_buf_tailroom(frag) - remaining) > 0) { printk("We should have been out of space now, " "tailroom %zd user data len %zd\n", net_buf_tailroom(frag), strlen(example_data)); zassert_true(false, "Still space"); } while (remaining > 0) { int copy; bytes = net_buf_tailroom(frag); copy = remaining > bytes ? bytes : remaining; memcpy(net_buf_add(frag, copy), &example_data[pos], copy); DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy); pos += bytes; remaining -= bytes; if (net_buf_tailroom(frag) - (bytes - copy)) { printk("There should have not been any tailroom left, " "tailroom %zd\n", net_buf_tailroom(frag) - (bytes - copy)); zassert_true(false, "There is still tailroom left"); } net_pkt_frag_add(pkt, frag); if (remaining > 0) { frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); } } bytes = net_pkt_get_len(pkt); if (bytes != strlen(example_data)) { printk("Invalid number of bytes in message, %zd vs %d\n", strlen(example_data), bytes); zassert_true(false, "Invalid number of bytes"); } /* Normally one should not unref the fragment list like this * because it will leave the pkt->frags pointing to already * freed fragment. */ net_pkt_frag_unref(pkt->frags); zassert_not_null(pkt->frags, "Frag list empty"); pkt->frags = NULL; /* to prevent double free */ net_pkt_unref(pkt); }
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); }