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

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

?? tcp_out.c

?? MCS-51的一個Free小型操作系統(tǒng),在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);

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久久久久久精| 国产综合色在线视频区| 成人动漫视频在线| 555夜色666亚洲国产免| 亚洲美女视频在线观看| 国产成人av影院| 久久久美女毛片 | 日韩三级在线免费观看| 国产精品亲子伦对白| 国产一区二区精品久久| 精品美女被调教视频大全网站| 日韩一区精品字幕| 91精品国产综合久久精品麻豆| 夜夜嗨av一区二区三区四季av| 色哟哟一区二区| 一区二区三区在线观看视频| 成人app在线| 国产精品国产三级国产三级人妇| av在线综合网| 天天操天天干天天综合网| 欧美日韩精品福利| 日韩二区三区在线观看| 久久久精品影视| 色天天综合久久久久综合片| 亚洲国产aⅴ天堂久久| 精品欧美一区二区久久 | 国产一区二区三区美女| 中文字幕在线不卡一区 | 麻豆精品国产91久久久久久| 欧美成人r级一区二区三区| 精品少妇一区二区三区免费观看| 国产精品乱码一区二区三区软件| 国产成人在线免费| 一区二区三区欧美| 69堂亚洲精品首页| www.欧美色图| 天使萌一区二区三区免费观看| 日韩亚洲电影在线| 国产成人aaa| 麻豆91在线看| 一区二区三区四区国产精品| 日韩免费成人网| 欧美影院午夜播放| bt7086福利一区国产| 日本中文一区二区三区| 亚洲一级二级三级| 17c精品麻豆一区二区免费| 26uuu另类欧美亚洲曰本| 欧美精品在线一区二区三区| 久久精品噜噜噜成人av农村| 亚洲成人自拍网| 樱花草国产18久久久久| 中文字幕字幕中文在线中不卡视频| 精品久久久久久久人人人人传媒| 欧美视频日韩视频| 欧美午夜电影网| 欧美唯美清纯偷拍| 欧美高清视频www夜色资源网| 91网站黄www| 99国产欧美久久久精品| 成人av在线一区二区三区| 成人午夜看片网址| 9人人澡人人爽人人精品| 成人高清在线视频| 日本精品一级二级| 欧美色男人天堂| 欧美一级免费观看| 精品成人一区二区三区四区| 日韩欧美一级二级三级久久久| 欧美高清一级片在线| 精品国产一区二区三区久久久蜜月 | 亚洲成av人片在www色猫咪| 337p粉嫩大胆噜噜噜噜噜91av | 欧美日精品一区视频| 欧美一区二区在线免费播放| 精品国产123| 亚洲人成在线观看一区二区| 亚洲国产欧美在线人成| 日本不卡视频在线| 国产成人精品三级| 91精品国产全国免费观看| 国产欧美精品一区| 亚洲一区二区偷拍精品| 国产真实乱偷精品视频免| 91丨porny丨蝌蚪视频| 精品女同一区二区| 亚洲午夜一二三区视频| 成人av集中营| 精品日韩av一区二区| 欧美日韩和欧美的一区二区| 欧美久久免费观看| 亚洲综合一区二区三区| 久久成人免费网| 欧美综合一区二区三区| 中文字幕精品—区二区四季| 日韩国产在线观看一区| 一本大道av伊人久久综合| 精品国产乱子伦一区| 亚洲国产日韩综合久久精品| 成人精品免费看| 欧美电影免费提供在线观看| 亚洲综合免费观看高清完整版在线 | 福利一区二区在线观看| 欧美一区二区美女| 亚洲成人黄色小说| 波多野结衣中文字幕一区 | 久久精品视频在线看| 久久精品999| 欧美精品一区二区三区在线 | 从欧美一区二区三区| 久久蜜桃av一区二区天堂| 国产一区二区不卡| 欧美国产欧美亚州国产日韩mv天天看完整 | 中文字幕精品三区| 成人精品一区二区三区中文字幕| 777奇米成人网| 国产九色sp调教91| 国产精品久久夜| 在线观看亚洲专区| 精品在线观看免费| 中文字幕一区三区| 91麻豆精品国产91久久久久| 日韩成人免费电影| 国产精品午夜在线| 欧美乱妇20p| 97久久超碰国产精品电影| 亚洲午夜私人影院| 久久亚区不卡日本| 在线观看成人小视频| 国产精品中文欧美| 午夜精品123| 中文字幕av免费专区久久| 欧美肥妇free| 99国产精品视频免费观看| 老司机免费视频一区二区三区| 久久精品日产第一区二区三区高清版| 菠萝蜜视频在线观看一区| 秋霞影院一区二区| 亚洲无线码一区二区三区| 国产色综合一区| 日韩视频一区二区| 欧美日韩大陆一区二区| 99综合电影在线视频| 激情文学综合插| 麻豆成人免费电影| 26uuu久久天堂性欧美| 国产精品亚洲综合一区在线观看| 亚洲精品国产a| 亚洲老妇xxxxxx| 亚洲色图20p| 国产精品婷婷午夜在线观看| 久久免费美女视频| 久久免费视频色| 国产日产欧美精品一区二区三区| 日韩一区二区三区观看| 日韩女优制服丝袜电影| 欧美日韩精品免费| 欧美色综合久久| 欧美视频在线一区二区三区| 91福利精品视频| 欧美精品乱人伦久久久久久| 欧美色视频在线| 日韩一区二区三区观看| 91精品婷婷国产综合久久竹菊| 欧美色爱综合网| 日韩视频免费观看高清在线视频| 欧美大黄免费观看| 欧美精品一区二区三区高清aⅴ | 日韩欧美在线一区二区三区| 精品嫩草影院久久| 樱桃视频在线观看一区| 男男视频亚洲欧美| 菠萝蜜视频在线观看一区| 欧亚一区二区三区| 国产偷国产偷亚洲高清人白洁| 亚洲国产电影在线观看| 日韩va亚洲va欧美va久久| 国产成人午夜电影网| 日韩一区二区三区视频| 综合色中文字幕| 国产精品一区2区| 91麻豆精品国产| 一区二区三区四区在线| 国产尤物一区二区在线| 8v天堂国产在线一区二区| 亚洲欧美日本韩国| 成人性色生活片| 久久久99免费| 久久99久久久久| 69久久夜色精品国产69蝌蚪网| 亚洲欧洲精品一区二区精品久久久| 日韩黄色在线观看| 欧美日韩和欧美的一区二区| 一区在线中文字幕| 国产suv精品一区二区三区| 久久伊99综合婷婷久久伊| 免费不卡在线观看| 91超碰这里只有精品国产| 日本午夜精品一区二区三区电影| 色国产精品一区在线观看|