日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uip1.0核心模块uip_process函数解读

發布時間:2023/12/20 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uip1.0核心模块uip_process函数解读 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載地址:https://www.amobbs.com/thread-5531817-1-1.html

?最近,利用uip搞了小東西,要想利用好uip, 最好徹底搞清楚其關鍵函數 uip_process.
當網卡接收到數據之后,均需要通過該函數來處理.
??下面是對uip 1.0中的uip_process函數解讀.

//要點: 網卡收到數據時,uip_process會遍歷uip_udp_conns數組,如果當前包的目的端口與
//本機端口不匹配,或者遠程端口與uip_udp_new中的端口不匹配,那么uip會直接丟棄
//這個包。
void uip_process(u8_t flag)
{
??u8_t temp[2];
??register struct uip_conn *uip_connr = uip_conn;

#if UIP_UDP
??if(flag == UIP_UDP_SEND_CONN) {? ? ? ???//若是則goto udp_send;不是則向下執行;
? ? goto udp_send;
??}
#endif /* UIP_UDP */
??
??uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];

??/* Check if we were invoked because of a poll request for a
? ???particular connection. */
??if(flag == UIP_POLL_REQUEST) { // 如果處于穩定連接狀態且沒有數據在緩存中等待確認則:
? ? if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
? ?? ? !uip_outstanding(uip_connr)) {
? ? ? ? uip_flags = UIP_POLL;
? ? ? ? UIP_APPCALL();
? ? ? ? goto appsend;
? ? }
? ? goto drop;
? ??
? ? /* Check if we were invoked because of the perodic timer fireing. */
??} else if(flag == UIP_TIMER) {
#if UIP_REASSEMBLY
? ? if(uip_reasstmr != 0) {
? ?? ?--uip_reasstmr;
? ? }
#endif /* UIP_REASSEMBLY */
? ? /* Increase the initial sequence number. */
? ? if(++iss[3] == 0) {
? ?? ?if(++iss[2] == 0) {
? ? ? ? if(++iss[1] == 0) {
? ? ? ?? ?++iss[0];
? ? ? ? }
? ?? ?}
? ? }

? ? /* Reset the length variables. */
? ? uip_len = 0;
? ? uip_slen = 0;

? ? /* Check if the connection is in a state in which we simply wait
? ?? ? for the connection to time out. If so, we increase the
? ?? ? connection's timer and remove the connection if it times
? ?? ? out. */
? ? if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
? ?? ? uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
? ?? ?++(uip_connr->timer);
? ?? ?if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
? ?//如果連接處于等待超時關閉狀態則增加超時計數器,如果到達超時期限則關閉當前連接
? ? ? ?? ?? ? uip_connr->tcpstateflags = UIP_CLOSED;
? ? ? ? ? ? ? ?? ?//uip_arp_close(uip_connr->ripaddr);
? ?? ?}
? ? } else if(uip_connr->tcpstateflags != UIP_CLOSED) {? ? ? ? //如果連接不處于關閉狀態
? ?? ?/* If the connection has outstanding data, we increase the
? ? ? ???connection's timer and see if it has reached the RTO value
? ? ? ???in which case we retransmit. */
//已經發送的數據包還未接收到對其的ACK,超時計數器減一且超時計數器值為0??
? ?? ?if(uip_outstanding(uip_connr)) {
? ? ? ? if(uip_connr->timer-- == 0) {
? ? ? ?? ?if(uip_connr->nrtx == UIP_MAXRTX ||
? ? ? ?? ?? ?((uip_connr->tcpstateflags == UIP_SYN_SENT ||
? ? ? ?? ?? ???uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
? ? ? ?? ?? ? uip_connr->nrtx == UIP_MAXSYNRTX)) {
? ? ? ?? ?//①如果到達所設定的重發次數則
? ? ? ?? ???uip_connr->tcpstateflags = UIP_CLOSED;//關閉當前連接

? ? ? ?? ???/* We call UIP_APPCALL() with uip_flags set to
? ? ? ?? ?? ???UIP_TIMEDOUT to inform the application that the
? ? ? ?? ?? ???connection has timed out. */
? ? ? ?? ???uip_flags = UIP_TIMEDOUT; //通知應用程序超時;
? ? ? ?? ???UIP_APPCALL();
? ? ? ?? ???/* We also send a reset packet to the remote host. */
? ? ? ?? ???BUF->flags = TCP_RST | TCP_ACK;? ? ? ?? ?//設置RST+ACK終止連接標志
? ? ? ?? ???goto tcp_send_nodata;
? ? ? ?? ?}
? ?//②沒有到達設定的重發次數則重傳數據:
? ? ? ?? ?/* Exponential backoff. */
? ? ? ?? ?uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???4:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???uip_connr->nrtx);? ? ? ? //重置重傳計數器
? ? ? ?? ?++(uip_connr->nrtx);
? ? ? ?? ?
? ? ? ?? ?/* Ok, so we need to retransmit. We do this differently
? ? ? ?? ?? ?depending on which state we are in. In ESTABLISHED, we
? ? ? ?? ?? ?call upon the application so that it may prepare the
? ? ? ?? ?? ?data for the retransmit. In SYN_RCVD, we resend the
? ? ? ?? ?? ?SYNACK that we sent earlier and in LAST_ACK we have to
? ? ? ?? ?? ?retransmit our FINACK. */
? ? ? ?? ?UIP_STAT(++uip_stat.tcp.rexmit);
? ? ? ?? ?switch(uip_connr->tcpstateflags & UIP_TS_MASK) {//根據連接處的不同狀態重發不同的數據包
? ? ? ?? ?case UIP_SYN_RCVD:
? ? ? ?? ???/* In the SYN_RCVD state, we should retransmit our
? ?? ?? ?? ?? ?SYNACK. */
? ? ? ?? ???goto tcp_send_synack; // 重新發送先前發送的SYN+ACK?
? ? ? ?? ???
#if UIP_ACTIVE_OPEN
? ? ? ?? ?case UIP_SYN_SENT:
? ? ? ?? ???/* In the SYN_SENT state, we retransmit out SYN. */
? ? ? ?? ???BUF->flags = 0;
? ? ? ?? ???goto tcp_send_syn;? ? ? ???//重發SYN請求連接
#endif /* UIP_ACTIVE_OPEN */
? ? ? ?? ???
? ? ? ?? ?case UIP_ESTABLISHED:
? ? ? ?? ???/* In the ESTABLISHED state, we call upon the application
? ?? ?? ?? ?? ?to do the actual retransmit after which we jump into
? ?? ?? ?? ?? ?the code for sending out the packet (the apprexmit
? ?? ?? ?? ?? ?label). */
? ? ? ?? ???uip_flags = UIP_REXMIT;
? ? ? ?? ???UIP_APPCALL();? ? ? ? //調用上層應用程序,通知重新生成數據重發
? ? ? ?? ???goto apprexmit;? ? ? ? //進入重發階段
? ? ? ?? ???
? ? ? ?? ?case UIP_FIN_WAIT_1:
? ? ? ?? ?case UIP_CLOSING:
? ? ? ?? ?case UIP_LAST_ACK:
? ? ? ?? ???/* In all these states we should retransmit a FINACK. */
? ? ? ?? ???goto tcp_send_finack;//重發FIN+ACK關閉連接?
? ? ? ?? ???
? ? ? ?? ?}
? ? ? ? }
? ? } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {??//處于穩定連接狀態且上次發送的數據?
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//接收到正確的ACK,可以繼續發送新數據?
? ? ? ? /* If there was no need for a retransmission, we poll the
? ?? ?? ???application for new data. */
? ? ? ? uip_flags = UIP_POLL; //詢問應用程序是否有數據要發送?
? ? ? ? UIP_APPCALL();//調用應用程序產生數據
? ? ? ? goto appsend;//發送數據
? ?? ?}
? ? }
? ? goto drop;
??}
#if UIP_UDP
??if(flag == UIP_UDP_TIMER) {
? ? if(uip_udp_conn->lport != 0) { //當前連接的本地端口不為0則
? ?? ?uip_conn = NULL;
? ?? ?uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
? ?? ?uip_len = uip_slen = 0;
? ?? ?uip_flags = UIP_POLL;? ? ? ???//詢問應用程序是否有數據要發送
? ?? ?UIP_UDP_APPCALL();//調用應用程序產生數據
? ?? ?goto udp_send;
? ? } else {
? ?? ?goto drop;//本地端口為0,表明沒有建立DUP連接,則
? ? }
??}
#endif

??/* This is where the input processing starts. */
??UIP_STAT(++uip_stat.ip.recv);

??/* Start of IP input header processing code. */
??//檢查IP幀頭中的IP版本及IP頭長度是否符合要
#if UIP_CONF_IPV6
??/* Check validity of the IP header. */
??if((BUF->vtc & 0xf0) != 0x60)??{ /* IP version and header length. */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.vhlerr);
? ? UIP_LOG("ipv6: invalid version.");
? ? goto drop; //不符合:goto drop;丟棄此包
??}
#else /* UIP_CONF_IPV6 */
??/* Check validity of the IP header. others 0x69,0x46 ? */
??if(BUF->vhl != 0x45)??{ /* IP version and header length. */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.vhlerr);
? ? ? ? temp[0]=??BUF->vhl;
? ? ? ? temp[1]='\0';
? ? ? ? UIP_LOG(temp);
? ? UIP_LOG("ip: invalid version or header length.");
? ? goto drop;//不符合:goto drop;丟棄此包
??}
#endif /* UIP_CONF_IPV6 */
??
??/* Check the size of the packet. If the size reported to us in
? ???uip_len is smaller the size reported in the IP header, we assume
? ???that the packet has been corrupted in transit. If the size of
? ???uip_len is larger than the size reported in the IP packet header,
? ???the packet has been padded and we set uip_len to the correct
? ???value.. */

??if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
? ? uip_len = (BUF->len[0] << 8) + BUF->len[1];
#if UIP_CONF_IPV6
? ? uip_len += 40; /* The length reported in the IPv6 header is the
? ? ? ? ? ? ? ?? ?? ? length of the payload that follows the
? ? ? ? ? ? ? ?? ?? ? header. However, uIP uses the uip_len variable
? ? ? ? ? ? ? ?? ?? ? for holding the size of the entire packet,
? ? ? ? ? ? ? ?? ?? ? including the IP header. For IPv4 this is not a
? ? ? ? ? ? ? ?? ?? ? problem as the length field in the IPv4 header
? ? ? ? ? ? ? ?? ?? ? contains the length of the entire packet. But
? ? ? ? ? ? ? ?? ?? ? for IPv6 we need to add the size of the IPv6
? ? ? ? ? ? ? ?? ?? ? header (40 bytes). */
#endif /* UIP_CONF_IPV6 */
??} else {
? ? UIP_LOG("ip: packet shorter than reported in IP header.");
? ? goto drop;
??}

#if !UIP_CONF_IPV6
??/* Check the fragment flag. */
??if((BUF->ipoffset[0] & 0x3f) != 0 ||
? ???BUF->ipoffset[1] != 0) {
#if UIP_REASSEMBLY
? ? uip_len = uip_reass();
? ? if(uip_len == 0) {
? ?? ?goto drop;
? ? }
#else /* UIP_REASSEMBLY */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.fragerr);
? ? UIP_LOG("ip: fragment dropped.");
? ? goto drop;
#endif /* UIP_REASSEMBLY */
??}
#endif /* UIP_CONF_IPV6 */

??if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
? ? /* If we are configured to use ping IP address configuration and
? ?? ? hasn't been assigned an IP address yet, we accept all ICMP
? ?? ? packets. */
#if UIP_PINGADDRCONF && !UIP_CONF_IPV6
? ? if(BUF->proto == UIP_PROTO_ICMP) {
? ?? ?UIP_LOG("ip: possible ping config packet received.");
? ?? ?goto icmp_input;
? ? } else {
? ?? ?UIP_LOG("ip: packet dropped since no address assigned.");
? ?? ?goto drop;
? ? }
#endif /* UIP_PINGADDRCONF */

??} else {
? ? /* If IP broadcast support is configured, we check for a broadcast
? ?? ? UDP packet, which may be destined to us. */
#if UIP_BROADCAST
? ? DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
? ? if(BUF->proto == UIP_PROTO_UDP &&
? ?? ? uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
? ?? ? /*&&
? ? ? ???uip_ipchksum() == 0xffff*/) {
? ?? ?goto udp_input;
? ? }
#endif /* UIP_BROADCAST */
? ? //檢查目的IP地址是否為本機地址
? ? /* Check if the packet is destined for our IP address. */
#if !UIP_CONF_IPV6
? ? if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
? ?? ?UIP_STAT(++uip_stat.ip.drop);
? ?? ?goto drop;//不是,丟棄此包
? ? }
#else /* UIP_CONF_IPV6 */
? ? /* For IPv6, packet reception is a little trickier as we need to
? ?? ? make sure that we listen to certain multicast addresses (all
? ?? ? hosts multicast address, and the solicited-node multicast
? ?? ? address) as well. However, we will cheat here and accept all
? ?? ? multicast packets that are sent to the ff02::/16 addresses. */
? ? if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
? ?? ? BUF->destipaddr[0] != HTONS(0xff02)) {
? ?? ?UIP_STAT(++uip_stat.ip.drop);
? ?? ?goto drop;//不是,丟棄此包
? ? }
#endif /* UIP_CONF_IPV6 */
??}

#if !UIP_CONF_IPV6
??if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ???checksum. */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.chkerr);
? ? UIP_LOG("ip: bad checksum.");
? ? goto drop;
??}
#endif /* UIP_CONF_IPV6 */
??//IP上層協議是否為TCP協議?
??if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ???proceed with TCP input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ???processing. */
? ? goto tcp_input;? ? ? ? //進入TCP數據處理模塊
??}

#if UIP_UDP
??if(BUF->proto == UIP_PROTO_UDP) {? ? ? ?? ?//IP上層協議是否為UDP協議?
? ? goto udp_input;? ? ? ? //進入UDP數據處理模塊
??}
#endif /* UIP_UDP */

#if !UIP_CONF_IPV6
??/* ICMPv4 processing code follows. */? ? ? ??
??//不是TCP不是UDP也不是ICMP協議?
??if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? here. */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.protoerr);
? ? UIP_LOG("ip: neither tcp nor icmp.");
? ? goto drop;? ? ? ???//本機只處理UDP、TCP、ICMP數據包,其它包都將丟棄?
??}

#if UIP_PINGADDRCONF
icmp_input: //是ICMP數據包
#endif /* UIP_PINGADDRCONF */
??UIP_STAT(++uip_stat.icmp.recv);
??//ICMP數據包處理部分
??/* ICMP echo (i.e., ping) processing. This is simple, we only change
? ???the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
? ???checksum before we return the packet. */
??if(ICMPBUF->type != ICMP_ECHO) {? ? ? ? //僅僅接收ECHO命令
? ? UIP_STAT(++uip_stat.icmp.drop);
? ? UIP_STAT(++uip_stat.icmp.typeerr);
? ? UIP_LOG("icmp: not icmp echo.");
? ? goto drop;? ? ? ? //若接收到別的命令,則將數據包丟棄。
??}

??/* If we are configured to use ping IP address assignment, we use
? ???the destination IP address of this ping packet and assign it to
? ???ourself. */
#if UIP_PINGADDRCONF
??if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
? ? uip_hostaddr[0] = BUF->destipaddr[0];
? ? uip_hostaddr[1] = BUF->destipaddr[1];
??}
#endif /* UIP_PINGADDRCONF */
??//若接收到的是ECHO命令則返回包含ECHO_REPLY的ICMP數據包給遠方主機,主要是用來響應ping命令
??ICMPBUF->type = ICMP_ECHO_REPLY;

??if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
? ? ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
??} else {
? ? ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
??}

??/* Swap IP addresses. */
??uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
??uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);

??UIP_STAT(++uip_stat.icmp.sent);
??goto send;

??/* End of IPv4 input header processing code. */
#else /* !UIP_CONF_IPV6 */

??/* This is IPv6 ICMPv6 processing code. */
??DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);

??if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???here. */
? ? UIP_STAT(++uip_stat.ip.drop);
? ? UIP_STAT(++uip_stat.ip.protoerr);
? ? UIP_LOG("ip: neither tcp nor icmp6.");
? ? goto drop;
??}

??UIP_STAT(++uip_stat.icmp.recv);

??/* If we get a neighbor solicitation for our address we should send
? ???a neighbor advertisement message back. */
??if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
? ? if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {

? ?? ?if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
? ? ? ? /* Save the sender's address in our neighbor list. */
? ? ? ? uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
? ?? ?}
? ?? ?
? ?? ?/* We should now send a neighbor advertisement back to where the
? ? ? ???neighbor solicication came from. */
? ?? ?ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
? ?? ?ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
? ?? ?
? ?? ?ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
? ?? ?
? ?? ?uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
? ?? ?uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
? ?? ?ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
? ?? ?ICMPBUF->options[1] = 1;??/* Options length, 1 = 8 bytes. */
? ?? ?memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
? ?? ?ICMPBUF->icmpchksum = 0;
? ?? ?ICMPBUF->icmpchksum = ~uip_icmp6chksum();
? ?? ?goto send;
? ?? ?
? ? }
? ? goto drop;
??} else if(ICMPBUF->type == ICMP6_ECHO) {
? ? /* ICMP echo (i.e., ping) processing. This is simple, we only
? ?? ? change the ICMP type from ECHO to ECHO_REPLY and update the
? ?? ? ICMP checksum before we return the packet. */
??//返回包含ECHO_REPLY的ICMP數據包給遠方主機,主要是用來響應ping命令
? ? ICMPBUF->type = ICMP6_ECHO_REPLY;
? ??
? ? uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
? ? uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
? ? ICMPBUF->icmpchksum = 0;
? ? ICMPBUF->icmpchksum = ~uip_icmp6chksum();
? ??
? ? UIP_STAT(++uip_stat.icmp.sent);
? ? goto send;
??} else {
? ? DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
? ? UIP_STAT(++uip_stat.icmp.drop);
? ? UIP_STAT(++uip_stat.icmp.typeerr);
? ? UIP_LOG("icmp: unknown ICMP message.");
? ? goto drop;
??}

??/* End of IPv6 ICMP processing. */
??
#endif /* !UIP_CONF_IPV6 */

#if UIP_UDP
??/* UDP input processing. */
udp_input:
??/* UDP processing is really just a hack. We don't do anything to the
? ???UDP/IP headers, but let the UDP application do all the hard
? ???work. If the application sets uip_slen, it has a packet to
? ???send. */
#if UIP_UDP_CHECKSUMS
??uip_len = uip_len - UIP_IPUDPH_LEN;
??uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
??if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {? ? ? ?? ?//根據要求校驗UDP
? ? UIP_STAT(++uip_stat.udp.drop);
? ? UIP_STAT(++uip_stat.udp.chkerr);
? ? UIP_LOG("udp: bad checksum.");
? ? goto drop;
??}
#else /* UIP_UDP_CHECKSUMS */
??uip_len = uip_len - UIP_IPUDPH_LEN;
#endif /* UIP_UDP_CHECKSUMS */
//在UDP連接列表中尋找接收到的數據包是否屬于列表中的連接
??/* Demultiplex this UDP packet between the UDP "connections". */
??for(uip_udp_conn = &uip_udp_conns[0];
? ?? ?uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
? ?? ?++uip_udp_conn) {
? ? /* If the local UDP port is non-zero, the connection is considered
? ?? ? to be used. If so, the local port number is checked against the
? ?? ? destination port number in the received packet. If the two port
? ?? ? numbers match, the remote port number is checked if the
? ?? ? connection is bound to a remote port. Finally, if the
? ?? ? connection is bound to a remote IP address, the source IP
? ?? ? address of the packet is checked. */
? ? if(uip_udp_conn->lport != 0 &&
? ?? ? UDPBUF->destport == uip_udp_conn->lport &&
? ?? ? (uip_udp_conn->rport == 0 ||
? ?? ???UDPBUF->srcport == uip_udp_conn->rport) &&
? ?? ? (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
? ? ? ? uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
? ? ? ? uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
? ?? ?goto udp_found;
? ? }
??}
??UIP_LOG("udp: no matching connection found");
??goto drop;??//如果不是則
??
udp_found:
??uip_conn = NULL;
??uip_flags = UIP_NEWDATA;? ? ? ? //接收到數據
??uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; //指向接收到的UDP包的數據部分
??uip_slen = 0;
??UIP_UDP_APPCALL();//使應用程序處理接收到的數據
udp_send:
??if(uip_slen == 0) { //表明沒有數據要發送
? ? goto drop;
??}
??//計算UDP數據包長度,填充UDP、IP幀頭中的數據長度及相關選項
??uip_len = uip_slen + UIP_IPUDPH_LEN;

#if UIP_CONF_IPV6
??/* For IPv6, the IP length field does not include the IPv6 IP header
? ???length. */
??BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
??BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
#else /* UIP_CONF_IPV6 */
??BUF->len[0] = (uip_len >> 8);
??BUF->len[1] = (uip_len & 0xff);
#endif /* UIP_CONF_IPV6 */

??BUF->ttl = uip_udp_conn->ttl;
??BUF->proto = UIP_PROTO_UDP;

??UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
??UDPBUF->udpchksum = 0;

??BUF->srcport??= uip_udp_conn->lport;
??BUF->destport = uip_udp_conn->rport;

??uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
??uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
? ?
??uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
??//根據要求計算校驗和
#if UIP_UDP_CHECKSUMS
??/* Calculate UDP checksum. */
??UDPBUF->udpchksum = ~(uip_udpchksum());
??if(UDPBUF->udpchksum == 0) {
? ? UDPBUF->udpchksum = 0xffff;
??}
#endif /* UIP_UDP_CHECKSUMS */
??
??goto ip_send_nolen; //發送UDP數據包
#endif /* UIP_UDP */
??
??/* TCP input processing. */
tcp_input:
??UIP_STAT(++uip_stat.tcp.recv);

??/* Start of TCP input header processing code. */
??//檢查TCP校驗和,若正確向下繼續,若錯誤則丟棄此包直接返回
??if(uip_tcpchksum() != 0xffff) {? ?/* Compute and check the TCP
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ???checksum. */
? ? UIP_STAT(++uip_stat.tcp.drop);
? ? UIP_STAT(++uip_stat.tcp.chkerr);
? ? UIP_LOG("tcp: bad checksum.");
? ? goto drop;
??}
??//在TCP連接列表uip_conns中輪詢,檢查接收到的TCP數據包是否已經建立連接
??//(通過逐個比較源端口、目的端口和源IP是否與鏈接列表中的相同)
??/* Demultiplex this segment. */
??/* First check any active connections. */
??for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
? ?? ?++uip_connr) {
? ? if(uip_connr->tcpstateflags != UIP_CLOSED &&
? ?? ? BUF->destport == uip_connr->lport &&
? ?? ? BUF->srcport == uip_connr->rport &&
? ?? ? uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
? ?? ?goto found;//若找到
? ? }
??}

??/* If we didn't find and active connection that expected the packet,
? ???either this packet is an old duplicate, or this is a SYN packet
? ???destined for a connection in LISTEN. If the SYN flag isn't set,
? ???it is an old packet and we send a RST. */
??if((BUF->flags & TCP_CTL) != TCP_SYN) {??//沒有找到則檢查接收到的TCP數據包中是否含有SYN請求建立連接標志
? ? goto reset;? ? ? ???//若沒有則,發送RST+ACK斷開連接
??}
??
??tmp16 = BUF->destport;

??/* Next, check listening connections. */
??for(c = 0; c < UIP_LISTENPORTS; ++c) {
? ? if(tmp16 == uip_listenports[c])
? ?? ?goto found_listen;//若有則檢查uip_listenports監聽列表,若TCP數據包目的端口在監聽列表中則
??}
//若不在監聽列表中則向下執行,進入 reset;發送RST+ACK斷開連接?
??/* No matching connection found, so we send a RST packet. */
??UIP_STAT(++uip_stat.tcp.synrst);
reset:

??/* We do not send resets in response to resets. */
??if (BUF->flags & TCP_RST) {? ? ? ? //接收到的是RST斷開連接包,則直接丟包返回
? ? ? ? //uip_arp_close(BUF->srcipaddr);?
? ? ? ???//增加對TCP_RST的響應處理,發送TCP_ACK
? ? ? ???UIP_LOG("tcp-1: got reset, aborting connection.");
? ?/* uip_connr->tcpstateflags = UIP_CLOSED;
? ? UIP_LOG("tcp-1: got reset, aborting connection.");
? ? uip_flags = UIP_ABORT;
? ? UIP_APPCALL();
//? ? ? ? uip_arp_close(uip_connr->ripaddr);
//增加對TCP_RST的響應處理,發送TCP_ACK
? ? BUF->flags = TCP_ACK;? ? ? ??
? ? ? ? goto tcp_send_nodata;*/
? ? goto drop;
??}

??UIP_STAT(++uip_stat.tcp.rst);
??//設置RST+ACK標志,填充適當的TCP幀頭
??BUF->flags = TCP_RST | TCP_ACK;
??uip_len = UIP_IPTCPH_LEN;
??BUF->tcpoffset = 5 << 4;

??/* Flip the seqno and ackno fields in the TCP header. */
??c = BUF->seqno[3];
??BUF->seqno[3] = BUF->ackno[3];
??BUF->ackno[3] = c;
??
??c = BUF->seqno[2];
??BUF->seqno[2] = BUF->ackno[2];
??BUF->ackno[2] = c;
??
??c = BUF->seqno[1];
??BUF->seqno[1] = BUF->ackno[1];
??BUF->ackno[1] = c;
??
??c = BUF->seqno[0];
??BUF->seqno[0] = BUF->ackno[0];
??BUF->ackno[0] = c;

??/* We also have to increase the sequence number we are
? ???acknowledging. If the least significant byte overflowed, we need
? ???to propagate the carry to the other bytes as well. */
??if(++BUF->ackno[3] == 0) {
? ? if(++BUF->ackno[2] == 0) {
? ?? ?if(++BUF->ackno[1] == 0) {
? ? ? ? ++BUF->ackno[0];
? ?? ?}
? ? }
??}

??/* Swap port numbers. */
??tmp16 = BUF->srcport;
??BUF->srcport = BUF->destport;
??BUF->destport = tmp16;
??
??/* Swap IP addresses. */
??uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
??uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
??
??/* And send out the RST packet! */
??goto tcp_send_noconn;//發送TCP數據

??/* This label will be jumped to if we matched the incoming packet
? ???with a connection in LISTEN. In that case, we should create a new
? ???connection and send a SYNACK in return. */
found_listen:? ? ? ? //被動連接
??/* First we check if there are any connections avaliable. Unused
? ???connections are kept in the same table as used connections, but
? ???unused ones have the tcpstate set to CLOSED. Also, connections in
? ???TIME_WAIT are kept track of and we'll use the oldest one if no
? ???CLOSED connections are found. Thanks to Eddie C. Dost for a very
? ???nice algorithm for the TIME_WAIT search. */
??uip_connr = 0;
??for(c = 0; c < UIP_CONNS; ++c) {
? ? if(uip_conns[c].tcpstateflags == UIP_CLOSED) { //從鏈接列表中找出一個空鏈接或剩余生存時間最短的連接
? ?? ?uip_connr = &uip_conns[c];
? ?? ?break;
? ? }
? ? if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
? ?? ?if(uip_connr == 0 ||
? ? ? ???uip_conns[c].timer > uip_connr->timer) {
? ? ? ? uip_connr = &uip_conns[c];
? ?? ?}
? ? }
??}

??if(uip_connr == 0) {
? ? /* All connections are used already, we drop packet and hope that
? ?? ? the remote end will retransmit the packet at a time when we
? ?? ? have more spare connections. */
? ? UIP_STAT(++uip_stat.tcp.syndrop);
? ? UIP_LOG("tcp: found no unused connections.");
? ? goto drop;
??}
??uip_conn = uip_connr;? ? ? ? //將找到的鏈接列表根據接收到的TCP數據包進行初始化
??
??/* Fill in the necessary fields for the new connection. */
??uip_connr->rto = uip_connr->timer = UIP_RTO;
??uip_connr->sa = 0;
??uip_connr->sv = 4;
??uip_connr->nrtx = 0;
??uip_connr->lport = BUF->destport;
??uip_connr->rport = BUF->srcport;
??uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
??uip_connr->tcpstateflags = UIP_SYN_RCVD;//設置TCP狀態為UIP_SYN_RCVD

??uip_connr->snd_nxt[0] = iss[0];??// 第二次握手用的seqno賦值,該值是有暫定。
??uip_connr->snd_nxt[1] = iss[1];
??uip_connr->snd_nxt[2] = iss[2];
??uip_connr->snd_nxt[3] = iss[3];
??uip_connr->len = 1;

??/* rcv_nxt should be the seqno from the incoming packet + 1. */
??uip_connr->rcv_nxt[3] = BUF->seqno[3];? ?// 將對方第一次握手發送的seqno+1賦值給
??uip_connr->rcv_nxt[2] = BUF->seqno[2];? ?// 第二次握手用的ackno
??uip_connr->rcv_nxt[1] = BUF->seqno[1];
??uip_connr->rcv_nxt[0] = BUF->seqno[0];
??uip_add_rcv_nxt(1);
//分析TCP的最大段長度
??/* Parse the TCP MSS option, if present. */
??if((BUF->tcpoffset & 0xf0) > 0x50) {
? ? for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
? ?? ?opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
? ?? ?if(opt == TCP_OPT_END) {
? ? ? ? /* End of options. */
? ? ? ? break;
? ?? ?} else if(opt == TCP_OPT_NOOP) {
? ? ? ? ++c;
? ? ? ? /* NOP option. */
? ?? ?} else if(opt == TCP_OPT_MSS &&
? ? ? ? ? ? ? ? uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
? ? ? ? /* An MSS option with the right option length. */
? ? ? ? tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
? ? ? ?? ?(u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
? ? ? ? uip_connr->initialmss = uip_connr->mss =
? ? ? ?? ?tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
? ? ? ??
? ? ? ? /* And we are done processing options. */
? ? ? ? break;
? ?? ?} else {
? ? ? ? /* All other options have a length field, so that we easily
? ? ? ?? ? can skip past them. */
? ? ? ? if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
? ? ? ?? ?/* If the length field is zero, the options are malformed
? ? ? ?? ?? ?and we don't process them further. */
? ? ? ?? ?break;
? ? ? ? }
? ? ? ? c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
? ?? ?}
? ? }
??}
//發送ACK?
??/* Our response will be a SYNACK. */
#if UIP_ACTIVE_OPEN
tcp_send_synack:
??BUF->flags = TCP_ACK;//設置ACK標志
??
tcp_send_syn:
??BUF->flags |= TCP_SYN; //設置SYN標志
#else /* UIP_ACTIVE_OPEN */
tcp_send_synack:
??BUF->flags = TCP_SYN | TCP_ACK;
#endif /* UIP_ACTIVE_OPEN */
??//填充TCP選項中最大報文段長度MSS
??/* We send out the TCP Maximum Segment Size option with our
? ???SYNACK. */
??BUF->optdata[0] = TCP_OPT_MSS;
??BUF->optdata[1] = TCP_OPT_MSS_LEN;
??BUF->optdata[2] = (UIP_TCP_MSS) / 256;
??BUF->optdata[3] = (UIP_TCP_MSS) & 255;
??uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
??BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
??goto tcp_send;

??/* This label will be jumped to if we found an active connection. */
found:? ? ? ?? ?//主動鏈接部分
??uip_conn = uip_connr;
??uip_flags = 0;
??/* We do a very naive form of TCP reset processing; we just accept
? ???any RST and kill our connection. We should in fact check if the
? ???sequence number of this reset is wihtin our advertised window
? ???before we accept the reset. */
??if(BUF->flags & TCP_RST) {//若接收到的是RST數據包,則將本連接狀態置為UIP_CLOSED
? ? uip_connr->tcpstateflags = UIP_CLOSED;
? ? UIP_LOG("tcp: got reset, aborting connection.");
? ? uip_flags = UIP_ABORT;
? ? UIP_APPCALL();? ? ? ???//通知應用程序處理連接斷開請求。然后丟棄此包,直接返回
? ? goto drop;
??}
??/* Calculated the length of the data, if the application has sent
? ???any data to us. */
??c = (BUF->tcpoffset >> 4) << 2;
??/* uip_len will contain the length of the actual TCP data. This is
? ???calculated by subtracing the length of the TCP header (in
? ???c) and the length of the IP header (20 bytes). */
??uip_len = uip_len - c - UIP_IPH_LEN;

??/* First, check if the sequence number of the incoming packet is
? ???what we're expecting next. If not, we send out an ACK with the
? ???correct numbers in. */
??if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
? ?? ? ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
? ? if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
? ?? ? (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
? ? ? ? BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
? ? ? ? BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
? ? ? ? BUF->seqno[3] != uip_connr->rcv_nxt[3])) { //檢查接收到的數據包中的數據編號是否為自己等在等待的數據編號
? ?? ?goto tcp_send_ack;? ?//若不是則發送自己期望的數據編號的數據,即請求重傳
? ? }
??}
??//檢查接收到的數據包中是否包含ACK
??/* Next, check if the incoming segment acknowledges any outstanding
? ???data. If so, we update the sequence number, reset the length of
? ???the outstanding data, calculate RTT estimations, and reset the
? ???retransmission timer. */
??if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {? ?// 收到了ACK幀,同時有待確認的數據
? ?// uip_connr->len 用于記錄本次發送的字節數
? ?// 在第三次握手中uip_connr->len = 1
? ? uip_add32(uip_connr->snd_nxt, uip_connr->len);// 計算下一次發送的第一個字節的序列號
? ? ? ???
? ? if(BUF->ackno[0] == uip_acc32[0] &&
? ?? ? BUF->ackno[1] == uip_acc32[1] &&
? ?? ? BUF->ackno[2] == uip_acc32[2] &&
? ?? ? BUF->ackno[3] == uip_acc32[3]) {
? ?? ?/* Update sequence number. */
? ?? ?uip_connr->snd_nxt[0] = uip_acc32[0];? ? ? ?? ?//更新發送數據序列的編號,使之可以發送后續數據
? ?? ?uip_connr->snd_nxt[1] = uip_acc32[1];
? ?? ?uip_connr->snd_nxt[2] = uip_acc32[2];
? ?? ?uip_connr->snd_nxt[3] = uip_acc32[3];
? ? ? ??
? ? ? ? // 計算RTT時間,重新設置RTT時間
? ?? ?/* Do RTT estimation, unless we have done retransmissions. */
? ?? ?if(uip_connr->nrtx == 0) {
? ? ? ? signed char m;
? ? ? ? m = uip_connr->rto - uip_connr->timer;
? ? ? ? /* This is taken directly from VJs original code in his paper */
? ? ? ? m = m - (uip_connr->sa >> 3);
? ? ? ? uip_connr->sa += m;
? ? ? ? if(m < 0) {
? ? ? ?? ?m = -m;
? ? ? ? }
? ? ? ? m = m - (uip_connr->sv >> 2);
? ? ? ? uip_connr->sv += m;
? ? ? ? uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;

? ?? ?}
? ?? ?/* Set the acknowledged flag. */
? ?? ?uip_flags = UIP_ACKDATA;//表明接收到ACK
? ?? ?/* Reset the retransmission timer. */
? ?? ?uip_connr->timer = uip_connr->rto;

? ?? ?/* Reset length of outstanding data. */
? ?? ?uip_connr->len = 0; //表明等待ACK的數據長度為0,即可以發送其它數據?
? ? }
? ? ? ? else
? ? ? ? {
??? ?? ???//當MCU作為TCP服務器時,如果ackno 與 uip_acc32
? ?? ?? ? //不一致時,會引起無法重新連接或發送數據, 當時等待發起連接端情動TCP_RST之后,允許重新連接
? ?? ?? ?//需要在用戶應用里如何處理? 或這里增加如何處理?
? ? ? ?? ? UIP_LOG("tcp: snd_nxt ,ackno reset ??? .");
? ? ? ? }?
??}
//檢查TCP狀態機制
??/* Do different things depending on in what state the connection is. */
??switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
? ? /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
? ? ? ? implemented, since we force the application to close when the
? ? ? ? peer sends a FIN (hence the application goes directly from
? ? ? ? ESTABLISHED to LAST_ACK). */
??case UIP_SYN_RCVD: //是否接收到對自己發送SYN的ACK確認
? ? /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
? ?? ? we are waiting for an ACK that acknowledges the data we sent
? ?? ? out the last time. Therefore, we want to have the UIP_ACKDATA
? ?? ? flag set. If so, we enter the ESTABLISHED state. */
? ? if(uip_flags & UIP_ACKDATA) {
? ?? ?uip_connr->tcpstateflags = UIP_ESTABLISHED; //若是,進入ESTABLISHED狀態
? ?? ?uip_flags = UIP_CONNECTED; //連接成功
? ?? ?uip_connr->len = 0;
? ?? ?if(uip_len > 0) {? ? ? ???//檢查數據包長度是否包含數據部分
? ?? ???uip_flags |= UIP_NEWDATA; //是
? ?? ???uip_add_rcv_nxt(uip_len);
? ?? ?}
? ?? ?uip_slen = 0;
? ?? ?UIP_APPCALL(); //處理剛建立的連接和新接收到數據
? ?? ?goto appsend;
? ? }
? ? goto drop;//若不是則丟包返回;
#if UIP_ACTIVE_OPEN
??case UIP_SYN_SENT:
? ? /* In SYN_SENT, we wait for a SYNACK that is sent in response to
? ?? ? our SYN. The rcv_nxt is set to sequence number in the SYNACK
? ?? ? plus one, and we send an ACK. We move into the ESTABLISHED
? ?? ? state. */
? ? if((uip_flags & UIP_ACKDATA) &&
? ?? ? (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {? ? ? ? //如果接收到ACK且為SYN+ACK

? ?? ?/* Parse the TCP MSS option, if present. */
? ?? ?if((BUF->tcpoffset & 0xf0) > 0x50) { //檢查TCP擴展選項,如果有擴展選項從中取出MSS信息
? ? ? ? for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
? ? ? ?? ?opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
? ? ? ?? ?if(opt == TCP_OPT_END) {
? ? ? ?? ???/* End of options. */
? ? ? ?? ???break;
? ? ? ?? ?} else if(opt == TCP_OPT_NOOP) {
? ? ? ?? ???++c;
? ? ? ?? ???/* NOP option. */
? ? ? ?? ?} else if(opt == TCP_OPT_MSS &&
? ? ? ? ? ? ? ?? ???uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
? ? ? ?? ???/* An MSS option with the right option length. */
? ? ? ?? ???tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
? ? ? ?? ?? ? uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
? ? ? ?? ???uip_connr->initialmss =
? ? ? ?? ?? ? uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;

? ? ? ?? ???/* And we are done processing options. */
? ? ? ?? ???break;
? ? ? ?? ?} else {
? ? ? ?? ???/* All other options have a length field, so that we easily
? ? ? ?? ?? ???can skip past them. */
? ? ? ?? ???if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
? ? ? ?? ?? ? /* If the length field is zero, the options are malformed
? ? ? ? ? ? ? ???and we don't process them further. */
? ? ? ?? ?? ? break;
? ? ? ?? ???}
? ? ? ?? ???c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
? ? ? ?? ?}
? ? ? ? }
? ?? ?}
? ?? ?uip_connr->tcpstateflags = UIP_ESTABLISHED; //進入ESTABLISHED狀態
? ?? ?//設置接收編號
? ? ? ?? ?uip_connr->rcv_nxt[0] = BUF->seqno[0];// 用于第三次握手的ackno,將收到的
? ?? ?uip_connr->rcv_nxt[1] = BUF->seqno[1]; // 第二次握手中的seqno+1賦值給第三
? ?? ?uip_connr->rcv_nxt[2] = BUF->seqno[2]; // 次握手中的ackno
? ?? ?uip_connr->rcv_nxt[3] = BUF->seqno[3];
? ?? ?uip_add_rcv_nxt(1);? ?// uip_connr->rcv_nxt[3] = uip_connr->rcv_nxt[3]+1
? ?? ?uip_flags = UIP_CONNECTED | UIP_NEWDATA; //設置接收編號
? ?? ?uip_connr->len = 0;
? ?? ?uip_len = 0;
? ?? ?uip_slen = 0;
? ?? ?UIP_APPCALL();//處理剛建立的連接和新接收到數據
? ?? ?goto appsend;
? ? }
? ? ? ? //沒有接收到ACK且為SYN+ACK則
? ? /* Inform the application that the connection failed */
? ? uip_flags = UIP_ABORT;//終止連接
? ? UIP_APPCALL();
? ? /* The connection is closed after we send the RST */
? ? uip_conn->tcpstateflags = UIP_CLOSED; //關閉TCP連接
? ? ? ? //uip_arp_close(uip_connr->ripaddr);
? ? goto reset;
#endif /* UIP_ACTIVE_OPEN */
? ??
??case UIP_ESTABLISHED:
? ? /* In the ESTABLISHED state, we call upon the application to feed
? ? data into the uip_buf. If the UIP_ACKDATA flag is set, the
? ? application should put new data into the buffer, otherwise we are
? ? retransmitting an old segment, and the application should put that
? ? data into the buffer.

? ? If the incoming packet is a FIN, we should close the connection on
? ? this side as well, and we send out a FIN and enter the LAST_ACK
? ? state. We require that there is no outstanding data; otherwise the
? ? sequence numbers will be screwed up. */
? ? ? ? //接收到遠方主機的FIN請求
? ? if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
? ?? ?if(uip_outstanding(uip_connr)) {
? ? ? ? goto drop;
? ?? ?}
//計算ackno:
? ?? ?uip_add_rcv_nxt(1 + uip_len);? ? ? ? //uip_connr->rcv_nxt+1+uip_len,其中uip_len是接收到的數據長度。
? ?? ?uip_flags |= UIP_CLOSE;? ? ? ? //關閉TCP連接
? ?? ?if(uip_len > 0) {
? ? ? ? uip_flags |= UIP_NEWDATA;//如果接收到的數據包中還包含有數據
? ?? ?}
? ?? ?UIP_APPCALL();
? ?? ?uip_connr->len = 1;
? ?? ?uip_connr->tcpstateflags = UIP_LAST_ACK;
? ?? ?uip_connr->nrtx = 0;
? ? tcp_send_finack:
? ?? ?BUF->flags = TCP_FIN | TCP_ACK;//發送TCP_FIN +TCP_ACK,關閉連接
? ?? ?goto tcp_send_nodata;
? ? }

? ? /* Check the URG flag. If this is set, the segment carries urgent
? ?? ? data that we must pass to the application. */
? ? if((BUF->flags & TCP_URG) != 0) {
#if UIP_URGDATA > 0
? ?? ?uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
? ?? ?if(uip_urglen > uip_len) {
? ? ? ? /* There is more urgent data in the next segment to come. */
? ? ? ? uip_urglen = uip_len;
? ?? ?}
? ?? ?uip_add_rcv_nxt(uip_urglen);
? ?? ?uip_len -= uip_urglen;
? ?? ?uip_urgdata = uip_appdata;
? ?? ?uip_appdata += uip_urglen;
? ? } else {
? ?? ?uip_urglen = 0;
#else /* UIP_URGDATA > 0 */
? ?? ?uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
? ?? ?uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
#endif /* UIP_URGDATA > 0 */
? ? }

? ? /* If uip_len > 0 we have TCP data in the packet, and we flag this
? ?? ? by setting the UIP_NEWDATA flag and update the sequence number
? ?? ? we acknowledge. If the application has stopped the dataflow
? ?? ? using uip_stop(), we must not accept any data packets from the
? ?? ? remote host. */
? ? if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
? ?? ?uip_flags |= UIP_NEWDATA;
? ?? ?uip_add_rcv_nxt(uip_len);
? ? }

? ? /* Check if the available buffer space advertised by the other end
? ?? ? is smaller than the initial MSS for this connection. If so, we
? ?? ? set the current MSS to the window size to ensure that the
? ?? ? application does not send more data than the other end can
? ?? ? handle.

? ?? ? If the remote host advertises a zero window, we set the MSS to
? ?? ? the initial MSS so that the application will send an entire MSS
? ?? ? of data. This data will not be acknowledged by the receiver,
? ?? ? and the application will retransmit it. This is called the
? ?? ? "persistent timer" and uses the retransmission mechanim.
? ? */
? ? tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
? ? if(tmp16 > uip_connr->initialmss ||
? ?? ? tmp16 == 0) {
? ?? ?tmp16 = uip_connr->initialmss;
? ? }
? ? uip_connr->mss = tmp16;

? ? /* If this packet constitutes an ACK for outstanding data (flagged
? ?? ? by the UIP_ACKDATA flag, we should call the application since it
? ?? ? might want to send more data. If the incoming packet had data
? ?? ? from the peer (as flagged by the UIP_NEWDATA flag), the
? ?? ? application must also be notified.

? ?? ? When the application is called, the global variable uip_len
? ?? ? contains the length of the incoming data. The application can
? ?? ? access the incoming data through the global pointer
? ?? ? uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
? ?? ? bytes into the uip_buf array.

? ?? ? If the application wishes to send any data, this data should be
? ?? ? put into the uip_appdata and the length of the data should be
? ?? ? put into uip_len. If the application don't have any data to
? ?? ? send, uip_len must be set to 0. */
? ? if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {//如果接收到的數據狀態
? ?? ?uip_slen = 0;
? ?? ?UIP_APPCALL(); //處理接收到的包

? ? appsend:
? ?? ?
? ?? ?if(uip_flags & UIP_ABORT) { //如果是終止連接
? ? ? ? uip_slen = 0;
? ? ? ? uip_connr->tcpstateflags = UIP_CLOSED;//終止連接
? ? ? ? BUF->flags = TCP_RST | TCP_ACK;? ? ? ? //發送RST+ACK關閉連接
? ? ? ? goto tcp_send_nodata;
? ?? ?}

? ?? ?if(uip_flags & UIP_CLOSE) { //如果是正常關閉連接
? ? ? ? uip_slen = 0;
? ? ? ? uip_connr->len = 1;
? ? ? ? uip_connr->tcpstateflags = UIP_FIN_WAIT_1; //進入等待關閉狀態
? ? ? ? uip_connr->nrtx = 0;
? ? ? ? BUF->flags = TCP_FIN | TCP_ACK;//發送FIN+ACK告知對方關閉連接
? ? ? ? goto tcp_send_nodata;
? ?? ?}

? ?? ?/* If uip_slen > 0, the application has data to be sent. */
? ?? ?if(uip_slen > 0) {??//如果有數據要發送則設置發送數據的長度

? ? ? ? /* If the connection has acknowledged data, the contents of
? ? ? ?? ? the ->len variable should be discarded. */
? ? ? ? if((uip_flags & UIP_ACKDATA) != 0) {
? ? ? ?? ?uip_connr->len = 0;
? ? ? ? }

? ? ? ? /* If the ->len variable is non-zero the connection has
? ? ? ?? ? already data in transit and cannot send anymore right
? ? ? ?? ? now. */
? ? ? ? if(uip_connr->len == 0) {

? ? ? ?? ?/* The application cannot send more than what is allowed by
? ? ? ?? ?? ?the mss (the minumum of the MSS and the available
? ? ? ?? ?? ?window). */
? ? ? ?? ?if(uip_slen > uip_connr->mss) {
? ? ? ?? ???uip_slen = uip_connr->mss;
? ? ? ?? ?}

? ? ? ?? ?/* Remember how much data we send out now so that we know
? ? ? ?? ?? ?when everything has been acknowledged. */
? ? ? ?? ?uip_connr->len = uip_slen;
? ? ? ? } else {

? ? ? ?? ?/* If the application already had unacknowledged data, we
? ? ? ?? ?? ?make sure that the application does not send (i.e.,
? ? ? ?? ?? ?retransmit) out more than it previously sent out. */
? ? ? ?? ?uip_slen = uip_connr->len;
? ? ? ? }
? ?? ?}
? ?? ?uip_connr->nrtx = 0;
? ? apprexmit:
? ?? ?uip_appdata = uip_sappdata;
? ?? ?
? ?? ?/* If the application has data to be sent, or if the incoming
? ?? ?? ?packet had new data in it, we must send out a packet. */
? ?? ?if(uip_slen > 0 && uip_connr->len > 0) {? ? ? ? //發送PSH_ACK數據包;
? ? ? ? /* Add the length of the IP and TCP headers. */
? ? ? ? uip_len = uip_connr->len + UIP_TCPIP_HLEN;
? ? ? ? /* We always set the ACK flag in response packets. */
? ? ? ? BUF->flags = TCP_ACK | TCP_PSH;
? ? ? ? /* Send the packet. */
? ? ? ? goto tcp_send_noopts;
? ?? ?}
? ?? ?/* If there is no data to send, just send out a pure ACK if
? ? ? ???there is newdata. */
? ?? ?if(uip_flags & UIP_NEWDATA) {//僅僅是發送ACK
? ? ? ? uip_len = UIP_TCPIP_HLEN;
? ? ? ? BUF->flags = TCP_ACK; //沒有數據要發送則發送對接收到數據的ACK
? ? ? ? goto tcp_send_noopts;
? ?? ?}
? ? }
? ? goto drop;
??case UIP_LAST_ACK:
? ? /* We can close this connection if the peer has acknowledged our
? ?? ? FIN. This is indicated by the UIP_ACKDATA flag. */
? ? if(uip_flags & UIP_ACKDATA) { //接收到對本機發送的FIN的ACK確認
? ?? ?uip_connr->tcpstateflags = UIP_CLOSED; //將連接置為關閉狀態
? ?? ?uip_flags = UIP_CLOSE;
? ?? ?UIP_APPCALL();? ? ? ? //通知應用程序連接已經斷開
? ? }
? ? break;
? ??
??case UIP_FIN_WAIT_1:
? ? /* The application has closed the connection, but the remote host
? ?? ? hasn't closed its end yet. Thus we do nothing but wait for a
? ?? ? FIN from the other side. */
? ? if(uip_len > 0) { //此時本機已經關閉連接等待對方關閉連接,如果接收到數據并不處理,僅僅將接收到數據包數目加一
? ?? ?uip_add_rcv_nxt(uip_len);
? ? }
? ? if(BUF->flags & TCP_FIN) { //如果接收到FIN請求
? ?? ?if(uip_flags & UIP_ACKDATA) {? ? ? ? //接收到對本機發送FIN的確認則將連接狀態置為
? ? ? ? uip_connr->tcpstateflags = UIP_TIME_WAIT;
? ? ? ? uip_connr->timer = 0;
? ? ? ? uip_connr->len = 0;
? ?? ?} else {
? ? ? ? uip_connr->tcpstateflags = UIP_CLOSING;? ? ? ? //將連接狀態置為
? ?? ?}
? ?? ?uip_add_rcv_nxt(1);
? ?? ?uip_flags = UIP_CLOSE;//通知應用程序有一方已經關閉連接
? ?? ?UIP_APPCALL();
? ?? ?goto tcp_send_ack;
? ? } else if(uip_flags & UIP_ACKDATA) { //僅僅接收到ACK則設置連接狀態標志
? ?? ?uip_connr->tcpstateflags = UIP_FIN_WAIT_2; // 進入等待對方關閉階段
? ?? ?uip_connr->len = 0;
? ?? ?goto drop;
? ? }
? ? if(uip_len > 0) { //表明接收到數據包
? ?? ?goto tcp_send_ack; //發送對接收到數據的確認ACK
? ? }
? ? goto drop;
? ?? ?
??case UIP_FIN_WAIT_2:
? ? if(uip_len > 0) { //此時本機已經關閉連接等待對方關閉連接,如果接收到數據并不處理,僅僅將接收到數據包數目加一
? ?? ?uip_add_rcv_nxt(uip_len);
? ? }
? ? if(BUF->flags & TCP_FIN) {//如果接收到對方發送的FIN請求
? ?? ?uip_connr->tcpstateflags = UIP_TIME_WAIT;//進入超時關閉狀態
? ?? ?uip_connr->timer = 0;
? ?? ?uip_add_rcv_nxt(1);
? ?? ?uip_flags = UIP_CLOSE;
? ?? ?UIP_APPCALL();//通知應用程序有一方已經關閉連接?
? ?? ?goto tcp_send_ack;
? ? }
? ? if(uip_len > 0) { //表明接收到數據包
? ?? ?goto tcp_send_ack;//發送對接收到數據的確認ACK
? ? }
? ? goto drop;

??case UIP_TIME_WAIT:
? ? goto tcp_send_ack;
? ??
??case UIP_CLOSING:
? ? if(uip_flags & UIP_ACKDATA) { //接收到對FIN的ACK
? ?? ?uip_connr->tcpstateflags = UIP_TIME_WAIT;? ? ? ? //連接進入超時等待狀態
? ?? ?uip_connr->timer = 0;
? ? }
??}
??goto drop;
??

??/* We jump here when we are ready to send the packet, and just want
? ???to set the appropriate TCP sequence numbers in the TCP header. */
tcp_send_ack:
??BUF->flags = TCP_ACK;//設置ACK標志
tcp_send_nodata:
??uip_len = UIP_IPTCPH_LEN;? ? ? ? //將長度設為幀頭長度,不包含數據
tcp_send_noopts:
??BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;? ? ? ???//將選項長度設為0
tcp_send:? ? ? ? //發送自己期望的數據編號的數據,即請求重發送自己期望的數據編號的數據,即請求重傳
??/* We're done with the input processing. We are now ready to send a
? ???reply. Our job is to fill in all the fields of the TCP and IP
? ???headers before calculating the checksum and finally send the
? ???packet. */
//寫入序號值, must do !!!?
//填充TCP幀頭確認編號和發送編號,IP地址和端口號
??BUF->ackno[0] = uip_connr->rcv_nxt[0];
??BUF->ackno[1] = uip_connr->rcv_nxt[1];
??BUF->ackno[2] = uip_connr->rcv_nxt[2];
??BUF->ackno[3] = uip_connr->rcv_nxt[3];
??
??BUF->seqno[0] = uip_connr->snd_nxt[0];
??BUF->seqno[1] = uip_connr->snd_nxt[1];
??BUF->seqno[2] = uip_connr->snd_nxt[2];
??BUF->seqno[3] = uip_connr->snd_nxt[3];

??BUF->proto = UIP_PROTO_TCP;
??
??BUF->srcport??= uip_connr->lport;
??BUF->destport = uip_connr->rport;

??uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
??uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);

??if(uip_connr->tcpstateflags & UIP_STOPPED) { //要求暫停發送數據則將接收窗口設為0;禁止對方往自己發送數據
? ? /* If the connection has issued uip_stop(), we advertise a zero
? ?? ? window so that the remote host will stop sending data. */
? ? BUF->wnd[0] = BUF->wnd[1] = 0;
??} else {
? ? BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
? ? BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
??}

tcp_send_noconn:
??BUF->ttl = UIP_TTL; //設置TCP包生存時間,傳送的數據的長度
#if UIP_CONF_IPV6
??/* For IPv6, the IP length field does not include the IPv6 IP header
? ???length. */
??BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
??BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
#else /* UIP_CONF_IPV6 */
??BUF->len[0] = (uip_len >> 8);
??BUF->len[1] = (uip_len & 0xff);
#endif /* UIP_CONF_IPV6 */

??BUF->urgp[0] = BUF->urgp[1] = 0;
??
??/* Calculate TCP checksum. */
??BUF->tcpchksum = 0;
??BUF->tcpchksum = ~(uip_tcpchksum()); //)計算TCP校驗和
??
ip_send_nolen:
? ?//設置IP幀頭中的各個選項
#if UIP_CONF_IPV6
??BUF->vtc = 0x60;
??BUF->tcflow = 0x00;
??BUF->flow = 0x00;
#else /* UIP_CONF_IPV6 */
??BUF->vhl = 0x45;
??BUF->tos = 0;
??BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
??++ipid;
??BUF->ipid[0] = ipid >> 8;
??BUF->ipid[1] = ipid & 0xff;
??/* Calculate IP checksum. */
??BUF->ipchksum = 0;
??BUF->ipchksum = ~(uip_ipchksum()); //計算IP校驗和
//??DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
#endif /* UIP_CONF_IPV6 */
??
??UIP_STAT(++uip_stat.tcp.sent);
send:
// DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
//? ? ? ?? ?? ???(BUF->len[0] << 8) | BUF->len[1]);
? ?//將發送的數據包計數器加一
??UIP_STAT(++uip_stat.ip.sent);
??/* Return and let the caller do the actual transmission. */
??uip_flags = 0;
??return;
drop:
??uip_len = 0;
??uip_flags = 0;
??return;
}

?

/*---------------------------------------------------------------------------*

總結

以上是生活随笔為你收集整理的uip1.0核心模块uip_process函数解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

日韩特黄av | 日韩在线网址 | 国产人成在线视频 | 五月婷亚洲 | 麻豆av电影| 天天干天天碰 | 视频91| 在线免费视频a | 成人免费观看在线视频 | 狠狠狠色丁香婷婷综合久久五月 | 在线免费观看国产视频 | 久久婷五月 | 特级毛片网站 | 麻花豆传媒mv在线观看网站 | 日韩电影一区二区在线 | 日日干美女 | 99热在线观看 | 久久夜色电影 | 91中文字幕永久在线 | 久草在线免费播放 | 亚洲精欧美一区二区精品 | 精品99免费视频 | 91福利社在线观看 | 最新日韩视频 | 成人黄色av免费在线观看 | 国内精品久久久久久久影视简单 | 狠狠久久| 国产精品门事件 | 91视频大全 | 91av大全 | 国产又粗又猛又黄又爽 | 久久五月天综合 | 天堂av观看 | 欧美最猛性xxx | 日韩中文字幕免费在线播放 | 九九热re| 日韩| 99热精品久久 | 一级黄色片网站 | 国产精品麻豆99久久久久久 | 97超碰在线免费观看 | 日韩精品一区二区三区三炮视频 | 国产在线成人 | 99热在线精品观看 | 天天爽天天搞 | 日本特黄一级 | 激情丁香综合五月 | 国产99在线播放 | 日本九九视频 | 午夜体验区 | 日韩色在线 | 亚洲最新精品 | 国产精品美女久久久久久2018 | 亚洲砖区区免费 | 蜜臀av在线一区二区三区 | 国产xxxx做受性欧美88 | 色噜噜日韩精品一区二区三区视频 | 日韩综合视频在线观看 | 精品成人a区在线观看 | 毛片精品免费在线观看 | 911av视频| 久久综合久色欧美综合狠狠 | 色91在线| 国产精品久久久久久久久久尿 | 国产成人高清在线 | 综合激情av | 亚州精品成人 | 亚洲欧洲在线视频 | 免费三级网| 色婷婷五 | 日韩电影在线观看一区 | 亚洲精品国产精品99久久 | 色福利网 | 成人一区电影 | 日一日干一干 | 在线观看不卡视频 | 久久免费的精品国产v∧ | 人人插人人玩 | av在线一级| 国产午夜精品一区二区三区在线观看 | 亚在线播放中文视频 | 91麻豆精品国产自产在线 | 国产一区二区视频在线 | 久久久精品成人 | 97成人在线观看 | 高清在线一区二区 | 国产欧美综合在线观看 | 在线网址你懂得 | 久久 亚洲视频 | 中文av在线免费观看 | 国产精品日韩久久久久 | 丁香婷婷久久 | 国产一区二区在线免费播放 | 99久久精品国产免费看不卡 | 国产精品1区2区在线观看 | 久久国产精品第一页 | 国产三级视频 | 91精品国| 久色 网 | 91精品天码美女少妇 | 成人在线视频免费观看 | 国内精品在线看 | 国产精品亚洲视频 | 久久精品中文 | 美女黄频网站 | 成年人免费在线播放 | 亚洲欧洲日韩在线观看 | 亚洲国产精品久久久 | 中文字幕久久精品亚洲乱码 | 麻豆精品视频在线观看免费 | 亚洲国产理论片 | 日韩免费b | 欧洲精品在线视频 | 一区二区精品国产 | 手机在线日韩视频 | 日韩二区在线播放 | 婷婷性综合 | 夜夜操夜夜干 | av高清一区二区三区 | 国产资源av | 精品一区二三区 | 中文网丁香综合网 | 国产资源在线观看 | 免费网站观看www在线观看 | 高清av在线 | 亚洲国产日韩在线 | 欧美在线观看小视频 | 日产乱码一二三区别在线 | 91麻豆精品久久久久久 | 91在线一区 | 99久久电影 | 成人国产网址 | 97超碰人人澡人人爱学生 | 国产一区二区午夜 | 色www精品视频在线观看 | 天天操天天射天天舔 | 超级碰99 | 97高清视频 | 99在线高清视频在线播放 | 精品一区二区在线观看 | 精品免费国产一区二区三区四区 | 日韩成人在线免费观看 | 在线亚州 | 亚洲精品观看 | 欧美日韩中文另类 | 粉嫩av一区二区三区四区五区 | 免费网站观看www在线观看 | 国内久久精品视频 | 97精品视频在线 | 日韩色在线观看 | 韩国av一区 | 亚洲高清视频在线观看免费 | 免费国产一区二区视频 | 国产成人一区二区三区免费看 | 成人亚洲网 | 亚洲在线 | 婷婷五综合 | 国产精品久久久久久久久搜平片 | 91亚洲精品久久久中文字幕 | 黄色1级大片 | 久久久高清 | 91欧美精品 | 久久经典视频 | 99在线热播精品免费99热 | 国产精品不卡在线观看 | 极品嫩模被强到高潮呻吟91 | 视频在线在亚洲 | 四虎成人精品在永久免费 | 成片免费观看视频 | 丁香五月缴情综合网 | 久一在线 | 国产精品自产拍在线观看蜜 | 亚洲国产高清在线观看视频 | 欧美粗又大 | 91成品视频 | 91精品在线播放 | 最近2019好看的中文字幕免费 | 九九视频在线观看视频6 | 操操色| 精品在线观看一区二区 | 夜夜操天天 | 欧美在线视频日韩 | 在线导航av| 国色天香第二季 | 麻豆视频国产精品 | 午夜免费在线观看 | 四虎在线影视 | 一区二区三区四区五区在线视频 | 欧美日韩不卡一区 | 国产精品一区二区三区电影 | 超碰在97 | 视频一区二区免费 | 亚洲精品麻豆视频 | 波多在线视频 | 手机版av在线 | 国产日韩视频在线观看 | 国产精品久久中文字幕 | 日韩在线影视 | 日本黄色免费在线 | 99久久精品免费看国产 | 国产一区二区三区在线 | 欧美性久久久久久 | 成人福利在线观看 | 欧美日韩在线观看视频 | 97免费在线观看视频 | 激情欧美xxxx | 成人综合免费 | 很黄很黄的网站免费的 | 成人三级黄色 | 人人澡人人模 | 青青久草在线 | 丁香高清视频在线看看 | 奇米影视8888在线观看大全免费 | 人人插人人爱 | 日日弄天天弄美女bbbb | 超级碰碰碰免费视频 | 高清在线观看av | 丁香花在线视频观看免费 | 91精彩视频在线观看 | 91最新在线观看 | 九月婷婷人人澡人人添人人爽 | 欧美日韩在线播放一区 | 色橹橹欧美在线观看视频高清 | 久久激情综合网 | 97av色| 国产一在线精品一区在线观看 | 国产精久久久久久久 | 麻豆国产视频下载 | 青青河边草免费视频 | 精品国产乱码一区二区三区在线 | 色久综合 | 五月天开心 | 国产精品少妇 | 9在线观看免费高清完整版在线观看明 | 国产一区在线观看免费 | 国产视频网站在线观看 | 操操碰 | 中文网丁香综合网 | 久久久久免费网站 | 久久国产女人 | 色综合咪咪久久网 | 亚洲精品系列 | 婷香五月 | 99热这里只有精品免费 | 天天插视频 | 国产资源在线免费观看 | 精品国产乱子伦一区二区 | 在线小视频你懂的 | 国产精品免费一区二区 | 黄色小说在线免费观看 | 免费看的毛片 | 日韩高清在线一区二区三区 | 亚洲韩国一区二区三区 | 久久久久国产免费免费 | 在线看片成人 | 国产精品麻豆99久久久久久 | 欧美一区在线看 | 国产小视频在线观看免费 | 久久久国产精品一区二区中文 | 久久欧美精品 | 国产一级性生活 | 五月婷婷激情六月 | 日韩电影中文字幕在线 | 三级动态视频在线观看 | 久久久久久久18 | 午夜体验区 | 丁香久久综合 | 国产亲近乱来精品 | 99精品视频免费 | 久久久久久国产一区二区三区 | 日韩中文幕 | 在线中文字幕观看 | 精品国产乱码一区二区三区在线 | 免费国产在线观看 | 亚洲aⅴ在线| 91免费观看视频在线 | 国产午夜三级一区二区三 | 亚洲永久国产精品 | 韩国视频一区二区三区 | 日韩在线观看小视频 | 国产1区在线观看 | 中文字幕91在线 | 97电影在线看视频 | 久草免费电影 | 在线高清一区 | 日日夜夜狠狠干 | 美女中文字幕 | 午夜10000| 伊人五月天.com | 麻豆影视网站 | 激情丁香久久 | 5月丁香婷婷综合 | 夜夜操天天干, | 久久草草影视免费网 | 一区二区三区在线观看免费 | 日韩免费在线视频观看 | 日韩精品一区在线观看 | 毛片一区二区 | 精品视频专区 | 天天爽夜夜爽精品视频婷婷 | 亚洲免费在线 | 黄色小说网站在线 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 国产亚洲精品久久久久久移动网络 | www.91国产 | 日本在线观看一区二区三区 | 麻豆一二三精选视频 | 五月激情电影 | 久久精品国产免费看久久精品 | 欧美五月婷婷 | 亚洲综合欧美日韩狠狠色 | 美女网站一区 | 亚洲成人蜜桃 | 999国产在线 | 成人国产精品入口 | 国产精品亚州 | 999久久国产精品免费观看网站 | 91麻豆免费视频 | 久久精品福利视频 | 国产精品久久久久久久久婷婷 | 久久精品中文字幕少妇 | 亚洲成a人片综合在线 | 福利视频网址 | 国产97视频 | 国产三级av在线 | 97国产在线播放 | 色婷婷激婷婷情综天天 | 999久久精品 | 99视频免费在线观看 | 六月丁香色婷婷 | 成年人电影免费看 | 成人av久久 | 国产原创91 | 久久精品成人欧美大片古装 | 国产一二区免费视频 | 91在线小视频 | 99久久综合国产精品二区 | 国产一区二区三区在线免费观看 | 伊人一级| 亚洲国产日韩欧美 | 粉嫩av一区二区三区四区在线观看 | 婷婷丁香激情综合 | 97超碰人人爱 | 亚洲国产精品99久久久久久久久 | 午夜精品久久久久久久99婷婷 | 51久久成人国产精品麻豆 | 日韩专区在线播放 | 黄av在线| 精品亚洲成a人在线观看 | 91九色在线观看视频 | 精品国产一区二区三区av性色 | 国产69久久久欧美一级 | 亚洲欧洲日韩 | 国产精品久久久久久久久久了 | 亚洲一区二区三区毛片 | 九九九在线观看 | 在线观看视频一区二区三区 | 日韩av一区二区三区四区 | 亚洲少妇激情 | 六月婷婷色| 日b视频在线观看网址 | 一区二区三区在线电影 | 99热9| 国产视频观看 | av在线播放中文字幕 | 日韩精品一区二区三区水蜜桃 | 青青草久草在线 | 99久久久国产精品免费观看 | 黄色中文字幕在线 | 欧美日韩精品在线播放 | 久久男人中文字幕资源站 | 日韩欧美有码在线 | 国产成人综合精品 | 九九亚洲视频 | 久久久九色精品国产一区二区三区 | 久久久久久国产精品美女 | 天天狠狠干 | 久久成年视频 | 国产四虎影院 | 亚洲激情电影在线 | 国产成人久久av | 成人污视频在线观看 | 天天想夜夜操 | 免费黄色网止 | 国产在线传媒 | 久久精品国产免费看久久精品 | 国产精品久久久久久久久久久免费 | 九九热国产视频 | 国产精选视频 | 亚洲欧洲精品视频 | 久久99久国产精品黄毛片入口 | 九九色网| 色偷偷88欧美精品久久久 | 亚洲激情视频在线观看 | 久久精品高清 | 超碰在线日本 | 96久久精品| 婷婷色在线视频 | 国产精品福利一区 | www蜜桃视频| 日韩久久久久久久久久久久 | 成人免费视频免费观看 | 色婷婷狠狠18 | www.777奇米 | 国产+日韩欧美 | 国产在线2020 | 看片网站黄色 | 欧美淫视频 | 免费观看视频的网站 | 国产精品免费麻豆入口 | 天天干,天天射,天天操,天天摸 | 黄色aa久久 | 亚洲黄色在线观看 | 天天操夜夜操国产精品 | 91视频免费看网站 | 中文字幕中文字幕在线中文字幕三区 | 在线综合色| 成人资源在线观看 | 99久久精品国产一区二区成人 | av中文字幕在线观看网站 | 99热亚洲精品 | 91精品国产99久久久久久红楼 | 国产日韩精品在线观看 | 国产片免费在线观看视频 | 日韩免费久久 | 亚洲精品资源在线 | 午夜精品久久久久久 | 国产在线中文 | 中文字幕xxxx| 久久综合偷偷噜噜噜色 | 天天操天天操一操 | 四虎在线观看 | 在线观看成年人 | 天海翼一区二区三区免费 | 国产精品视频久久 | 国产精品99免视看9 国产精品毛片一区视频 | 国产成人精品免费在线观看 | 最新久久免费视频 | 黄网站污 | 亚洲成人高清在线 | 国产美女黄网站免费 | 四虎影视成人精品国库在线观看 | 亚洲欧美视屏 | 国产精品免费久久久久久久久久中文 | 97在线观看免费 | 一区二区三区在线影院 | 久久久久久久久久久福利 | 国产中文字幕在线视频 | 成人黄大片视频在线观看 | av在线免费播放 | 成人黄色片在线播放 | 亚洲精品大全 | 日本视频网 | 国产一级二级视频 | 日韩中文字幕91 | 欧美日韩在线观看一区二区 | 免费69视频| 水蜜桃亚洲一二三四在线 | 麻豆国产露脸在线观看 | 97国产视频 | 亚洲理论视频 | 婷婷激情五月综合 | 天天综合视频在线观看 | 天天躁日日躁狠狠躁 | 91av精品 | 午夜丰满寂寞少妇精品 | 黄色片免费在线 | 久久久久免费精品视频 | 超碰免费在线公开 | 成人精品一区二区三区中文字幕 | 中文字幕 第二区 | 欧美日韩视频观看 | 日韩69av| 久久久久久久综合色一本 | 欧美性生活大片 | 国产一在线精品一区在线观看 | 在线观看免费视频 | 天天拍天天草 | 成人久久久精品国产乱码一区二区 | 国内揄拍国内精品 | 欧美影院久久 | 精品亚洲成人 | 一区二区三区在线免费 | 国产精品久久久久久久久久不蜜月 | 精品综合久久久 | 久久精品99久久 | 欧美精品久久久久a | 91黄色视屏 | 久久黄色免费 | 97国产电影| 亚洲成人av一区 | 色在线视频网 | 最近日韩中文字幕中文 | 久久五月精品 | 在线观看韩国av | 天天操天天色天天射 | 精品综合久久久 | www在线免费观看 | 91桃色在线观看视频 | 国内精品久久久久影院日本资源 | 97成人精品区在线播放 | 日韩精品久久久久久久电影99爱 | 在线日韩视频 | 1区2区视频| 欧美精品亚洲二区 | 久久精品一区八戒影视 | 国产精品久久久久久久久久久免费看 | 国产麻豆精品传媒av国产下载 | 蜜臀久久99精品久久久无需会员 | 91麻豆文化传媒在线观看 | 日本69hd| 国产成人亚洲精品自产在线 | 又色又爽又黄高潮的免费视频 | 麻豆成人在线观看 | 国产乱码精品一区二区三区介绍 | 中文字幕免费 | 亚洲精品欧洲精品 | 亚洲乱码中文字幕综合 | 91在线在线观看 | 国产最新视频在线观看 | 久久久国产精品免费 | 日韩中文字幕亚洲一区二区va在线 | 国产日韩精品一区二区三区在线 | 看片的网址 | 一级黄色大片 | 欧美-第1页-屁屁影院 | a视频在线观看免费 | 粉嫩av一区二区三区四区五区 | av 一区 二区 久久 | 国产精品视频99 | 精品嫩模福利一区二区蜜臀 | 人人插人人澡 | 在线观看一级视频 | 亚洲欧洲国产精品 | 二区三区在线观看 | 日韩欧美视频免费观看 | 综合久久久 | 亚洲色图27p | 成人午夜电影网 | 国产伦理久久精品久久久久_ | 国产在线观看你懂得 | 91av视频| 精品久久久999 | 精品爱爱 | 国产不卡在线看 | 免费亚洲婷婷 | 天堂黄色片| 国产亚洲精品美女久久 | 91av视频免费在线观看 | 日韩首页 | 久av电影 | 91大神dom调教在线观看 | 婷婷色5月 | 国产精品成人一区二区 | 欧美日韩国产精品一区二区 | 国产精品毛片一区视频 | 日韩视频免费观看高清完整版在线 | 欧美成人精品欧美一级乱黄 | 亚洲一级影院 | 久久精品国产亚洲aⅴ | 91视频传媒| 欧美午夜视频在线 | 五月婷婷天堂 | 国产 欧美 日本 | 日日爽天天操 | 99色免费视频 | 国产成人在线免费观看 | 欧美午夜a | 8090yy亚洲精品久久 | 精品国产视频在线观看 | 正在播放五月婷婷狠狠干 | 91免费观看视频在线 | 久久精品国产久精国产 | 日韩精品一卡 | 99精品免费| 91在线看网站 | 亚洲色综合 | 最新的av网站 | 国产九九九精品视频 | 成人在线视频网 | 国产精品乱码久久 | 日本中文字幕在线播放 | 狠狠88综合久久久久综合网 | 精品久久久成人 | 六月婷婷久香在线视频 | 国产精品不卡视频 | 久久久片 | 麻豆免费视频观看 | 在线观看av免费观看 | 丁香婷婷网 | 人人爽人人爽人人爽人人爽 | 国产小视频在线免费观看 | 久久久国产日韩 | 日韩欧美大片免费观看 | 亚洲成av人片在线观看无 | 久草视频免费在线播放 | 国产精品 999 | 九九热只有这里有精品 | 久草在线视频网 | 久久久久国产成人精品亚洲午夜 | 亚洲人成网站精品片在线观看 | 五月婷婷av在线 | 国产精品亚洲a | 久久黄色网 | 五月婷婷视频在线观看 | 波多野结衣亚洲一区二区 | 一区二区 不卡 | 麻豆视频www| 国产aaa毛片| 911亚洲精品第一 | 91热视频| 91自拍成人| av免费网| 99视频| 久久久久久久久久久久av | 国产福利一区二区三区在线观看 | 国产一级片久久 | 99自拍视频在线观看 | 激情视频综合网 | 成人久久精品 | 精品国产一区二区三区在线观看 | www.狠狠操| 国产视频2区 | 国产成人一区二区精品非洲 | 欧美日韩中文在线观看 | 日韩免费高清在线 | 麻豆高清免费国产一区 | 97在线资源| 黄色电影在线免费观看 | 高清有码中文字幕 | 久久人91精品久久久久久不卡 | 日韩精选在线观看 | 在线成人小视频 | 久久久天堂| 国产午夜麻豆影院在线观看 | 欧美资源 | 青青河边草免费视频 | av不卡中文字幕 | 成年人免费看的视频 | 精品国产91亚洲一区二区三区www | 欧美日韩aaaa| 日精品| 久久国产一区 | 五月婷婷婷婷婷 | 91污视频在线 | 亚洲成人av片 | 色久网| 最近中文字幕国语免费av | 丁香婷婷综合网 | 国产999精品久久久久久 | 精品久久久久久综合日本 | 久久久99久久| 色偷偷网站视频 | 日本h视频在线观看 | 91最新中文字幕 | www操操 | 99精品久久只有精品 | 激情深爱| 国产成人精品久久久久蜜臀 | 国产成人99av超碰超爽 | av免费播放| 欧美极品一区二区三区 | 久久久男人的天堂 | 色综合久久网 | 在线观看亚洲免费视频 | 成人综合免费 | 96av在线 | 一区二区精品在线 | 日韩欧美在线一区 | www.99久久.com | 欧美亚洲国产一卡 | 丁香五月网久久综合 | 婷婷精品国产一区二区三区日韩 | 久久精品视频在线 | 国产精品观看在线亚洲人成网 | 亚洲最大免费成人网 | 97网| 日韩欧美国产成人 | 国产精品一区二区免费在线观看 | 久久理伦片| 人人爽人人av| 91福利视频久久久久 | 国产福利小视频在线 | 91黄色免费网站 | 日本中文字幕免费观看 | 成人黄性视频 | 日日夜夜精品视频天天综合网 | 激情综合五月婷婷 | 久久亚洲区 | 国产手机精品视频 | 成人网在线免费视频 | 人人爱夜夜操 | 久在线观看视频 | 在线免费观看涩涩 | 99国产精品久久久久久久久久 | 久久久久国产精品一区二区 | 中文字幕亚洲精品日韩 | 一区二区 久久 | 国产在线国偷精品产拍免费yy | 激情片av| 欧美天天综合 | 亚州精品视频 | 久久久美女 | 91九色国产 | 在线视频久 | 天天综合导航 | 五月婷激情 | 国产99亚洲 | 免费观看91视频大全 | 五月开心激情 | 久久久久亚洲精品国产 | 欧美大片在线看免费观看 | av久久久久久 | 国产免费黄色 | 日韩在线视| 国产精品久久久久一区 | 成人免费视频在线观看 | 99国产精品一区二区 | 久久免费电影网 | 中文av在线播放 | 精品影院一区二区久久久 | 欧美精品一二三 | 欧美精品一区在线 | 成人av一区二区兰花在线播放 | 在线观看国产日韩欧美 | 2018亚洲男人天堂 | 国产视频在线免费观看 | 99久久精品免费看国产一区二区三区 | 亚洲精品动漫成人3d无尽在线 | 婷婷六月在线 | 人人狠狠 | 国产精品国产三级国产aⅴ9色 | 国外调教视频网站 | va视频在线| 中文乱幕日产无线码1区 | 99久久精品国产一区二区三区 | 久久久国产精品电影 | 激情五月在线视频 | 黄色精品视频 | 国产91影院 | 超碰国产97 | 精品久久久久一区二区国产 | 东方av免费在线观看 | 最近2019中文免费高清视频观看www99 | av三级在线播放 | a级国产乱理论片在线观看 特级毛片在线观看 | 久久久久久久久久亚洲精品 | 久久精品国产精品亚洲精品 | 国产h在线播放 | 中文字幕av一区二区三区四区 | 久久久久综合网 | 国产精品免费久久久久影院仙踪林 | 久久精品国产第一区二区三区 | 精品国内自产拍在线观看视频 | 超碰97成人 | 欧美成人精品欧美一级乱 | 黄色av网站在线观看免费 | 亚洲精品自拍 | 免费在线播放黄色 | 91麻豆传媒 | 狠狠干婷婷 | 日韩欧美在线国产 | 黄色av电影一级片 | 国产传媒中文字幕 | 国产1区2 | 91久久偷偷做嫩草影院 | 国产黄色大片免费看 | 天天草综合 | 最新日韩精品 | 亚洲精品在线一区二区三区 | 天天干天天搞天天射 | 亚洲精品毛片一级91精品 | 波多野结衣综合网 | 91视频免费网站 | 国产精品1区 | 久久a国产| 久久久久这里只有精品 | 伊人婷婷在线 | 日韩av成人在线 | 国产精品网红直播 | 免费观看9x视频网站在线观看 | 欧美一级看片 | 成人免费观看网址 | 一级免费观看 | 成年人网站免费观看 | 超碰国产97 | 在线观看视频中文字幕 | 狠狠干电影 | 欧美日韩视频在线一区 | 91麻豆精品久久久久久 | 国产高清在线不卡 | 日韩免费电影网站 | 激情综合色综合久久 | 久久人人爽人人片 | 久久精品专区 | 99久久久国产精品美女 | 欧美激情精品久久久久久免费印度 | 色操插 | 日日爽天天 | 欧美在线视频一区二区三区 | 日韩在线网 | 欧美少妇影院 | 黄av资源| 色网站黄 | 四虎影视国产精品免费久久 | 亚洲国产影院 | 国产亚洲综合精品 | 久久不卡视频 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 亚洲综合色视频 | 国产精品成人一区 | 久久免费精品一区二区三区 | 国产精品乱码久久 | 亚洲视频播放 | 成人91av| 在线观看完整版免费 | 98涩涩国产露脸精品国产网 | 激情网五月 | www最近高清中文国语在线观看 | 五月色婷 | 久久国产精品免费看 | 亚洲精品白浆高清久久久久久 | 免费亚洲精品视频 | 日韩av免费观看网站 | 欧美精品国产综合久久 | 在线播放日韩av | 国内精品久久久久影院日本资源 | 99re国产| 国产黄色大片 | 一本一本久久aa综合精品 | 午夜久久久精品 | 97热视频 | 国产精品久久久久久一区二区三区 | 亚洲aⅴ久久精品 | 五月婷婷综合在线观看 | aaa亚洲精品一二三区 | 国产美女网站在线观看 | 午夜精品久久久久久久99 | 又污又黄网站 | 亚洲第一香蕉视频 | 在线视频电影 | 久久免费视频1 | 91av成人 | 免费高清av在线看 | av日韩av| 国产乱码精品一区二区三区介绍 | 在线观看成人网 | 黄色a一级片 | 国产日韩精品在线 | 国产成人精品免高潮在线观看 | 不卡视频在线看 | 欧美大片大全 | 91精品国产自产在线观看永久 | 毛片美女网站 | 不卡的av在线 | 中文字幕 国产 一区 | 在线看的毛片 | 在线观看91网站 | 国产午夜三级 | 久一在线 | 国产成人a v电影 | 黄色av高清 | 欧美久久电影 | 久久国产综合视频 | 天天干夜夜干 | 国产在线观看二区 | 国精产品999国精产品视频 | 国产视频黄 | av看片在线 | 亚洲成av人片在线观看香蕉 | 久久久久久国产精品亚洲78 | 欧美一区二区在线免费看 | 国产亚洲精品久久久久久 | 欧美 日韩 久久 | 国产精品九九九 | 日韩欧美在线视频一区二区三区 | 在线视频一二三 | 黄色三级网站 | 中文字幕在线视频一区二区三区 | 黄色成人av | 久久草视频 | 97精品在线视频 | 日韩电影中文字幕 | 高清中文字幕 | 国产综合激情 | 亚洲成av人影院 | 国产精品video爽爽爽爽 | 中文字幕日本特黄aa毛片 | www91在线| 久久伊人免费视频 | 亚洲专区一二三 | 国产美腿白丝袜足在线av | 精品伊人久久久 | 国产精品麻豆一区二区三区 | 亚洲精品视频在 | 亚洲激情综合网 | 久久成人高清视频 | 99久高清在线观看视频99精品热在线观看视频 | 91人人澡人人爽人人精品 | av在线播放网址 | 免费又黄又爽 | 超碰在线观看av.com | 国产无套一区二区三区久久 | 天天玩天天干天天操 | 日本在线观看中文字幕 | 久久艹国产视频 | 久久成视频 | 久久综合9988久久爱 | 99久e精品热线免费 99国产精品久久久久久久久久 | 久久国产精品免费一区二区三区 | 日本久久久久久久久久久 | 91精品视频免费 | 在线观看韩国av | 国产偷v国产偷∨精品视频 在线草 | 日韩| 精品在线你懂的 | 福利电影一区二区 | 久久久久久久久久久免费视频 | 天天射,天天干 | 99久久精品国产一区 | japanese黑人亚洲人4k | 中文字幕免费在线看 | 三级av免费 | 毛片一级免费一级 | 在线观看日本韩国电影 | 男女激情免费网站 | 亚洲激情电影在线 | www178ccom视频在线 | 色婷久久 | 91色亚洲| 成人h视频在线 | 麻豆一区在线观看 | 玖草影院| 国际精品久久久 | 国产99久久久国产精品 | 欧美aaa视频| 午夜久久久久久久久久久 | 天天干天天操天天操 | 中文字幕在线观看一区二区三区 | 国产高清视频免费观看 | 天天天天天天天操 | 久草在线最新免费 | 欧美成人播放 | 在线观看成人av | 国产精品亚洲片在线播放 | 久久久高清一区二区三区 | 黄色在线看网站 | 国内少妇自拍视频一区 | 久久国产精品99久久久久 | 国产手机在线视频 | 天天综合网久久综合网 | 成人精品一区二区三区中文字幕 | 色综合www | 免费观看www小视频的软件 | 96亚洲精品久久 | 国产精品免费观看在线 | 夜夜操天天干 | 日韩免费网址 | 久久久亚洲影院 | 国产免费一区二区三区最新 | 久久久久久网址 | 少妇bbr搡bbb搡bbb | 久久字幕网 | 久久草精品 | 色噜噜在线观看 | 欧美激情精品久久久久久变态 | 国产激情小视频在线观看 | 337p日本欧洲亚洲大胆裸体艺术 | 天天综合区 | 狠狠搞,com| 亚洲久草网 | 久久成熟 | 久久国产系列 | 国产精品va在线 | 这里只有精品视频在线观看 | 在线观看一区二区视频 | 久久激情视频免费观看 | 91超碰免费在线 | 永久免费精品视频网站 | 国产精品v欧美精品 | 国内久久看 | 99精品欧美一区二区蜜桃免费 | 伊人久久在线观看 | 成人久久18免费 | 激情视频免费在线观看 | 国产午夜精品一区二区三区嫩草 | 狠狠狠色丁香婷婷综合激情 | 久久久久综合 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 97视频在线免费观看 | 亚洲天堂精品 | 黄色小视频在线观看免费 | 波多野结衣小视频 | 亚洲男男gⅴgay双龙 | 黄色影院在线免费观看 | 久章草在线 | 亚洲国产精品女人久久久 | 韩国av一区二区三区 |