⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pbuf.c

📁 uCOSII_lwip_lpc1768
💻 C
📖 第 1 页 / 共 3 页
字号:
 * * @param p pbuf to increase reference counter of * */voidpbuf_ref(struct pbuf *p){  SYS_ARCH_DECL_PROTECT(old_level);  /* pbuf given? */  if (p != NULL) {    SYS_ARCH_PROTECT(old_level);    ++(p->ref);    SYS_ARCH_UNPROTECT(old_level);  }}/** * Concatenate two pbufs (each may be a pbuf chain) and take over * the caller's reference of the tail pbuf. *  * @note The caller MAY NOT reference the tail pbuf afterwards. * Use pbuf_chain() for that purpose. *  * @see pbuf_chain() */voidpbuf_cat(struct pbuf *h, struct pbuf *t){  struct pbuf *p;  LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",             ((h != NULL) && (t != NULL)), return;);  /* proceed to last pbuf of chain */  for (p = h; p->next != NULL; p = p->next) {    /* add total length of second chain to all totals of first chain */    p->tot_len += t->tot_len;  }  /* { p is last pbuf of first h chain, p->next == NULL } */  LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);  LWIP_ASSERT("p->next == NULL", p->next == NULL);  /* add total length of second chain to last pbuf total of first chain */  p->tot_len += t->tot_len;  /* chain last pbuf of head (p) with first of tail (t) */  p->next = t;  /* p->next now references t, but the caller will drop its reference to t,   * so netto there is no change to the reference count of t.   */}/** * Chain two pbufs (or pbuf chains) together. *  * The caller MUST call pbuf_free(t) once it has stopped * using it. Use pbuf_cat() instead if you no longer use t. *  * @param h head pbuf (chain) * @param t tail pbuf (chain) * @note The pbufs MUST belong to the same packet. * @note MAY NOT be called on a packet queue. * * The ->tot_len fields of all pbufs of the head chain are adjusted. * The ->next field of the last pbuf of the head chain is adjusted. * The ->ref field of the first pbuf of the tail chain is adjusted. * */voidpbuf_chain(struct pbuf *h, struct pbuf *t){  pbuf_cat(h, t);  /* t is now referenced by h */  pbuf_ref(t);  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\r\n", (void *)h, (void *)t));}/** * Dechains the first pbuf from its succeeding pbufs in the chain. * * Makes p->tot_len field equal to p->len. * @param p pbuf to dechain * @return remainder of the pbuf chain, or NULL if it was de-allocated. * @note May not be called on a packet queue. */struct pbuf *pbuf_dechain(struct pbuf *p){  struct pbuf *q;  u8_t tail_gone = 1;  /* tail */  q = p->next;  /* pbuf has successor in chain? */  if (q != NULL) {    /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */    LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);    /* enforce invariant if assertion is disabled */    q->tot_len = p->tot_len - p->len;    /* decouple pbuf from remainder */    p->next = NULL;    /* total length of pbuf p is its own length only */    p->tot_len = p->len;    /* q is no longer referenced by p, free it */    LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\r\n", (void *)q));    tail_gone = pbuf_free(q);    if (tail_gone > 0) {      LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,                  ("pbuf_dechain: deallocated %p (as it is no longer referenced)\r\n", (void *)q));    }    /* return remaining tail or NULL if deallocated */  }  /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */  LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);  return ((tail_gone > 0) ? NULL : q);}/** * * 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 one of the pbufs is NULL or p_to is not big *                 enough to hold p_from */err_tpbuf_copy(struct pbuf *p_to, struct pbuf *p_from){  u16_t offset_to=0, offset_from=0, len;  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\r\n",    (void*)p_to, (void*)p_from));  /* is the target big enough to hold the source? */  LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&             (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);  /* iterate through pbuf chain */  do  {    LWIP_ASSERT("p_to != NULL", p_to != NULL);    /* copy one part of the original chain */    if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {      /* complete current p_from fits into current p_to */      len = p_from->len - offset_from;    } else {      /* current p_from does not fit into current p_to */      len = p_to->len - offset_to;    }    MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len);    offset_to += len;    offset_from += len;    LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);    if (offset_to == p_to->len) {      /* on to next p_to (if any) */      offset_to = 0;      p_to = p_to->next;    }    LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);    if (offset_from >= p_from->len) {      /* on to next p_from (if any) */      offset_from = 0;      p_from = p_from->next;    }    if((p_from != NULL) && (p_from->len == p_from->tot_len)) {      /* don't copy more than one packet! */      LWIP_ERROR("pbuf_copy() does not allow packet queues!\r\n",                 (p_from->next == NULL), return ERR_VAL;);    }    if((p_to != NULL) && (p_to->len == p_to->tot_len)) {      /* don't copy more than one packet! */      LWIP_ERROR("pbuf_copy() does not allow packet queues!\r\n",                  (p_to->next == NULL), return ERR_VAL;);    }  } while (p_from);  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\r\n"));  return ERR_OK;}/** * Copy (part of) the contents of a packet buffer * to an application supplied buffer. * * @param buf the pbuf from which to copy data * @param dataptr the application supplied buffer * @param len length of data to copy (dataptr must be big enough). No more  * than buf->tot_len will be copied, irrespective of len * @param offset offset into the packet buffer from where to begin copying len bytes * @return the number of bytes copied, or 0 on failure */u16_tpbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset){  struct pbuf *p;  u16_t left;  u16_t buf_copy_len;  u16_t copied_total = 0;  LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);  LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);  left = 0;  if((buf == NULL) || (dataptr == NULL)) {    return 0;  }  /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */  for(p = buf; len != 0 && p != NULL; p = p->next) {    if ((offset != 0) && (offset >= p->len)) {      /* don't copy from this buffer -> on to the next */      offset -= p->len;    } else {      /* copy from this buffer. maybe only partially. */      buf_copy_len = p->len - offset;      if (buf_copy_len > len)          buf_copy_len = len;      /* copy the necessary parts of the buffer */      MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);      copied_total += buf_copy_len;      left += buf_copy_len;      len -= buf_copy_len;      offset = 0;    }  }  return copied_total;}/** * Copy application supplied data into a pbuf. * This function can only be used to copy the equivalent of buf->tot_len data. * * @param buf pbuf to fill with data * @param dataptr application supplied data buffer * @param len length of the application supplied data buffer * * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough */err_tpbuf_take(struct pbuf *buf, const void *dataptr, u16_t len){  struct pbuf *p;  u16_t buf_copy_len;  u16_t total_copy_len = len;  u16_t copied_total = 0;  LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);  LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);  if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {    return ERR_ARG;  }  /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */  for(p = buf; total_copy_len != 0; p = p->next) {    LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);    buf_copy_len = total_copy_len;    if (buf_copy_len > p->len) {      /* this pbuf cannot hold all remaining data */      buf_copy_len = p->len;    }    /* copy the necessary parts of the buffer */    MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);    total_copy_len -= buf_copy_len;    copied_total += buf_copy_len;  }  LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);  return ERR_OK;}/** * Creates a single pbuf out of a queue of pbufs. * * @remark: The source pbuf 'p' is not freed by this function because that can *          be illegal in some places! * * @param p the source pbuf * @param layer pbuf_layer of the new pbuf * * @return a new, single pbuf (p->next is NULL) *         or the old pbuf if allocation fails */struct pbuf*pbuf_coalesce(struct pbuf *p, pbuf_layer layer){  struct pbuf *q;  err_t err;  if (p->next == NULL) {    return p;  }  q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);  if (q == NULL) {    /* @todo: what do we do now? */    return p;  }  err = pbuf_copy(q, p);  LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);  pbuf_free(p);  return q;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -