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

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

?? tcp_out.c

?? MCS-51的一個Free小型操作系統,在KeilC中下編譯工作
?? 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"

#include <string.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=NULL;
  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 = NULL;
  queue = NULL;
  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);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
青青青爽久久午夜综合久久午夜| 日本三级韩国三级欧美三级| 欧美日韩久久久一区| 精品在线亚洲视频| 一区二区三区免费在线观看| 欧美tickling网站挠脚心| 91视频免费播放| 麻豆视频一区二区| 亚洲欧美日韩国产另类专区| 精品国产91久久久久久久妲己| 色综合视频在线观看| 激情深爱一区二区| 婷婷丁香久久五月婷婷| 国产午夜精品久久久久久免费视| 欧美久久久久久久久| 99久久精品免费观看| 国产精品一区二区视频| 五月婷婷久久丁香| 《视频一区视频二区| 久久噜噜亚洲综合| 日韩一级高清毛片| 欧美日韩www| 日本韩国欧美国产| 成人高清伦理免费影院在线观看| 理论片日本一区| 日韩在线播放一区二区| 亚洲日本一区二区| 国产精品不卡在线| 国产日韩欧美一区二区三区综合| 日韩欧美在线123| 欧美精品视频www在线观看| 色综合天天综合网国产成人综合天 | 一级做a爱片久久| 国产欧美日韩中文久久| 精品国内二区三区| 欧美sm极限捆绑bd| 精品对白一区国产伦| 欧美一区二区在线视频| 欧美日韩高清在线播放| 欧美日韩国产成人在线91 | 日韩欧美一区二区免费| 欧美日韩国产电影| 欧美久久高跟鞋激| 91精品国产全国免费观看| 欧美精品v国产精品v日韩精品| 精品视频在线免费观看| 精品污污网站免费看| 欧美日韩综合色| 欧美午夜精品久久久久久孕妇| 在线观看一区二区精品视频| 日本韩国精品一区二区在线观看| 色八戒一区二区三区| 欧美在线你懂的| 在线观看不卡视频| 欧美日韩久久一区二区| 欧美一区二区三区成人| 51精品久久久久久久蜜臀| 欧美一区二区三区性视频| 日韩女优电影在线观看| 久久先锋影音av| 国产女主播视频一区二区| 国产精品久久国产精麻豆99网站| 日韩美女视频一区| 一区二区成人在线观看| 日韩精品电影一区亚洲| 久久精品国产久精国产爱| 国产91丝袜在线播放0| yourporn久久国产精品| 欧美亚洲国产一区二区三区 | 日韩主播视频在线| 久久精品久久99精品久久| 国产不卡在线一区| 91福利在线看| 日韩久久久久久| 中文字幕不卡在线观看| 亚洲午夜一二三区视频| 精品一区二区三区在线视频| 不卡av在线免费观看| 欧洲日韩一区二区三区| 日韩一区二区三区观看| 国产精品女上位| 亚洲地区一二三色| 国产福利91精品一区二区三区| 91在线免费视频观看| 日韩欧美在线网站| 综合激情成人伊人| 乱一区二区av| 色综合久久中文综合久久牛| 日韩美女一区二区三区四区| 亚洲视频在线一区| 久久精工是国产品牌吗| 97精品视频在线观看自产线路二| 91.成人天堂一区| 中文字幕一区二区在线播放 | 成人午夜激情在线| 欧美日韩国产一区| 国产女人aaa级久久久级| 午夜欧美一区二区三区在线播放| 国产成人精品免费| 欧美精品日韩一区| 国产精品久久久久久久浪潮网站| 日本不卡中文字幕| 91浏览器打开| 久久精品人人做人人爽人人| 国产在线麻豆精品观看| 国产高清精品在线| 欧美日韩精品高清| 国产精品理论在线观看| 美女在线一区二区| 在线影视一区二区三区| 国产精品网站在线| 玖玖九九国产精品| 欧美高清视频www夜色资源网| 国产精品久久久99| 国产一区二区三区蝌蚪| 欧美一区二区三区成人| 亚洲图片欧美视频| 成年人国产精品| 久久久青草青青国产亚洲免观| 婷婷六月综合亚洲| 欧美性猛片xxxx免费看久爱| 国产精品日韩成人| 国产成a人无v码亚洲福利| 欧美成人精品高清在线播放| 三级在线观看一区二区| 99久久亚洲一区二区三区青草| 精品久久久久久久久久久久久久久久久| 亚洲福利一区二区| 亚洲综合一二三区| 日精品一区二区| 国产区在线观看成人精品 | 国产成人免费视频一区| 欧美乱妇15p| 韩国精品在线观看| 久久精品国产免费看久久精品| 午夜电影久久久| 久久精品在这里| 另类综合日韩欧美亚洲| 日本一区二区久久| 日本一区二区三区视频视频| 欧美精品一区二区三区高清aⅴ| 日韩欧美一二区| 国产精品欧美综合在线| 欧美韩日一区二区三区四区| 国产宾馆实践打屁股91| 一级精品视频在线观看宜春院| 制服视频三区第一页精品| 国产成人综合在线播放| 性欧美疯狂xxxxbbbb| 欧美国产丝袜视频| 69堂精品视频| 久久久久久久久久看片| 欧美视频精品在线| av电影天堂一区二区在线观看| 全国精品久久少妇| 夜夜嗨av一区二区三区中文字幕 | 久久众筹精品私拍模特| 欧美日韩在线直播| 成年人午夜久久久| 国产福利一区二区三区| 精品无码三级在线观看视频| 午夜精品福利一区二区蜜股av| 日韩一区有码在线| 日本一区二区高清| 国产视频亚洲色图| 国产网红主播福利一区二区| 久久这里只精品最新地址| 欧美大尺度电影在线| 久久亚洲私人国产精品va媚药| 欧美日韩国产中文| www.亚洲人| 国产美女主播视频一区| 欧美视频在线观看一区| 国产欧美综合在线| 日本韩国欧美一区二区三区| 亚洲一区二区三区四区在线免费观看| 欧洲人成人精品| 久久99国产精品免费网站| 国产精品福利影院| 欧美日韩高清一区二区三区| 久久福利视频一区二区| 国产精品美女久久久久久2018| 欧美自拍偷拍一区| 日本亚洲最大的色成网站www| 国产精品一二三四五| 欧美久久高跟鞋激| 国产精品亚洲午夜一区二区三区| 国产精品久久久久久久久免费桃花 | 久久女同性恋中文字幕| 日韩国产一二三区| 国产精品成人一区二区艾草| 91精品在线免费| 成人激情校园春色| 日韩黄色免费电影| 18成人在线视频| 欧美成人精品二区三区99精品| 色哟哟在线观看一区二区三区| 国内精品国产成人| 亚洲成人午夜影院| 国产欧美视频一区二区三区|