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

📄 tcplib.c

📁 tinyos-2.x.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
      } else {
        printf("sending RST on bad data in state SYN_SENT\n");
        // we'll just let the timeout eventually close the socket, though
        tcplib_send_rst(iph, tcph);
        break;
      }
    case TCP_SYN_RCVD:
    case TCP_LISTEN:
      /* not connected. */
      if (tcph->flags & TCP_FLAG_SYN) {
        struct tcplib_sock *new_sock;

        if (this_conn->state == TCP_LISTEN) {
          memcpy(&this_conn->r_ep.sin6_addr, &iph->ip6_src, 16);
          this_conn->r_ep.sin6_port = tcph->srcport;
          new_sock = tcplib_accept(this_conn, &this_conn->r_ep);
          if (new_sock != this_conn) {
            memset(this_conn->r_ep.sin6_addr.s6_addr, 0, 16);
            this_conn->r_ep.sin6_port = 0;
            if (new_sock != NULL) {
              memcpy(&new_sock->r_ep.sin6_addr, &iph->ip6_src, 16);
              new_sock->r_ep.sin6_port = tcph->srcport;
              conn_add_once(new_sock);
            }
          }
          if (new_sock == NULL) {
            tcplib_send_rst(iph, tcph);
            break;
          }
          memcpy(&new_sock->l_ep.sin6_addr, &iph->ip6_dst, 16);
          new_sock->l_ep.sin6_port = tcph->dstport;

          new_sock->ackno = hdr_seqno + 1;
          circ_buf_init(new_sock->tx_buf, new_sock->tx_buf_len,
                        0xcafebabe + 1);
        } else {
          /* recieved a SYN retransmission. */
          new_sock = this_conn;
        }

        if (new_sock != NULL) {
          new_sock->seqno = 0xcafebabe + 1;
          new_sock->state = TCP_SYN_RCVD;
          tcplib_send_ack(new_sock, 0, TCP_FLAG_ACK | TCP_FLAG_SYN);
          new_sock->seqno++;
        } else {
          memset(&this_conn->r_ep, 0, sizeof(struct sockaddr_in6));
        }
      } else if (this_conn->state == TCP_LISTEN) {
        tcplib_send_rst(iph, tcph);
        break;
      }
      /* this is SYN_RECVd */
      if (tcph->flags & TCP_FLAG_ACK) {
        this_conn->state = TCP_ESTABLISHED;
      } 
      /* fall through to handle any data. */
      

    case TCP_CLOSE_WAIT:
    case TCP_ESTABLISHED:
    ESTABLISHED:

      /* ack any data in this packet */
      if (this_conn->state == TCP_ESTABLISHED || this_conn->state == TCP_FIN_WAIT_1) {
        if (payload_len > 0) {
          if ((this_conn->flags & TCP_ACKPENDING) == TCP_ACKPENDING) {
            // printf("Incr would overflow\n");
          }
          this_conn->flags ++;
        }


        // receive side sequence check and add data
        printf("seqno: %u ackno: %u\n", hdr_seqno, hdr_ackno);


        // send side recieve sequence check and congestion window updates.
        if (hdr_ackno > circ_get_seqno(this_conn->tx_buf)) {
          // new data is being ACKed
          // or we haven't sent anything new
          if (this_conn->cwnd <= this_conn->ssthresh) {
            // in slow start; increase the cwnd by one segment
            this_conn->cwnd += ONE_SEGMENT(this_conn);
            // printf("in slow start\n");
          } else {
            // in congestion avoidance
            this_conn->cwnd += (ONE_SEGMENT(this_conn) * ONE_SEGMENT(this_conn)) / this_conn->cwnd;
            // printf("in congestion avoidence\n");
          }
          // printf("ACK new data: cwnd: %i ssthresh: %i\n", this_conn->cwnd, this_conn->ssthresh);
          // reset the duplicate ack counter
          UNSET_ACK_COUNT(this_conn->flags);
          // truncates the ack buffer 
          circ_shorten_head(this_conn->tx_buf, hdr_ackno);
          // printf("ack_count: %i\n", GET_ACK_COUNT(this_conn->flags));

          if (this_conn->seqno == hdr_ackno) {
            tcplib_extern_acked(this_conn);
          }
        } else if (this_conn->seqno > circ_get_seqno(this_conn->tx_buf)) {
          // this is a duplicate ACK
          //  - increase the counter of the number of duplicate ACKs
          //  - if we get to three duplicate ACK's, start resending at
          //    the ACK number because this probably means we lost a segment

          INCR_ACK_COUNT(this_conn->flags);
          // printf("ack_count: %i\n", GET_ACK_COUNT(this_conn->flags));
          // printf("dup ack count: %i\n", GET_ACK_COUNT(this_conn->flags));
          // a "dup ack count" of 2 is really 3 total acks because we start with zero
          if (GET_ACK_COUNT(this_conn->flags) == 2) {
            UNSET_ACK_COUNT(this_conn->flags);
            printf("detected multiple duplicate ACKs-- doing fast retransmit [%u, %u]\n",
                   circ_get_seqno(this_conn->tx_buf),
                   this_conn->seqno);

            // this is our detection of a "duplicate ack" event.
            // we are going to reset ssthresh and retransmit the data.
            reset_ssthresh(this_conn);
            tcplib_output(this_conn, circ_get_seqno(this_conn->tx_buf));
            this_conn->timer.retx = 6;
            
          }
        }

        if (hdr_seqno != this_conn->ackno) {
          printf("==> received forward segment\n");
          if ((hdr_seqno > this_conn->ackno + this_conn->my_wind) ||
              (hdr_seqno < this_conn->ackno - this_conn->my_wind)) {
            // send a RST on really wild data 
            tcplib_send_rst(iph, tcph);
          } else {
            tcplib_send_ack(this_conn, 0, TCP_FLAG_ACK);
            this_conn->flags |= TCP_ACKSENT;
          }
        } else { // (hdr_seqno == this_conn->ackno) {
          receive_data(this_conn, tcph, len - sizeof(struct ip6_hdr));

          if (this_conn->flags & TCP_ACKSENT) {
            this_conn->flags &= ~TCP_ACKSENT;
            tcplib_send_ack(this_conn, 0, TCP_FLAG_ACK);
          }
        }          

        // reset the retransmission timer
        if (this_conn->timer.retx == 0)
          this_conn->timer.retx = 6;
      }
    case TCP_TIME_WAIT:
      if ((payload_len > 0 && (this_conn->flags & TCP_ACKPENDING) >= 1) 
          || tcph->flags & TCP_FLAG_FIN) {
        tcplib_send_ack(this_conn, (payload_len == 0 && tcph->flags & TCP_FLAG_FIN), TCP_FLAG_ACK);
        /* only close the connection if we've gotten all the data */
        if (this_conn->state == TCP_ESTABLISHED 
            && tcph->flags & TCP_FLAG_FIN
            && hdr_seqno  == this_conn->ackno) {
          this_conn->state = TCP_CLOSE_WAIT;
          tcplib_extern_closed(this_conn);
        }
      }
      break;
    case TCP_CLOSED:
    default:
      rc = -1;
      // printf("sending RST\n");
      // tcplib_send_ack(this_conn, 0, TCP_FLAG_ACK | TCP_FLAG_RST);
    }
  } else {
    /* this_conn was NULL */
    /* interestingly, TCP sends a RST on this condition, not an ICMP error.  go figure. */
    printf("sending rst on missing connection\n");
    tcplib_send_rst(iph, tcph);

  }
  return rc;
}


/* bind the socket to a local address */
int tcplib_bind(struct tcplib_sock *sock,
                struct sockaddr_in6 *addr) {
  /* not using an already-bound port */
  /* TODO : SDH : check local address */
  if (conn_checkport(addr->sin6_port))
    return -1;
  
  memcpy(&sock->l_ep, addr, sizeof(struct sockaddr_in6));
  /* passive open */
  sock->state = TCP_LISTEN;
  return 0;
}

/* connect the socket to a remote endpoint */
int tcplib_connect(struct tcplib_sock *sock,
                   struct sockaddr_in6 *serv_addr) {
  if (sock->tx_buf == NULL)
    return -1;

  switch (sock->state) {
  case TCP_CLOSED:
    // passive open; need to set up the local endpoint.
    memset(&sock->l_ep, 0, sizeof(struct sockaddr_in6));
    sock->l_ep.sin6_port = htons(alloc_local_port());
    break;
  case TCP_LISTEN:
    // we got here by calling bind, so we're cool.
    break;
  default:
    return -1;
  }
  circ_buf_init(sock->tx_buf, sock->tx_buf_len,
                0xcafebabe + 1);

  sock->ackno = 0;
  sock->seqno = 0xcafebabe;
  memcpy(&sock->r_ep, serv_addr, sizeof(struct sockaddr_in6));
  tcplib_send_ack(sock, 0, TCP_FLAG_SYN);
  sock->state = TCP_SYN_SENT;
  sock->seqno++;
  sock->timer.retx = 6;

  return 0;
}


int tcplib_send(struct tcplib_sock *sock, void *data, int len) {
  /* have enough tx buffer left? */
  if (sock->state != TCP_ESTABLISHED)
    return -1;
  if (sock->seqno - circ_get_seqno(sock->tx_buf) + len > sock->tx_buf_len) // circ_get_window(sock->tx_buf))
    return -1;
  if (circ_buf_write(sock->tx_buf, sock->seqno, data, len) < 0)
    return -1;

  sock->seqno += len;
  // printf("tcplib_output from send\n");
  tcplib_output(sock, sock->seqno - len);
  
  // 3 seconds
  if (sock->timer.retx == 0)
    sock->timer.retx = 6;

  return 0;
}

void tcplib_retx_expire(struct tcplib_sock *sock) {
  // printf("retransmission timer expired!\n");
  sock->retxcnt++;
  switch (sock->state) {
  case TCP_ESTABLISHED:
    if (circ_get_seqno(sock->tx_buf) != sock->seqno) {
      printf("retransmitting [%u, %u]\n", circ_get_seqno(sock->tx_buf),
             sock->seqno);
      reset_ssthresh(sock);
      // restart slow start
      sock->cwnd = ONE_SEGMENT(sock);
      // printf("tcplib_output from timer\n");
      tcplib_output(sock, circ_get_seqno(sock->tx_buf));
      sock->timer.retx = 6;
    } else {
      sock->retxcnt--;
    }
    break;
  case TCP_SYN_SENT:
    tcplib_send_ack(sock, 0, TCP_FLAG_SYN);
    sock->timer.retx = 6;
    break;
  case TCP_LAST_ACK:
  case TCP_FIN_WAIT_1:
    tcplib_send_ack(sock, 1, TCP_FLAG_ACK | TCP_FLAG_FIN);
    sock->timer.retx = 6;
    break;
  case TCP_TIME_WAIT:
    sock->state = TCP_CLOSED;
    // exit TIME_WAIT
    tcplib_extern_closedone(sock);
    break;
  default:
    break;
  }

  /* if we've hit this timer a lot, give up
   *
   * do this by going into
   * TIME_WAIT, which will generate a FIN if anyone sends to us but
   * otherwise just do nothing.
   *
   * we don't do something like try to close it here, since we might
   * have gotten here from doing that.
   */
  if (sock->retxcnt > TCPLIB_GIVEUP) {
    sock->state = TCP_TIME_WAIT;
    sock->timer.retx = TCPLIB_TIMEWAIT_LEN;
   }
}

int tcplib_abort(struct tcplib_sock *sock) {
  switch (sock->state) {
    // nothing to abort
  case TCP_CLOSED:
  case TCP_LISTEN:
    break;
  default:
    tcplib_send_ack(sock, 0, TCP_FLAG_RST);
    memset(&sock->l_ep, 0, sizeof(struct sockaddr_in6));
    memset(&sock->r_ep, 0, sizeof(struct sockaddr_in6));
    sock->state = TCP_CLOSED;
  }
  return 0;
}

int tcplib_close(struct tcplib_sock *sock) {
  int rc = 0;

  switch (sock->state) {
    /* passive close */
  case TCP_CLOSE_WAIT:
    tcplib_send_ack(sock, 1, TCP_FLAG_ACK | TCP_FLAG_FIN);
    sock->timer.retx = 6;
    sock->state = TCP_LAST_ACK;
    break;
    /* active close */
  case TCP_ESTABLISHED:
    // kick off the close
    tcplib_send_ack(sock, 0, TCP_FLAG_ACK | TCP_FLAG_FIN);
    sock->timer.retx = 6;
    sock->state = TCP_FIN_WAIT_1;
    break;
  case TCP_SYN_SENT:
    sock->state = TCP_CLOSED;
    break;
  default:
    /* this is meaningless in other states */
    rc = -1;
  }
  return rc;
}

int tcplib_timer_process() {
  struct tcplib_sock *iter;
  for (iter = conns; iter != NULL; iter = iter->next) {
    if (iter->timer.retx > 0 && (--iter->timer.retx) == 0)
      tcplib_retx_expire(iter);
    if ((iter->flags & TCP_ACKPENDING) >= 2) {
      tcplib_send_ack(iter, 0, TCP_FLAG_ACK);
    }
  }
  return 0;
}

⌨️ 快捷键说明

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