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

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? tcp_out.c

?? ARM7的一些試驗程序
?? 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);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
99re8在线精品视频免费播放| 激情国产一区二区| 亚洲成a人片在线不卡一二三区 | 婷婷激情综合网| 麻豆成人91精品二区三区| 国产美女主播视频一区| 色综合久久久久久久| 欧美麻豆精品久久久久久| 精品少妇一区二区三区免费观看| 国产日韩综合av| 一区二区三区国产豹纹内裤在线| 精品一区二区综合| 色综合久久88色综合天天免费| 国产伦精品一区二区三区免费迷| 91精品国产91热久久久做人人 | 欧美伦理电影网| 国产欧美视频在线观看| 洋洋av久久久久久久一区| 日本欧美韩国一区三区| 色综合久久综合网欧美综合网| 日韩写真欧美这视频| 国产精品久久久久久久久果冻传媒| 亚洲一区在线播放| 成人h动漫精品一区二区 | 国产精品电影一区二区| 日韩激情一二三区| 99精品桃花视频在线观看| 久久天堂av综合合色蜜桃网| 亚洲福利视频一区| 色先锋久久av资源部| 欧美国产精品劲爆| 国产精品影视在线| 日韩欧美国产一二三区| 午夜欧美在线一二页| 欧美日韩午夜精品| 一区二区三区日韩在线观看| 91日韩精品一区| 午夜精品一区在线观看| 欧美日韩一区国产| 亚洲3atv精品一区二区三区| 日本二三区不卡| 国产精品久久夜| 99国产精品国产精品毛片| 国产欧美日韩不卡免费| 99re热视频精品| 亚洲一二三区视频在线观看| 欧美一区二区三区日韩| 爽爽淫人综合网网站| 欧美va在线播放| 成人涩涩免费视频| 午夜精品免费在线| 中文久久乱码一区二区| 欧美日韩成人高清| 国产a视频精品免费观看| 亚洲日韩欧美一区二区在线| 欧美高清dvd| 国产电影一区在线| 婷婷开心久久网| 国产三级精品视频| 7799精品视频| 91亚洲男人天堂| 免费看欧美女人艹b| 一区二区三区毛片| 久久九九影视网| 日韩区在线观看| 色激情天天射综合网| 国产综合久久久久影院| 亚洲同性gay激情无套| 日韩一区二区精品| 欧美色偷偷大香| 在线观看亚洲精品| 欧洲精品在线观看| 91麻豆蜜桃一区二区三区| 国产一区二三区| 韩国成人福利片在线播放| 久久99国产精品麻豆| 国产主播一区二区| 国内精品伊人久久久久av一坑| 蜜桃视频一区二区三区| 亚洲色欲色欲www在线观看| 国产人成亚洲第一网站在线播放| 欧美精品成人一区二区三区四区| 波多野结衣在线一区| 丁香天五香天堂综合| 成人自拍视频在线观看| 成人黄色免费短视频| 波多野结衣中文字幕一区二区三区| 国产精品一区二区x88av| 久久精品免费看| 99麻豆久久久国产精品免费优播| av在线播放成人| 欧美肥妇bbw| 亚洲三级电影网站| 日本怡春院一区二区| 国产suv精品一区二区6| 91污片在线观看| 3751色影院一区二区三区| 欧美mv日韩mv| 亚洲午夜电影在线观看| 蜜臀精品久久久久久蜜臀| 成人午夜精品一区二区三区| 在线精品亚洲一区二区不卡| 久久色.com| 日本vs亚洲vs韩国一区三区 | 国产视频不卡一区| 亚洲电影一区二区| 国产91丝袜在线播放0| 色婷婷久久综合| 国产亚洲午夜高清国产拍精品| 中文字幕色av一区二区三区| 五月开心婷婷久久| 日本道精品一区二区三区| 国产日产欧美一区二区视频| 日韩精品一级中文字幕精品视频免费观看 | 国产日韩欧美一区二区三区乱码| 亚洲靠逼com| 成人18视频日本| 久久久久久黄色| 精品一二三四区| 日本不卡1234视频| 这里只有精品免费| 一区二区三区91| 91亚洲精品一区二区乱码| 国产精品午夜电影| 乱一区二区av| 久久久久亚洲综合| 国内外成人在线| 久久久三级国产网站| 国产一区二区免费视频| 2017欧美狠狠色| 国产福利91精品一区| 国产精品乱人伦中文| 丁香婷婷综合色啪| 一区二区视频在线看| 色综合久久天天| 亚洲成人综合在线| 婷婷综合五月天| 欧美一区二区三区不卡| 青娱乐精品在线视频| 中文字幕视频一区| 欧美电影免费提供在线观看| 久久成人免费网| 国产精品日产欧美久久久久| 91九色最新地址| 久久不见久久见中文字幕免费| 国产亚洲一本大道中文在线| 99精品国产91久久久久久| 婷婷激情综合网| 欧美高清在线一区二区| 精品视频123区在线观看| 久久精品国产亚洲高清剧情介绍 | 亚洲视频一区二区在线观看| 欧美一区欧美二区| 色婷婷av一区二区三区gif | 欧美成人女星排行榜| 91老司机福利 在线| 国产在线不卡一区| 亚洲成va人在线观看| 亚洲婷婷综合久久一本伊一区 | 五月激情丁香一区二区三区| 久久久99久久| 日韩午夜激情免费电影| 日本久久精品电影| aaa欧美日韩| aaa欧美色吧激情视频| 国产精品一区二区在线看| 亚洲chinese男男1069| 亚洲欧美日韩中文字幕一区二区三区 | 欧美色视频一区| 91在线porny国产在线看| 高清国产午夜精品久久久久久| 黑人精品欧美一区二区蜜桃| 久久99精品国产.久久久久| 丝袜美腿亚洲一区二区图片| 亚洲成人综合网站| 日本亚洲免费观看| 国产精品亚洲一区二区三区在线| 国内不卡的二区三区中文字幕 | 欧美成人三级在线| 久久综合久久99| 中文文精品字幕一区二区| 亚洲一区视频在线| 另类欧美日韩国产在线| 久久99热这里只有精品| 国产精品一区专区| 在线视频一区二区三区| 欧美一区二区三区四区视频| 久久免费看少妇高潮| 亚洲精品高清在线| 三级久久三级久久久| 99久久精品免费看国产免费软件| 欧美日韩一区三区| 中文字幕 久热精品 视频在线| 国产精品国产三级国产aⅴ原创| 亚洲一区中文日韩| eeuss影院一区二区三区| 在线综合亚洲欧美在线视频| 精品国产乱码久久久久久老虎 | 91天堂素人约啪| 久久久不卡影院|