/*---------------------------------------------------------------------------*/ static int prepare_and_send_buf(coap_context_t *ctx, session_t *session, uint8_t *data, size_t len) { struct net_buf *buf; int max_data_len; /* This net_buf gets sent to network, so it is not released * by this function unless there was an error and buf was * not actually sent. */ buf = ip_buf_get_tx(ctx->net_ctx); if (!buf) { len = -ENOBUFS; goto out; } max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN; PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__, data, len); if (len > max_data_len) { PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n", __FUNCTION__, len, max_data_len); ip_buf_unref(buf); len = -EINVAL; goto out; } /* Note that we have reversed the addresses here * because net_reply() will reverse them again. */ #ifdef CONFIG_NETWORKING_WITH_IPV6 uip_ip6addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip6addr_t *)&ctx->my_addr.in6_addr); uip_ip6addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip6addr_t *)&session->addr.ipaddr); #else uip_ip4addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip4addr_t *)&ctx->my_addr.in_addr); uip_ip4addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip4addr_t *)&session->addr.ipaddr); #endif NET_BUF_UDP(buf)->destport = uip_ntohs(ctx->my_port); NET_BUF_UDP(buf)->srcport = session->addr.port; uip_set_udp_conn(buf) = net_context_get_udp_connection(ctx->net_ctx); memcpy(net_buf_add(buf, len), data, len); ip_buf_appdatalen(buf) = len; ip_buf_appdata(buf) = buf->data + ip_buf_reserve(buf); if (net_reply(ctx->net_ctx, buf)) { ip_buf_unref(buf); } out: return len; }
static struct net_buf *ip_buf_get_reserve(enum ip_buf_type type, uint16_t reserve_head) #endif { struct net_buf *buf = NULL; /* Note that we do not reserve any space in front of the * buffer so buf->data points to first byte of the IP header. * This is done like this so that IP stack works the same * way as BT and 802.15.4 stacks. * * The reserve_head variable in the function will tell * the size of the IP + other headers if there are any. * That variable is only used to calculate the pointer * where the application data starts. */ switch (type) { case IP_BUF_RX: buf = net_buf_get(&free_rx_bufs, 0); dec_free_rx_bufs(buf); break; case IP_BUF_TX: buf = net_buf_get(&free_tx_bufs, 0); dec_free_tx_bufs(buf); break; } if (!buf) { #ifdef DEBUG_IP_BUFS NET_ERR("Failed to get free %s buffer (%s():%d)\n", type2str(type), caller, line); #else NET_ERR("Failed to get free %s buffer\n", type2str(type)); #endif return NULL; } ip_buf_type(buf) = type; ip_buf_appdata(buf) = buf->data + reserve_head; ip_buf_appdatalen(buf) = 0; ip_buf_reserve(buf) = reserve_head; net_buf_add(buf, reserve_head); NET_BUF_CHECK_IF_NOT_IN_USE(buf); #ifdef DEBUG_IP_BUFS NET_DBG("%s [%d] buf %p reserve %u ref %d (%s():%d)\n", type2str(type), get_frees(type), buf, reserve_head, buf->ref, caller, line); #else NET_DBG("%s buf %p reserve %u ref %d\n", type2str(type), buf, reserve_head, buf->ref); #endif return buf; }