亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? tcp_out.c

?? ARM7的一些試驗(yàn)程序
?? C
?? 第 1 頁 / 共 2 頁
字號:
/**
 * @file
 *
 * Transmission Control Protocol, outgoing traffic
 *
 * The output functions of TCP.
 *
 */

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *
 * Author: Adam Dunkels <adam@sics.se>
 *
 */

#include "lwip/def.h"
#include "lwip/opt.h"

#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"

#include "lwip/ip_addr.h"
#include "lwip/netif.h"

#include "lwip/inet.h"
#include "lwip/tcp.h"

#include "lwip/stats.h"

#if LWIP_TCP

/* Forward declarations.*/
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);

err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
  /* no data, no length, flags, copy=1, no optdata, no optdatalen */
  return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}

/**
 * Write data for sending (but does not send it immediately).
 *
 * It waits in the expectation of more data being sent soon (as
 * it can send them more efficiently by combining them together).
 * To prompt the system to send data now, call tcp_output() after
 * calling tcp_write().
 * 
 * @arg pcb Protocol control block of the TCP connection to enqueue data for. 
 * 
 * @see tcp_write()
 */

err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
    arg, len, (unsigned int)copy));
  /* connection is in valid state for data transmission? */
  if (pcb->state == ESTABLISHED ||
     pcb->state == CLOSE_WAIT ||
     pcb->state == SYN_SENT ||
     pcb->state == SYN_RCVD) {
    if (len > 0) {
      return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
    }
    return ERR_OK;
  } else {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
    return ERR_CONN;
  }
}

/**
 * Enqueue either data or TCP options (but not both) for tranmission
 * 
 * 
 * 
 * @arg pcb Protocol control block for the TCP connection to enqueue data for.
 * @arg arg Pointer to the data to be enqueued for sending.
 * @arg len Data length in bytes
 * @arg flags
 * @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
 * referenced.
 * @arg optdata
 * @arg optlen
 */
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
  u8_t flags, u8_t copy,
  u8_t *optdata, u8_t optlen)
{
  struct pbuf *p;
  struct tcp_seg *seg, *useg, *queue;
  u32_t left, seqno;
  u16_t seglen;
  void *ptr;
  u8_t queuelen;

  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
    (void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
  LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
      len == 0 || optlen == 0);
  LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
      arg == NULL || optdata == NULL);
  /* fail on too much data */
  if (len > pcb->snd_buf) {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
    return ERR_MEM;
  }
  left = len;
  ptr = arg;

  /* seqno will be the sequence number of the first segment enqueued
   * by the call to this function. */
  seqno = pcb->snd_lbb;

  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));

  /* If total number of pbufs on the unsent/unacked queues exceeds the
   * configured maximum, return an error */
  queuelen = pcb->snd_queuelen;
  if (queuelen >= TCP_SND_QUEUELEN) {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
    goto memerr;
  }
  if (queuelen != 0) {
    LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
      pcb->unacked != NULL || pcb->unsent != NULL);
  } else {
    LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
      pcb->unacked == NULL && pcb->unsent == NULL);
  }

  /* First, break up the data into segments and tuck them together in
   * the local "queue" variable. */
  useg = queue = seg = NULL;
  seglen = 0;
  while (queue == NULL || left > 0) {

    /* The segment length should be the MSS if the data to be enqueued
     * is larger than the MSS. */
    seglen = left > pcb->mss? pcb->mss: left;

    /* Allocate memory for tcp_seg, and fill in fields. */
    seg = memp_malloc(MEMP_TCP_SEG);
    if (seg == NULL) {
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
      goto memerr;
    }
    seg->next = NULL;
    seg->p = NULL;

    /* first segment of to-be-queued data? */
    if (queue == NULL) {
      queue = seg;
    }
    /* subsequent segments of to-be-queued data */
    else {
      /* Attach the segment to the end of the queued segments */
      LWIP_ASSERT("useg != NULL", useg != NULL);
      useg->next = seg;
    }
    /* remember last segment of to-be-queued data for next iteration */
    useg = seg;

    /* If copy is set, memory should be allocated
     * and data copied into pbuf, otherwise data comes from
     * ROM or other static memory, and need not be copied. If
     * optdata is != NULL, we have options instead of data. */
     
    /* options? */
    if (optdata != NULL) {
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
        goto memerr;
      }
      ++queuelen;
      seg->dataptr = seg->p->payload;
    }
    /* copy from volatile memory? */
    else if (copy) {
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
        goto memerr;
      }
      ++queuelen;
      if (arg != NULL) {
        memcpy(seg->p->payload, ptr, seglen);
      }
      seg->dataptr = seg->p->payload;
    }
    /* do not copy data */
    else {
      /* First, allocate a pbuf for holding the data.
       * since the referenced data is available at least until it is sent out on the
       * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
       * instead of PBUF_REF here.
       */
      if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
        goto memerr;
      }
      ++queuelen;
      /* reference the non-volatile payload data */
      p->payload = ptr;
      seg->dataptr = ptr;

      /* Second, allocate a pbuf for the headers. */
      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
        /* If allocation fails, we have to deallocate the data pbuf as
         * well. */
        pbuf_free(p);
        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
        goto memerr;
      }
      ++queuelen;

      /* Concatenate the headers and data pbufs together. */
      pbuf_cat(seg->p/*header*/, p/*data*/);
      p = NULL;
    }

    /* Now that there are more segments queued, we check again if the
    length of the queue exceeds the configured maximum. */
    if (queuelen > TCP_SND_QUEUELEN) {
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
      goto memerr;
    }

    seg->len = seglen;

    /* build TCP header */
    if (pbuf_header(seg->p, TCP_HLEN)) {
      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
      TCP_STATS_INC(tcp.err);
      goto memerr;
    }
    seg->tcphdr = seg->p->payload;
    seg->tcphdr->src = htons(pcb->local_port);
    seg->tcphdr->dest = htons(pcb->remote_port);
    seg->tcphdr->seqno = htonl(seqno);
    seg->tcphdr->urgp = 0;
    TCPH_FLAGS_SET(seg->tcphdr, flags);
    /* don't fill in tcphdr->ackno and tcphdr->wnd until later */

    /* Copy the options into the header, if they are present. */
    if (optdata == NULL) {
      TCPH_HDRLEN_SET(seg->tcphdr, 5);
    }
    else {
      TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
      /* Copy options into data portion of segment.
       Options can thus only be sent in non data carrying
       segments such as SYN|ACK. */
      memcpy(seg->dataptr, optdata, optlen);
    }
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
      ntohl(seg->tcphdr->seqno),
      ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
      flags));

    left -= seglen;
    seqno += seglen;
    ptr = (void *)((char *)ptr + seglen);
  }

  /* Now that the data to be enqueued has been broken up into TCP
  segments in the queue variable, we add them to the end of the
  pcb->unsent queue. */
  if (pcb->unsent == NULL) {
    useg = NULL;
  }
  else {
    for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
  }
  /* { useg is last segment on the unsent queue, NULL if list is empty } */

  /* If there is room in the last pbuf on the unsent queue,
  chain the first pbuf on the queue together with that. */
  if (useg != NULL &&
    TCP_TCPLEN(useg) != 0 &&
    !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
    !(flags & (TCP_SYN | TCP_FIN)) &&
    /* fit within max seg size */
    useg->len + queue->len <= pcb->mss) {
    /* Remove TCP header from first segment of our to-be-queued list */
    pbuf_header(queue->p, -TCP_HLEN);
    pbuf_cat(useg->p, queue->p);
    useg->len += queue->len;
    useg->next = queue->next;

    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %u\n", useg->len));
    if (seg == queue) {
      seg = NULL;
    }
    memp_free(MEMP_TCP_SEG, queue);
  }
  else {
    /* empty list */
    if (useg == NULL) {
      /* initialize list with this segment */
      pcb->unsent = queue;
    }
    /* enqueue segment */
    else {
      useg->next = queue;
    }
  }
  if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
    ++len;
  }
  pcb->snd_lbb += len;
  pcb->snd_buf -= len;
  /* update number of segments on the queues */
  pcb->snd_queuelen = queuelen;
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
  if (pcb->snd_queuelen != 0) {
    LWIP_ASSERT("tcp_enqueue: valid queue length",
      pcb->unacked != NULL || pcb->unsent != NULL);
  }

  /* Set the PSH flag in the last segment that we enqueued, but only
  if the segment has data (indicated by seglen > 0). */
  if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
  }

  return ERR_OK;
  memerr:
  TCP_STATS_INC(tcp.memerr);

  if (queue != NULL) {
    tcp_segs_free(queue);

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
美女视频免费一区| 日韩精品一级中文字幕精品视频免费观看 | 午夜在线电影亚洲一区| 在线看国产日韩| 亚洲妇熟xx妇色黄| 欧美一区二区免费观在线| 人人爽香蕉精品| 26uuu另类欧美| 99久久综合国产精品| 亚洲天堂精品在线观看| 欧美日韩精品免费观看视频| 奇米精品一区二区三区在线观看一| 日韩一区二区影院| 国产成人精品1024| 亚洲在线中文字幕| 91精品免费观看| 懂色一区二区三区免费观看| 国产精品久久久久久亚洲伦| 在线观看一区日韩| 精品一区二区三区不卡| 国产亲近乱来精品视频| 欧美无砖砖区免费| 国产在线视频一区二区| 亚洲视频一区二区在线观看| 538在线一区二区精品国产| 国产专区欧美精品| 亚洲欧美一区二区三区国产精品 | 美脚の诱脚舐め脚责91| 欧美国产综合一区二区| 欧美三级中文字幕在线观看| 久久精品免费看| 亚洲丝袜精品丝袜在线| 日韩欧美一区中文| 9i看片成人免费高清| 日日骚欧美日韩| 中文字幕一区二区三区在线播放 | 国产一区二区成人久久免费影院| 亚洲日本电影在线| 精品国产91久久久久久久妲己| 99国产精品久久久久| 精品一区二区三区免费视频| 亚洲综合偷拍欧美一区色| 久久综合色一综合色88| 欧美体内she精视频| 成人中文字幕电影| 久久不见久久见中文字幕免费| 亚洲日本护士毛茸茸| 国产午夜精品一区二区| 欧美一区二区日韩| 欧美日韩视频不卡| 91啦中文在线观看| 国产·精品毛片| 精品一区二区三区av| 日韩精品一二区| 亚洲影院久久精品| 国产精品二区一区二区aⅴ污介绍| 欧美一区二区精品久久911| 一本到三区不卡视频| 福利视频网站一区二区三区| 久久国产精品72免费观看| 首页国产丝袜综合| 亚洲成人资源在线| 亚洲码国产岛国毛片在线| 亚洲国产成人午夜在线一区| 久久久不卡网国产精品一区| 欧美www视频| 欧美一区二区三区免费视频| 欧美日韩高清在线播放| 欧美亚州韩日在线看免费版国语版| 国产不卡在线播放| 国产乱码精品一区二区三区av | 91精品国产综合久久香蕉麻豆| 欧美性色aⅴ视频一区日韩精品| 不卡一区中文字幕| 成人av手机在线观看| 成人久久18免费网站麻豆| 成人亚洲精品久久久久软件| 国产精华液一区二区三区| 国产麻豆精品在线| 国产成人鲁色资源国产91色综| 韩国女主播一区| 国产揄拍国内精品对白| 国产福利一区在线| 高清久久久久久| 成人在线综合网| 99re热这里只有精品视频| 99久久婷婷国产综合精品电影 | 麻豆精品一区二区| 激情文学综合插| 国产宾馆实践打屁股91| 高清av一区二区| 91免费国产视频网站| 色婷婷久久久综合中文字幕 | 一区二区三区四区亚洲| 一区二区三区在线免费观看| 亚洲福利一二三区| 日韩精品一级二级 | 欧美一区二区三区色| 日韩一区二区三区视频| 精品国产91洋老外米糕| 久久精品欧美一区二区三区不卡 | 欧美亚洲国产一区在线观看网站| 在线精品视频一区二区三四| 日韩一区二区三区在线视频| 久久精品夜夜夜夜久久| 亚洲人成精品久久久久久| 亚洲福利视频一区| 激情丁香综合五月| 不卡的av网站| 欧美二区三区91| 久久久久国产一区二区三区四区| 亚洲天堂精品视频| 日本中文字幕一区二区有限公司| 极品美女销魂一区二区三区 | 美日韩一级片在线观看| 国产99精品在线观看| 欧洲一区二区三区在线| 欧美一区二区三区免费观看视频| 国产色综合久久| 亚洲黄色免费网站| 国产精品一二三四| 欧美三级资源在线| 欧美韩日一区二区三区| 日韩av网站免费在线| 丁香激情综合国产| 日韩一区二区麻豆国产| 中文字幕一区在线| 精品一区二区免费| 欧美视频中文一区二区三区在线观看| 久久在线观看免费| 亚洲v中文字幕| 99久久婷婷国产综合精品电影| 在线综合视频播放| 一区二区视频在线| 国产成人在线网站| 欧美变态口味重另类| 亚洲成人综合在线| 91美女精品福利| 中文久久乱码一区二区| 精品在线播放免费| 337p亚洲精品色噜噜噜| 亚洲色图在线播放| 成人一道本在线| 久久久午夜精品理论片中文字幕| 亚洲成人一区在线| 色88888久久久久久影院野外| 欧美国产精品久久| 国产精品亚洲视频| 日韩精品一区二区三区中文不卡| 亚洲高清免费一级二级三级| av成人免费在线| 亚洲国产成人在线| 国产不卡免费视频| 国产日韩欧美高清在线| 国产精品香蕉一区二区三区| 精品国产亚洲一区二区三区在线观看| 亚洲国产视频网站| 色菇凉天天综合网| 中文字幕亚洲一区二区va在线| 国产**成人网毛片九色| 国产色一区二区| 成人精品免费网站| 国产精品家庭影院| 波多野结衣亚洲一区| 中文字幕乱码日本亚洲一区二区| 国产99久久久国产精品潘金| 国产女主播视频一区二区| 国产精品一区二区无线| 欧美极品少妇xxxxⅹ高跟鞋| 国产精品白丝av| 国产色综合久久| 99热在这里有精品免费| 中文字幕一区二区三区av| 99久久er热在这里只有精品66| 亚洲日本va在线观看| 91成人免费电影| 日一区二区三区| 精品国产乱码久久久久久1区2区 | 久久av中文字幕片| 久久午夜色播影院免费高清 | 精品伊人久久久久7777人| 久久婷婷国产综合精品青草| 懂色av一区二区三区免费看| 亚洲欧洲精品一区二区三区| 91国模大尺度私拍在线视频| 亚洲国产精品自拍| 日韩欧美视频一区| 成人一区二区在线观看| 一区二区在线观看视频在线观看| 欧美无砖砖区免费| 久久成人av少妇免费| 国产精品女主播在线观看| 欧美在线观看视频一区二区| 青青草原综合久久大伊人精品优势| 精品对白一区国产伦| 91社区在线播放| 欧美a级一区二区| 国产精品久久久久久亚洲伦| 欧美日韩精品综合在线| 国产精品一区二区x88av|