📄 tcp.c
字号:
tcp_kill_timewait(void){ struct tcp_pcb *pcb, *inactive; u32_t inactivity; inactivity = 0; inactive = NULL; for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { inactivity = tcp_ticks - pcb->tmr; inactive = pcb; } } if (inactive != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", (void *)inactive, inactivity)); tcp_abort(inactive); } }struct tcp_pcb *tcp_alloc(u8_t prio){ struct tcp_pcb *pcb; u32_t iss; pcb = memp_malloc(MEMP_TCP_PCB); if (pcb == NULL) { /* Try killing oldest connection in TIME-WAIT. */ LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); tcp_kill_timewait(); pcb = memp_malloc(MEMP_TCP_PCB); if (pcb == NULL) { tcp_kill_prio(prio); pcb = memp_malloc(MEMP_TCP_PCB); } } if (pcb != NULL) { memset(pcb, 0, sizeof(struct tcp_pcb)); pcb->prio = TCP_PRIO_NORMAL; pcb->snd_buf = TCP_SND_BUF; pcb->snd_queuelen = 0; pcb->rcv_wnd = TCP_WND; pcb->tos = 0; pcb->ttl = TCP_TTL; pcb->mss = TCP_MSS; pcb->rto = 3000 / TCP_SLOW_INTERVAL; pcb->sa = 0; pcb->sv = 3000 / TCP_SLOW_INTERVAL; pcb->rtime = 0; pcb->cwnd = 1; iss = tcp_next_iss(); pcb->snd_wl2 = iss; pcb->snd_nxt = iss; pcb->snd_max = iss; pcb->lastack = iss; pcb->snd_lbb = iss; pcb->tmr = tcp_ticks; pcb->polltmr = 0;#if LWIP_CALLBACK_API pcb->recv = tcp_recv_null;#endif /* LWIP_CALLBACK_API */ /* Init KEEPALIVE timer */ pcb->keepalive = TCP_KEEPDEFAULT; pcb->keep_cnt = 0; } return pcb;}/** * Creates a new TCP protocol control block but doesn't place it on * any of the TCP PCB lists. * * @internal: Maybe there should be a idle TCP PCB list where these * PCBs are put on. We can then implement port reservation using * tcp_bind(). Currently, we lack this (BSD socket type of) feature. */struct tcp_pcb *tcp_new(void){ return tcp_alloc(TCP_PRIO_NORMAL);}/* * tcp_arg(): * * Used to specify the argument that should be passed callback * functions. * */ voidtcp_arg(struct tcp_pcb *pcb, void *arg){ pcb->callback_arg = arg;}#if LWIP_CALLBACK_API/** * Used to specify the function that should be called when a TCP * connection receives data. * */ voidtcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)){ pcb->recv = recv;}/** * Used to specify the function that should be called when TCP data * has been successfully delivered to the remote host. * */ voidtcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)){ pcb->sent = sent;}/** * Used to specify the function that should be called when a fatal error * has occured on the connection. * */ voidtcp_err(struct tcp_pcb *pcb, void (* errf)(void *arg, err_t err)){ pcb->errf = errf;}/** * Used for specifying the function that should be called when a * LISTENing connection has been connected to another host. * */ voidtcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)){ ((struct tcp_pcb_listen *)pcb)->accept = accept;}#endif /* LWIP_CALLBACK_API *//** * Used to specify the function that should be called periodically * from TCP. The interval is specified in terms of the TCP coarse * timer interval, which is called twice a second. * */ voidtcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval){#if LWIP_CALLBACK_API pcb->poll = poll;#endif /* LWIP_CALLBACK_API */ pcb->pollinterval = interval;}/** * Purges a TCP PCB. Removes any buffered data and frees the buffer memory. * */voidtcp_pcb_purge(struct tcp_pcb *pcb){ if (pcb->state != CLOSED && pcb->state != TIME_WAIT && pcb->state != LISTEN) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); if (pcb->unsent != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); } if (pcb->unacked != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); }#if TCP_QUEUE_OOSEQ /* LW */ if (pcb->ooseq != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); } tcp_segs_free(pcb->ooseq); pcb->ooseq = NULL;#endif /* TCP_QUEUE_OOSEQ */ tcp_segs_free(pcb->unsent); tcp_segs_free(pcb->unacked); pcb->unacked = pcb->unsent = NULL; }}/** * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. * */voidtcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb){ TCP_RMV(pcblist, pcb); tcp_pcb_purge(pcb); /* if there is an outstanding delayed ACKs, send it */ if (pcb->state != TIME_WAIT && pcb->state != LISTEN && pcb->flags & TF_ACK_DELAY) { pcb->flags |= TF_ACK_NOW; tcp_output(pcb); } pcb->state = CLOSED; LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());}/** * Calculates a new initial sequence number for new connections. * */u32_ttcp_next_iss(void){ iss += tcp_ticks; /* XXX */ return iss;}#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUGvoidtcp_debug_print(struct tcp_hdr *tcphdr){ LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", ntohs(tcphdr->src), ntohs(tcphdr->dest))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", ntohl(tcphdr->seqno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", ntohl(tcphdr->ackno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", TCPH_HDRLEN(tcphdr), TCPH_FLAGS(tcphdr) >> 5 & 1, TCPH_FLAGS(tcphdr) >> 4 & 1, TCPH_FLAGS(tcphdr) >> 3 & 1, TCPH_FLAGS(tcphdr) >> 2 & 1, TCPH_FLAGS(tcphdr) >> 1 & 1, TCPH_FLAGS(tcphdr) & 1, ntohs(tcphdr->wnd))); tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));}voidtcp_debug_print_state(enum tcp_state s){ LWIP_DEBUGF(TCP_DEBUG, ("State: ")); switch (s) { case CLOSED: LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n")); break; case LISTEN: LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n")); break; case SYN_SENT: LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n")); break; case SYN_RCVD: LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n")); break; case ESTABLISHED: LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n")); break; case FIN_WAIT_1: LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n")); break; case FIN_WAIT_2: LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n")); break; case CLOSE_WAIT: LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n")); break; case CLOSING: LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n")); break; case LAST_ACK: LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n")); break; case TIME_WAIT: LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n")); break; }}voidtcp_debug_print_flags(u8_t flags){ if (flags & TCP_FIN) { LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); } if (flags & TCP_SYN) { LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); } if (flags & TCP_RST) { LWIP_DEBUGF(TCP_DEBUG, ("RST ")); } if (flags & TCP_PSH) { LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); } if (flags & TCP_ACK) { LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); } if (flags & TCP_URG) { LWIP_DEBUGF(TCP_DEBUG, ("URG ")); } if (flags & TCP_ECE) { LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); } if (flags & TCP_CWR) { LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); }}voidtcp_debug_print_pcbs(void){ struct tcp_pcb *pcb; LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } }s16_ttcp_pcbs_sane(void){ struct tcp_pcb *pcb; for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); } for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); } return 1;}#endif /* TCP_DEBUG */#endif /* LWIP_TCP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -