* @ingroup pbuf * Create PBUF_RAM copies of pbufs. * * Used to queue packets on behalf of the lwIP stack, such as * ARP based queueing. * * @note You MUST explicitly use p = pbuf_take(p); * * @note Only one packet is copied, no packet queue! * * @param p_to pbuf destination of the copy * @param p_from pbuf source of the copy * * @return ERR_OK if pbuf was copied * ERR_ARG if
| 958 | * enough to hold p_from |
| 959 | */ |
| 960 | err_t |
| 961 | pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) |
| 962 | { |
| 963 | size_t offset_to = 0, offset_from = 0, len; |
| 964 | |
| 965 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", |
| 966 | (const void *)p_to, (const void *)p_from)); |
| 967 | |
| 968 | /* is the target big enough to hold the source? */ |
| 969 | LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && |
| 970 | (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); |
| 971 | |
| 972 | /* iterate through pbuf chain */ |
| 973 | do { |
| 974 | /* copy one part of the original chain */ |
| 975 | if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { |
| 976 | /* complete current p_from fits into current p_to */ |
| 977 | len = p_from->len - offset_from; |
| 978 | } else { |
| 979 | /* current p_from does not fit into current p_to */ |
| 980 | len = p_to->len - offset_to; |
| 981 | } |
| 982 | MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len); |
| 983 | offset_to += len; |
| 984 | offset_from += len; |
| 985 | LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); |
| 986 | LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); |
| 987 | if (offset_from >= p_from->len) { |
| 988 | /* on to next p_from (if any) */ |
| 989 | offset_from = 0; |
| 990 | p_from = p_from->next; |
| 991 | } |
| 992 | if (offset_to == p_to->len) { |
| 993 | /* on to next p_to (if any) */ |
| 994 | offset_to = 0; |
| 995 | p_to = p_to->next; |
| 996 | LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;); |
| 997 | } |
| 998 | |
| 999 | if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { |
| 1000 | /* don't copy more than one packet! */ |
| 1001 | LWIP_ERROR("pbuf_copy() does not allow packet queues!", |
| 1002 | (p_from->next == NULL), return ERR_VAL;); |
| 1003 | } |
| 1004 | if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { |
| 1005 | /* don't copy more than one packet! */ |
| 1006 | LWIP_ERROR("pbuf_copy() does not allow packet queues!", |
| 1007 | (p_to->next == NULL), return ERR_VAL;); |
| 1008 | } |
| 1009 | } while (p_from); |
| 1010 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); |
| 1011 | return ERR_OK; |
| 1012 | } |
| 1013 | |
| 1014 | /** |
| 1015 | * @ingroup pbuf |
no outgoing calls