标签:
1 /**
2 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
3 * the segment between the PCBs and passes it on to tcp_process(), which implements
4 * the TCP finite state machine. This function is called by the IP layer (in
5 * ip_input()).
6 *
7 * @param p received TCP segment to process (p->payload pointing to the IP header)
8 * @param inp network interface on which this segment was received
9 */
10 void
11 tcp_input(struct pbuf *p, struct netif *inp)
12 {
13 struct tcp_pcb *pcb, *prev;
14 struct tcp_pcb_listen *lpcb;
15 u8_t hdrlen;
16 err_t err;
17
18 PERF_START;
19
20 TCP_STATS_INC(tcp.recv);
21 snmp_inc_tcpinsegs();
22
23 iphdr = p->payload; // 得到了IP header
24 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); // 得到了TCP header
25
26 ............
27
28 /* Convert fields in TCP header to host byte order. */
29 tcphdr->src = ntohs(tcphdr->src); // 把tcp header的一些内容从网络字节序转成主机字节序。可以猜测ip header已经在ip层被转过了。
30 tcphdr->dest = ntohs(tcphdr->dest);
31 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
32 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
33 tcphdr->wnd = ntohs(tcphdr->wnd);
34
35 ..................
36
37 //下面出现了3个pcb链表,分别是tcp_active_pcbs、tcp_tw_pcbs和tcp_listen_pcbs。
38 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
39 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
40 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
41 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
42 if (pcb->remote_port == tcphdr->src &&
43 pcb->local_port == tcphdr->dest &&
44 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
45 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
46
47 /* Move this PCB to the front of the list so that subsequent
48 lookups will be faster (we exploit locality in TCP segment
49 arrivals). */
50 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
51 if (prev != NULL) {
52 prev->next = pcb->next;
53 pcb->next = tcp_active_pcbs;
54 tcp_active_pcbs = pcb;
55 }
56 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
57 break;
58 }
59 prev = pcb;
60 }
61
62 if (pcb == NULL) {
63 /* If it did not go to an active connection, we check the connections
64 in the TIME-WAIT state. */
65 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
66 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
67 if (pcb->remote_port == tcphdr->src &&
68 pcb->local_port == tcphdr->dest &&
69 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
70 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
71 /* We don‘t really care enough to move this PCB to the front
72 of the list since we are not very likely to receive that
73 many segments for connections in TIME-WAIT. */
74 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
75 tcp_timewait_input(pcb);
76 pbuf_free(p);
77 return;
78 }
79 }
80
81 //我们暂时只关心tcp_listen_pcbs这个链表。这个链表包含了所有处在listen状态的pcb。一个listen状态的pcb是什么时候把自己注册进tcp_listen_pcbs这个链表的?这个待会讲到。
82 /* Finally, if we still did not get a match, we check all PCBs that
83 are LISTENing for incoming connections. */
84 prev = NULL;
85 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
86 if ((ip_addr_isany(&(lpcb->local_ip)) || // 如果pcb->local_ip是0或者NULL,意味着接收任何ip的连接请求
87 ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) && // 或者pcb->local_ip和接收到的tcp segment的ip地址一致,并且pcb->local_port和接收到的tcp segment的port号也一致,认为找到了之前注册的、并且是remote client发过来的这个tcp segment的目标的pcb。
88 lpcb->local_port == tcphdr->dest) {
89 /* Move this PCB to the front of the list so that subsequent
90 lookups will be faster (we exploit locality in TCP segment
91 arrivals). */
92 if (prev != NULL) {
93 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
94 /* our successor is the remainder of the listening list */
95 lpcb->next = tcp_listen_pcbs.listen_pcbs;
96 /* put this listening pcb at the head of the listening list */
97 tcp_listen_pcbs.listen_pcbs = lpcb;
98 }
99
100 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
101 tcp_listen_input(lpcb); // 得到server正在listen状态的pcb后,用刚收到的remote tcp segment更新pcb,马上会分析这个函数
102 pbuf_free(p);
103 return;
104 }
105 prev = (struct tcp_pcb *)lpcb;
106 }
107 }
1 /**
2 * Called by tcp_input() when a segment arrives for a listening
3 * connection (from tcp_input()).
4 *
5 * @param pcb the tcp_pcb_listen for which a segment arrived
6 * @return ERR_OK if the segment was processed
7 * another err_t on error
8 *
9 * @note the return value is not (yet?) used in tcp_input()
10 * @note the segment which arrived is saved in global variables, therefore only the pcb
11 * involved is passed as a parameter to this function
12 */
13 static err_t
14 tcp_listen_input(struct tcp_pcb_listen *pcb)
15 {
16 struct tcp_pcb *npcb;
17 err_t rc;
18
19 /* In the LISTEN state, we check for incoming SYN segments,
20 creates a new PCB, and responds with a SYN|ACK. */
21 if (flags & TCP_ACK) {
22 /* For incoming segments with the ACK flag set, respond with a
23 RST. */
24 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
25 tcp_rst(ackno + 1, seqno + tcplen,
26 &(iphdr->dest), &(iphdr->src),
27 tcphdr->dest, tcphdr->src);
28 } else if (flags & TCP_SYN) {
29 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
30 #if TCP_LISTEN_BACKLOG
31 if (pcb->accepts_pending >= pcb->backlog) {
32 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
33 return ERR_ABRT;
34 }
35 #endif /* TCP_LISTEN_BACKLOG */
36 npcb = tcp_alloc(pcb->prio); // allocate一个新的pcb,待会会放入active pcb链表
37 /* If a new PCB could not be created (probably due to lack of memory),
38 we don‘t do anything, but rely on the sender will retransmit the
39 SYN at a time when we have more memory available. */
40 if (npcb == NULL) {
41 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
42 TCP_STATS_INC(tcp.memerr);
43 return ERR_MEM;
44 }
45 #if TCP_LISTEN_BACKLOG
46 pcb->accepts_pending++;
47 #endif /* TCP_LISTEN_BACKLOG */
48 /* Set up the new PCB. */
49 ip_addr_set(&(npcb->local_ip), &(iphdr->dest)); // pcb里存好server端自己的ip
50 npcb->local_port = pcb->local_port; // pcb里存好server端自己的port号
51 ip_addr_set(&(npcb->remote_ip), &(iphdr->src)); // pcb里指定client端的ip
52 npcb->remote_port = tcphdr->src; // pcb里指定client端的port号
53 npcb->state = SYN_RCVD; // pcb的状态变成了SYN_RCVD
54 npcb->rcv_nxt = seqno + 1;
55 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
56 npcb->snd_wnd = tcphdr->wnd;
57 npcb->ssthresh = npcb->snd_wnd;
58 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
59 npcb->callback_arg = pcb->callback_arg;
60 #if LWIP_CALLBACK_API
61 npcb->accept = pcb->accept;
62 #endif /* LWIP_CALLBACK_API */
63 /* inherit socket options */
64 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
65 /* Register the new PCB so that we can begin receiving segments
66 for it. */
67 TCP_REG(&tcp_active_pcbs, npcb); // 把新pcb加入active pcbs链表,以后这个pcb专门为server端与remote ip对应的这个client端之间的通信服务
68
69 /* Parse any options in the SYN. */
70 tcp_parseopt(npcb);
71 #if TCP_CALCULATE_EFF_SEND_MSS
72 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
73 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
74
75 snmp_inc_tcppassiveopens();
76
77 /* Send a SYN|ACK together with the MSS option. */
78 rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS // tx一个SYN|ACK
79 #if LWIP_TCP_TIMESTAMPS
80 /* and maybe include the TIMESTAMP option */
81 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
82 #endif
83 );
84 if (rc != ERR_OK) {
85 tcp_abandon(npcb, 0);
86 return rc;
87 }
88 return tcp_output(npcb);
89 }
90 return ERR_OK;
91 }
1 void
2 tcp_input(struct pbuf *p, struct netif *inp)
3 {
4 struct tcp_pcb *pcb, *prev;
5 struct tcp_pcb_listen *lpcb;
6 u8_t hdrlen;
7 err_t err;
8
9 PERF_START;
10
11 TCP_STATS_INC(tcp.recv);
12 snmp_inc_tcpinsegs();
13
14 iphdr = p->payload; // 得到了IP header
15 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); // 得到了TCP header
16
17 ............
18
19 /* Convert fields in TCP header to host byte order. */
20 tcphdr->src = ntohs(tcphdr->src); // 把tcp header的一些内容从网络字节序转成主机字节序。可以猜测ip header已经在ip层被转过了。
21 tcphdr->dest = ntohs(tcphdr->dest);
22 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
23 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
24 tcphdr->wnd = ntohs(tcphdr->wnd);
25
26 ..................
27
28 //下面出现了3个pcb链表,分别是tcp_active_pcbs、tcp_tw_pcbs和tcp_listen_pcbs。
29 // 这一次,tcp segment对应的client-server专属pcb能够在 tcp_active_pcbs链表里找到。
30 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
31 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
32 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
33 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
34 if (pcb->remote_port == tcphdr->src && // 这个tcp segment对应的client和server信息都能和某个pcb一致,则找到了这个pcb
35 pcb->local_port == tcphdr->dest &&
36 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
37 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
38
39 /* Move this PCB to the front of the list so that subsequent
40 lookups will be faster (we exploit locality in TCP segment
41 arrivals). */
42 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
43 if (prev != NULL) {
44 prev->next = pcb->next;
45 pcb->next = tcp_active_pcbs;
46 tcp_active_pcbs = pcb;
47 }
48 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
49 break;
50 }
51 prev = pcb;
52 }
53
54 .............
55
56 if (pcb != NULL) {
57 err = tcp_process(pcb);
58 }
1 static err_t
2 tcp_process(struct tcp_pcb *pcb)
3 {
4 ..............
5 case SYN_RCVD:
6 if (flags & TCP_ACK) {
7 /* expected ACK number? */
8 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
9 u16_t old_cwnd;
10 pcb->state = ESTABLISHED;
11 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
12 #if LWIP_CALLBACK_API
13 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
14 #endif
15 /* Call the accept function. */
16 TCP_EVENT_ACCEPT(pcb, ERR_OK, err); // 这里会调到accept_function函数
17 if (err != ERR_OK) {
18 /* If the accept function returns with an error, we abort
19 * the connection. */
20 tcp_abort(pcb);
21 return ERR_ABRT;
22 }
23 old_cwnd = pcb->cwnd;
24 /* If there was any data contained within this ACK,
25 * we‘d better pass it on to the application as well. */
26 tcp_receive(pcb);
27
28 /* Prevent ACK for SYN to generate a sent event */
29 if (pcb->acked != 0) {
30 pcb->acked--;
31 }
32
33 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
34
35 if (recv_flags & TF_GOT_FIN) {
36 tcp_ack_now(pcb);
37 pcb->state = CLOSE_WAIT;
38 }
39 }
40 /* incorrect ACK number */
41 else {
42 /* send RST */
43 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
44 tcphdr->dest, tcphdr->src);
45 }
46 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
47 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
48 tcp_rexmit(pcb);
49 }
50 break;
51 ....................
52 }
1 /**
2 * Accept callback function for TCP netconns.
3 * Allocates a new netconn and posts that to conn->acceptmbox.
4 *
5 * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
6 */
7 // 注意accept_function的参数是
8 // arg:server端负责listen的那个sock的sock->conn,
9 // newpcb:listen到tcp segment后为特定的client-server创建的pcb
10 // err:err
11 static err_t
12 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
13 {
14 struct netconn *newconn;
15 struct netconn *conn;
16
17 #if API_MSG_DEBUG
18 #if TCP_DEBUG
19 tcp_debug_print_state(newpcb->state);
20 #endif /* TCP_DEBUG */
21 #endif /* API_MSG_DEBUG */
22 conn = (struct netconn *)arg;
23
24 LWIP_ERROR("accept_function: invalid conn->acceptmbox",
25 conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);
26
27 /* We have to set the callback here even though
28 * the new socket is unknown. conn->socket is marked as -1. */
29 newconn = netconn_alloc(conn->type, conn->callback); // 新建一个netconn
30 if (newconn == NULL) {
31 return ERR_MEM;
32 }
33 newconn->pcb.tcp = newpcb;
34 setup_tcp(newconn); // 这个函数很重要,我们要记住它把newconn和newpcb绑定起来了
35 newconn->err = err;
36
37 if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) { // 把newconn丢到了旧conn(即负责listen的pcb的conn)的acceptmbox这个mailbox上
38 /* When returning != ERR_OK, the connection is aborted in tcp_process(),
39 so do nothing here! */
40 newconn->pcb.tcp = NULL;
41 netconn_free(newconn);
42 return ERR_MEM;
43 } else {
44 /* Register event with callback */
45 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
46 }
47
48 return ERR_OK;
49 }
1 /* Below this, the well-known socket functions are implemented.
2 * Use google.com or opengroup.org to get a good description :-)
3 *
4 * Exceptions are documented!
5 */
6
7 int
8 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) // 这里的s是负责listen的socket
9 {
10 struct lwip_socket *sock, *nsock;
11 struct netconn *newconn;
12 struct ip_addr naddr;
13 u16_t port;
14 int newsock;
15 struct sockaddr_in sin;
16 err_t err;
17
18 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
19 sock = get_socket(s); // 从用户可见的int型socket得到协议栈自己维护的socket descriptor
20 if (!sock)
21 return -1;
22
23 if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
24 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
25 sock_set_errno(sock, EWOULDBLOCK);
26 return -1;
27 }
28
29 newconn = netconn_accept(sock->conn); // 传入的是listen socket指向的conn
30 ..................
31 }
1 /**
2 * Accept a new connection on a TCP listening netconn.
3 *
4 * @param conn the TCP listen netconn
5 * @return the newly accepted netconn or NULL on timeout
6 */
7 struct netconn *
8 netconn_accept(struct netconn *conn)
9 {
10 struct netconn *newconn;
11
12 .............
13
14 #if LWIP_SO_RCVTIMEO
15 if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
16 newconn = NULL;
17 } else
18 #else
19 sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0); // 这里从listen socket->conn的acceptmbox取出1个conn,当然就是socket用户在调用listen()后,listen()通过accept_function()函数放入的新conn,这是和listen socket->conn不同的新conn,这里名字是newconn
20 #endif /* LWIP_SO_RCVTIMEO*/
21 ..................
22
23 return newconn;
24 }
1 /* Below this, the well-known socket functions are implemented.
2 * Use google.com or opengroup.org to get a good description :-)
3 *
4 * Exceptions are documented!
5 */
6
7 int
8 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) // 这里的s是负责listen的socket
9 {
10 .................
11 newconn = netconn_accept(sock->conn); // 传入的是listen socket指向的conn
12 if (!newconn) {
13 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
14 sock_set_errno(sock, err_to_errno(sock->conn->err));
15 return -1;
16 }
17
18 /* get the IP address and port of the remote host */
19 err = netconn_peer(newconn, &naddr, &port); // 从newconn里得到client端ip addr和port号,实际是从newconn绑定的pcb里获得
20 if (err != ERR_OK) {
21 netconn_delete(newconn);
22 sock_set_errno(sock, err_to_errno(err));
23 return -1;
24 }
25
26 /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
27 * not be NULL if addr is valid.
28 */
29 if (NULL != addr) { // 如果实参addr地址不是NULL,就把client端的ip地址和port写入addr指向的地址,作为这个函数的返回值之一。但是很多时候这个addr参数用户都会设置为NULL,不需要这个信息。
30 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
31 memset(&sin, 0, sizeof(sin));
32 sin.sin_len = sizeof(sin);
33 sin.sin_family = AF_INET;
34 sin.sin_port = htons(port);
35 sin.sin_addr.s_addr = naddr.addr;
36
37 if (*addrlen > sizeof(sin))
38 *addrlen = sizeof(sin);
39
40 MEMCPY(addr, &sin, *addrlen);
41 }
42
43 newsock = alloc_socket(newconn); // 对于一个client和server的peer,现在有了新的pcb、新的conn,还需要一个新的socket给用户用!并且这个函数还把newconn和socket绑定起来了,从新socket能得到newconn。
44 if (newsock == -1) {
45 netconn_delete(newconn);
46 sock_set_errno(sock, ENFILE);
47 return -1;
48 }
49 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
50 newconn->callback = event_callback;
51 nsock = &sockets[newsock];
52 LWIP_ASSERT("invalid socket pointer", nsock != NULL);
53
54 sys_sem_wait(socksem);
55 /* See event_callback: If data comes in right away after an accept, even
56 * though the server task might not have created a new socket yet.
57 * In that case, newconn->socket is counted down (newconn->socket--),
58 * so nsock->rcvevent is >= 1 here!
59 */
60 nsock->rcvevent += -1 - newconn->socket;
61 newconn->socket = newsock; // 从newconn能找到new socket
62 sys_sem_signal(socksem);
63
64 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
65 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
66 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
67
68 sock_set_errno(sock, 0);
69 return newsock;
70 }
标签:
原文地址:http://www.cnblogs.com/codingfun/p/4184187.html