static bool net_pkt_is_compact(struct net_pkt *pkt) { struct net_buf *frag, *last; size_t total = 0, calc; int count = 0; last = NULL; frag = pkt->frags; while (frag) { total += frag->len; count++; last = frag; frag = frag->frags; } NET_ASSERT(last); if (!last) { return false; } calc = count * (last->size) - net_buf_tailroom(last) - count * (net_buf_headroom(last)); if (total == calc) { return true; } NET_DBG("Not compacted total %zu real %zu", total, calc); return false; }
static inline struct net_nbr *get_nbr(struct net_nbr *start, int idx) { NET_ASSERT(idx < CONFIG_NET_IPV6_MAX_NEIGHBORS); return (struct net_nbr *)((void *)start + ((sizeof(struct net_nbr) + start->size) * idx)); }
/* Called by driver when an IP packet has been received */ int net_recv_data(struct net_if *iface, struct net_pkt *pkt) { NET_ASSERT(pkt && pkt->frags); NET_ASSERT(iface); if (!pkt->frags) { return -ENODATA; } if (!atomic_test_bit(iface->flags, NET_IF_UP)) { return -ENETDOWN; } NET_DBG("fifo %p iface %p pkt %p len %zu", &rx_queue, iface, pkt, net_pkt_get_len(pkt)); net_pkt_set_iface(pkt, iface); k_fifo_put(&rx_queue, pkt); return 0; }
int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr) { ARG_UNUSED(lladdr); if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) { return -EALREADY; } NET_ASSERT(nbr->idx < CONFIG_NET_IPV6_MAX_NEIGHBORS); NET_ASSERT(net_neighbor_lladdr[nbr->idx].ref > 0); net_neighbor_lladdr[nbr->idx].ref--; if (!net_neighbor_lladdr[nbr->idx].ref) { memset(net_neighbor_lladdr[nbr->idx].lladdr.addr, 0, sizeof(net_neighbor_lladdr[nbr->idx].lladdr.storage)); } nbr->idx = NET_NBR_LLADDR_UNKNOWN; nbr->iface = NULL; return 0; }
struct net_pkt *net_ipv4_create(struct net_context *context, struct net_pkt *pkt, const struct in_addr *src, const struct in_addr *dst) { NET_ASSERT(((struct sockaddr_in_ptr *)&context->local)->sin_addr); if (!src) { src = ((struct sockaddr_in_ptr *)&context->local)->sin_addr; } if (net_is_ipv4_addr_unspecified(src) || net_is_ipv4_addr_mcast(src)) { src = &net_pkt_iface(pkt)->ipv4.unicast[0].address.in_addr; } return net_ipv4_create_raw(pkt, src, dst, net_context_get_iface(context), net_context_get_ip_proto(context)); }
bool WriteTGA( const char filename[], int width, int height, uint8_t * ptr ) { FILE * file = fopen( filename, "wb" ); if ( !file ) return false; putc( 0, file ); putc( 0, file ); putc( 10, file ); /* compressed RGB */ putc( 0, file ); putc( 0, file ); putc( 0, file ); putc( 0, file ); putc( 0, file ); putc( 0, file ); putc( 0, file ); /* X origin */ putc( 0, file ); putc( 0, file ); /* y origin */ putc( ( width & 0x00FF ),file ); putc( ( width & 0xFF00 ) >> 8,file ); putc( ( height & 0x00FF ), file ); putc( ( height & 0xFF00 ) >> 8, file ); putc( 24, file ); /* 24 bit bitmap */ putc( 0, file ); for ( int y = 0; y < height; ++y ) { uint8_t * line = ptr + width * 3 * y; uint8_t * end_of_line = line + width * 3; uint8_t * pixel = line; while ( true ) { if ( pixel >= end_of_line ) break; uint8_t * start = pixel; uint8_t * finish = pixel + 128 * 3; if ( finish > end_of_line ) finish = end_of_line; uint32_t previous = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2]; pixel += 3; int counter = 1; // RLE packet while ( pixel < finish ) { NET_ASSERT( pixel < end_of_line ); uint32_t current = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2]; if ( current != previous ) break; previous = current; pixel += 3; counter++; } if ( counter > 1 ) { NET_ASSERT( counter <= 128 ); putc( uint8_t( counter - 1 ) | 128, file ); putc( start[0], file ); putc( start[1], file ); putc( start[2], file ); continue; } // RAW packet while ( pixel < finish ) { NET_ASSERT( pixel < end_of_line ); uint32_t current = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2]; if ( current == previous ) break; previous = current; pixel += 3; counter++; } NET_ASSERT( counter >= 1 ); NET_ASSERT( counter <= 128 ); putc( uint8_t( counter - 1 ), file ); fwrite( start, counter * 3, 1, file ); } } fclose( file ); return true; }
static void https_handler(struct http_client_ctx *ctx, struct k_sem *startup_sync) { struct tx_fifo_block *tx_data; struct http_client_request req; size_t len; int ret; /* First mbedtls specific initialization */ ret = https_init(ctx); k_sem_give(startup_sync); if (ret < 0) { return; } reset: http_parser_init(&ctx->parser, HTTP_RESPONSE); ctx->rsp.data_len = 0; /* Wait that the sender sends the data, and the peer to respond to. */ tx_data = k_fifo_get(&ctx->https.mbedtls.ssl_ctx.tx_fifo, K_FOREVER); if (tx_data) { /* Because the req pointer might disappear as it is controlled * by application, copy the data here. */ memcpy(&req, tx_data->req, sizeof(req)); } else { NET_ASSERT(tx_data); goto reset; } print_info(ctx, ctx->req.method); /* If the connection is not active, then re-connect */ ret = tcp_connect(ctx); if (ret < 0 && ret != -EALREADY) { k_sem_give(&ctx->req.wait); goto reset; } mbedtls_ssl_session_reset(&ctx->https.mbedtls.ssl); mbedtls_ssl_set_bio(&ctx->https.mbedtls.ssl, ctx, ssl_tx, ssl_rx, NULL); /* SSL handshake. The ssl_rx() function will be called next by * mbedtls library. The ssl_rx() will block and wait that data is * received by ssl_received() and passed to it via fifo. After * receiving the data, this function will then proceed with secure * connection establishment. */ /* Waiting SSL handshake */ do { ret = mbedtls_ssl_handshake(&ctx->https.mbedtls.ssl); if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { goto close; } if (ret < 0) { print_error("mbedtls_ssl_handshake returned " "-0x%x", ret); goto close; } } } while (ret != 0); ret = http_request(ctx, &req, BUF_ALLOC_TIMEOUT); k_mem_pool_free(&tx_data->block); if (ret < 0) { NET_DBG("Send error (%d)", ret); goto close; } NET_DBG("Read HTTPS response"); do { len = ctx->rsp.response_buf_len - 1; memset(ctx->rsp.response_buf, 0, ctx->rsp.response_buf_len); ret = mbedtls_ssl_read(&ctx->https.mbedtls.ssl, ctx->rsp.response_buf, len); if (ret == 0) { goto close; } if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { continue; } if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { NET_DBG("Connection was closed gracefully"); goto close; } if (ret == MBEDTLS_ERR_NET_CONN_RESET) { NET_DBG("Connection was reset by peer"); goto close; } if (ret == -EIO) { NET_DBG("Response received, waiting another ctx %p", ctx); goto next; } if (ret < 0) { print_error("mbedtls_ssl_read returned -0x%x", ret); goto close; } /* The data_len will count how many bytes we have read, * this value is passed to user supplied response callback * by on_body() and on_message_complete() functions. */ ctx->rsp.data_len += ret; ret = http_parser_execute(&ctx->parser, &ctx->settings, ctx->rsp.response_buf, ret); if (!ret) { goto close; } ctx->rsp.data_len = 0; if (ret > 0) { /* Get more data */ ret = MBEDTLS_ERR_SSL_WANT_READ; } } while (ret < 0); close: /* If there is any pending data that have not been processed yet, * we need to free it here. */ if (ctx->https.mbedtls.ssl_ctx.rx_pkt) { 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; } NET_DBG("Resetting HTTPS connection %p", ctx); tcp_disconnect(ctx); next: mbedtls_ssl_close_notify(&ctx->https.mbedtls.ssl); goto reset; }
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; }