117#ifdef LWIP_HOOK_FILENAME
118#include LWIP_HOOK_FILENAME
121#ifndef TCP_LOCAL_PORT_RANGE_START
124#define TCP_LOCAL_PORT_RANGE_START 0xc000
125#define TCP_LOCAL_PORT_RANGE_END 0xffff
126#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & (u16_t)~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START))
129#if LWIP_TCP_KEEPALIVE
130#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl)
131#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl)
133#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE
134#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT
139#define INITIAL_MSS 536
141#define INITIAL_MSS TCP_MSS
144static const char *
const tcp_state_str[] = {
159static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START;
163static const u8_t tcp_backoff[13] =
164{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
166static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
171struct tcp_pcb *tcp_bound_pcbs;
173union tcp_listen_pcbs_t tcp_listen_pcbs;
176struct tcp_pcb *tcp_active_pcbs;
178struct tcp_pcb *tcp_tw_pcbs;
181struct tcp_pcb **
const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
182 &tcp_active_pcbs, &tcp_tw_pcbs
185u8_t tcp_active_pcbs_changed;
188static u8_t tcp_timer;
189static u8_t tcp_timer_ctr;
190static u16_t tcp_new_port(
void);
192static err_t tcp_close_shutdown_fin(
struct tcp_pcb *pcb);
193#if LWIP_TCP_PCB_NUM_EXT_ARGS
194static void tcp_ext_arg_invoke_callbacks_destroyed(
struct tcp_pcb_ext_args *ext_args);
204 tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
210tcp_free(
struct tcp_pcb *pcb)
212 LWIP_ASSERT(
"tcp_free: LISTEN", pcb->state != LISTEN);
213#if LWIP_TCP_PCB_NUM_EXT_ARGS
214 tcp_ext_arg_invoke_callbacks_destroyed(pcb->ext_args);
221tcp_free_listen(
struct tcp_pcb *pcb)
223 LWIP_ASSERT(
"tcp_free_listen: !LISTEN", pcb->state != LISTEN);
224#if LWIP_TCP_PCB_NUM_EXT_ARGS
225 tcp_ext_arg_invoke_callbacks_destroyed(pcb->ext_args);
239 if (++tcp_timer & 1) {
246#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
251tcp_remove_listener(
struct tcp_pcb *list,
struct tcp_pcb_listen *lpcb)
255 LWIP_ASSERT(
"tcp_remove_listener: invalid listener", lpcb != NULL);
257 for (pcb = list; pcb != NULL; pcb = pcb->next) {
258 if (pcb->listener == lpcb) {
259 pcb->listener = NULL;
269tcp_listen_closed(
struct tcp_pcb *pcb)
271#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
273 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
274 LWIP_ASSERT(
"pcb->state == LISTEN", pcb->state == LISTEN);
275 for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
276 tcp_remove_listener(*tcp_pcb_lists[i], (
struct tcp_pcb_listen *)pcb);
282#if TCP_LISTEN_BACKLOG
294tcp_backlog_delayed(
struct tcp_pcb *pcb)
296 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
298 if ((pcb->flags & TF_BACKLOGPEND) == 0) {
299 if (pcb->listener != NULL) {
300 pcb->listener->accepts_pending++;
301 LWIP_ASSERT(
"accepts_pending != 0", pcb->listener->accepts_pending != 0);
302 tcp_set_flags(pcb, TF_BACKLOGPEND);
317tcp_backlog_accepted(
struct tcp_pcb *pcb)
319 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
321 if ((pcb->flags & TF_BACKLOGPEND) != 0) {
322 if (pcb->listener != NULL) {
323 LWIP_ASSERT(
"accepts_pending != 0", pcb->listener->accepts_pending != 0);
324 pcb->listener->accepts_pending--;
325 tcp_clear_flags(pcb, TF_BACKLOGPEND);
348tcp_close_shutdown(
struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
350 LWIP_ASSERT(
"tcp_close_shutdown: invalid pcb", pcb != NULL);
352 if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
353 if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) {
356 LWIP_ASSERT(
"pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED);
360 tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
361 pcb->local_port, pcb->remote_port);
366 if (tcp_input_pcb == pcb) {
368 tcp_trigger_input_pcb_close();
378 switch (pcb->state) {
387 if (pcb->local_port != 0) {
388 TCP_RMV(&tcp_bound_pcbs, pcb);
393 tcp_listen_closed(pcb);
394 tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
395 tcp_free_listen(pcb);
398 TCP_PCB_REMOVE_ACTIVE(pcb);
400 MIB2_STATS_INC(mib2.tcpattemptfails);
403 return tcp_close_shutdown_fin(pcb);
409tcp_close_shutdown_fin(
struct tcp_pcb *pcb)
412 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
414 switch (pcb->state) {
416 err = tcp_send_fin(pcb);
418 tcp_backlog_accepted(pcb);
419 MIB2_STATS_INC(mib2.tcpattemptfails);
420 pcb->state = FIN_WAIT_1;
424 err = tcp_send_fin(pcb);
426 MIB2_STATS_INC(mib2.tcpestabresets);
427 pcb->state = FIN_WAIT_1;
431 err = tcp_send_fin(pcb);
433 MIB2_STATS_INC(mib2.tcpestabresets);
434 pcb->state = LAST_ACK;
451 tcp_set_flags(pcb, TF_CLOSEPEND);
484tcp_close(
struct tcp_pcb *pcb)
488 LWIP_ERROR(
"tcp_close: invalid pcb", pcb != NULL,
return ERR_ARG);
489 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_close: closing in "));
491 tcp_debug_print_state(pcb->state);
493 if (pcb->state != LISTEN) {
495 tcp_set_flags(pcb, TF_RXCLOSED);
498 return tcp_close_shutdown(pcb, 1);
515tcp_shutdown(
struct tcp_pcb *pcb,
int shut_rx,
int shut_tx)
519 LWIP_ERROR(
"tcp_shutdown: invalid pcb", pcb != NULL,
return ERR_ARG);
521 if (pcb->state == LISTEN) {
526 tcp_set_flags(pcb, TF_RXCLOSED);
529 return tcp_close_shutdown(pcb, 1);
532 if (pcb->refused_data != NULL) {
534 pcb->refused_data = NULL;
540 switch (pcb->state) {
544 return tcp_close_shutdown(pcb, (u8_t)shut_rx);
563tcp_abandon(
struct tcp_pcb *pcb,
int reset)
573 LWIP_ERROR(
"tcp_abandon: invalid pcb", pcb != NULL,
return);
576 LWIP_ASSERT(
"don't call tcp_abort/tcp_abandon for listen-pcbs",
577 pcb->state != LISTEN);
581 if (pcb->state == TIME_WAIT) {
582 tcp_pcb_remove(&tcp_tw_pcbs, pcb);
586 u16_t local_port = 0;
587 enum tcp_state last_state;
588 seqno = pcb->snd_nxt;
589 ackno = pcb->rcv_nxt;
593 errf_arg = pcb->callback_arg;
594 if (pcb->state == CLOSED) {
595 if (pcb->local_port != 0) {
597 TCP_RMV(&tcp_bound_pcbs, pcb);
601 local_port = pcb->local_port;
602 TCP_PCB_REMOVE_ACTIVE(pcb);
604 if (pcb->unacked != NULL) {
605 tcp_segs_free(pcb->unacked);
607 if (pcb->unsent != NULL) {
608 tcp_segs_free(pcb->unsent);
611 if (pcb->ooseq != NULL) {
612 tcp_segs_free(pcb->ooseq);
615 tcp_backlog_accepted(pcb);
618 tcp_rst(pcb, seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
620 last_state = pcb->state;
622 TCP_EVENT_ERR(last_state, errf, errf_arg,
ERR_ABRT);
638tcp_abort(
struct tcp_pcb *pcb)
662tcp_bind(
struct tcp_pcb *pcb,
const ip_addr_t *ipaddr, u16_t port)
665 int max_pcb_list = NUM_TCP_PCB_LISTS;
666 struct tcp_pcb *cpcb;
667#if LWIP_IPV6 && LWIP_IPV6_SCOPES
668 ip_addr_t zoned_ipaddr;
675 if (ipaddr == NULL) {
679 LWIP_ERROR(
"tcp_bind: invalid ipaddr", ipaddr != NULL,
return ERR_ARG);
682 LWIP_ERROR(
"tcp_bind: invalid pcb", pcb != NULL,
return ERR_ARG);
684 LWIP_ERROR(
"tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED,
return ERR_VAL);
693 max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
697#if LWIP_IPV6 && LWIP_IPV6_SCOPES
702 if (IP_IS_V6(ipaddr) && ip6_addr_lacks_zone(ip_2_ip6(ipaddr), IP6_UNICAST)) {
703 ip_addr_copy(zoned_ipaddr, *ipaddr);
704 ip6_addr_select_zone(ip_2_ip6(&zoned_ipaddr), ip_2_ip6(&zoned_ipaddr));
705 ipaddr = &zoned_ipaddr;
710 port = tcp_new_port();
716 for (i = 0; i < max_pcb_list; i++) {
717 for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
718 if (cpcb->local_port == port) {
728 if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) &&
729 (ip_addr_isany(&cpcb->local_ip) ||
730 ip_addr_isany(ipaddr) ||
731 ip_addr_eq(&cpcb->local_ip, ipaddr))) {
740 if (!ip_addr_isany(ipaddr)
741#
if LWIP_IPV4 && LWIP_IPV6
742 || (IP_GET_TYPE(ipaddr) != IP_GET_TYPE(&pcb->local_ip))
745 ip_addr_set(&pcb->local_ip, ipaddr);
747 pcb->local_port = port;
748 TCP_REG(&tcp_bound_pcbs, pcb);
749 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_bind: bind to port %"U16_F
"\n", port));
764tcp_bind_netif(
struct tcp_pcb *pcb,
const struct netif *
netif)
768 pcb->netif_idx = netif_get_index(
netif);
770 pcb->netif_idx = NETIF_NO_INDEX;
779tcp_accept_null(
void *arg,
struct tcp_pcb *pcb, err_t err)
784 LWIP_ASSERT(
"tcp_accept_null: invalid pcb", pcb != NULL);
826tcp_listen_with_backlog(
struct tcp_pcb *pcb, u8_t backlog)
829 return tcp_listen_with_backlog_and_err(pcb, backlog, NULL);
849tcp_listen_with_backlog_and_err(
struct tcp_pcb *pcb, u8_t backlog, err_t *err)
851 struct tcp_pcb_listen *lpcb = NULL;
858 LWIP_ERROR(
"tcp_listen_with_backlog_and_err: invalid pcb", pcb != NULL, res =
ERR_ARG;
goto done);
859 LWIP_ERROR(
"tcp_listen_with_backlog_and_err: pcb already connected", pcb->state == CLOSED, res =
ERR_CLSD;
goto done);
862 if (pcb->state == LISTEN) {
863 lpcb = (
struct tcp_pcb_listen *)pcb;
872 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
873 if ((lpcb->local_port == pcb->local_port) &&
874 ip_addr_eq(&lpcb->local_ip, &pcb->local_ip)) {
883 lpcb = (
struct tcp_pcb_listen *)
memp_malloc(MEMP_TCP_PCB_LISTEN);
888 lpcb->callback_arg = pcb->callback_arg;
889 lpcb->local_port = pcb->local_port;
890 lpcb->state = LISTEN;
891 lpcb->prio = pcb->prio;
892 lpcb->so_options = pcb->so_options;
893 lpcb->netif_idx = pcb->netif_idx;
894 lpcb->ttl = pcb->ttl;
895 lpcb->tos = pcb->tos;
897 lpcb->netif_hints.tci = pcb->netif_hints.tci;
899#if LWIP_IPV4 && LWIP_IPV6
900 IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type);
902 ip_addr_copy(lpcb->local_ip, pcb->local_ip);
903 if (pcb->local_port != 0) {
904 TCP_RMV(&tcp_bound_pcbs, pcb);
906#if LWIP_TCP_PCB_NUM_EXT_ARGS
908 memcpy(&lpcb->ext_args, &pcb->ext_args,
sizeof(pcb->ext_args));
912 lpcb->accept = tcp_accept_null;
914#if TCP_LISTEN_BACKLOG
915 lpcb->accepts_pending = 0;
916 tcp_backlog_set(lpcb, backlog);
918 TCP_REG(&tcp_listen_pcbs.pcbs, (
struct tcp_pcb *)lpcb);
924 return (
struct tcp_pcb *)lpcb;
934tcp_update_rcv_ann_wnd(
struct tcp_pcb *pcb)
936 u32_t new_right_edge;
938 LWIP_ASSERT(
"tcp_update_rcv_ann_wnd: invalid pcb", pcb != NULL);
939 new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
941 if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) {
943 pcb->rcv_ann_wnd = pcb->rcv_wnd;
944 return new_right_edge - pcb->rcv_ann_right_edge;
946 if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) {
949 pcb->rcv_ann_wnd = 0;
952 u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
954 LWIP_ASSERT(
"new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff);
956 pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd;
972tcp_recved(
struct tcp_pcb *pcb, u16_t len)
975 tcpwnd_size_t rcv_wnd;
979 LWIP_ERROR(
"tcp_recved: invalid pcb", pcb != NULL,
return);
982 LWIP_ASSERT(
"don't call tcp_recved for listen-pcbs",
983 pcb->state != LISTEN);
985 rcv_wnd = (tcpwnd_size_t)(pcb->rcv_wnd + len);
986 if ((rcv_wnd > TCP_WND_MAX(pcb)) || (rcv_wnd < pcb->rcv_wnd)) {
988 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_recved: window got too big or tcpwnd_size_t overflow\n"));
989 pcb->rcv_wnd = TCP_WND_MAX(pcb);
991 pcb->rcv_wnd = rcv_wnd;
994 wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
1005 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_recved: received %"U16_F
" bytes, wnd %"TCPWNDSIZE_F
" (%"TCPWNDSIZE_F
").\n",
1006 len, pcb->rcv_wnd, (u16_t)(TCP_WND_MAX(pcb) - pcb->rcv_wnd)));
1019 struct tcp_pcb *pcb;
1023 if (tcp_port == TCP_LOCAL_PORT_RANGE_END) {
1024 tcp_port = TCP_LOCAL_PORT_RANGE_START;
1027 for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
1028 for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
1029 if (pcb->local_port == tcp_port) {
1031 if (n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) {
1071tcp_connect(
struct tcp_pcb *pcb,
const ip_addr_t *ipaddr, u16_t port,
1072 tcp_connected_fn connected)
1077 u16_t old_local_port;
1081 LWIP_ERROR(
"tcp_connect: invalid pcb", pcb != NULL,
return ERR_ARG);
1082 LWIP_ERROR(
"tcp_connect: invalid ipaddr", ipaddr != NULL,
return ERR_ARG);
1084 LWIP_ERROR(
"tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED,
return ERR_ISCONN);
1086 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_connect to port %"U16_F
"\n", port));
1087 ip_addr_set(&pcb->remote_ip, ipaddr);
1088 pcb->remote_port = port;
1090 if (pcb->netif_idx != NETIF_NO_INDEX) {
1094 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1096 if (
netif == NULL) {
1102 if (ip_addr_isany(&pcb->local_ip)) {
1103 const ip_addr_t *local_ip = ip_netif_get_local_ip(
netif, ipaddr);
1104 if (local_ip == NULL) {
1107 ip_addr_copy(pcb->local_ip, *local_ip);
1110#if LWIP_IPV6 && LWIP_IPV6_SCOPES
1113 if (IP_IS_V6(&pcb->remote_ip) &&
1114 ip6_addr_lacks_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNICAST)) {
1115 ip6_addr_assign_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNICAST,
netif);
1119 old_local_port = pcb->local_port;
1120 if (pcb->local_port == 0) {
1121 pcb->local_port = tcp_new_port();
1122 if (pcb->local_port == 0) {
1130 struct tcp_pcb *cpcb;
1133 for (i = 2; i < NUM_TCP_PCB_LISTS; i++) {
1134 for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
1135 if ((cpcb->local_port == pcb->local_port) &&
1136 (cpcb->remote_port == port) &&
1137 ip_addr_eq(&cpcb->local_ip, &pcb->local_ip) &&
1138 ip_addr_eq(&cpcb->remote_ip, ipaddr)) {
1148 iss = tcp_next_iss(pcb);
1151 pcb->lastack = iss - 1;
1152 pcb->snd_wl2 = iss - 1;
1153 pcb->snd_lbb = iss - 1;
1156 pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND);
1157 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
1158 pcb->snd_wnd = TCP_WND;
1161 pcb->mss = INITIAL_MSS;
1162#if TCP_CALCULATE_EFF_SEND_MSS
1163 pcb->mss = tcp_eff_send_mss_netif(pcb->mss,
netif, &pcb->remote_ip);
1166#if LWIP_CALLBACK_API
1167 pcb->connected = connected;
1173 ret = tcp_enqueue_flags(pcb, TCP_SYN);
1176 pcb->state = SYN_SENT;
1177 if (old_local_port != 0) {
1178 TCP_RMV(&tcp_bound_pcbs, pcb);
1180 TCP_REG_ACTIVE(pcb);
1181 MIB2_STATS_INC(mib2.tcpactiveopens);
1198 struct tcp_pcb *pcb, *prev;
1199 tcpwnd_size_t eff_wnd;
1212 pcb = tcp_active_pcbs;
1214 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: no active pcbs\n"));
1216 while (pcb != NULL) {
1217 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: processing active pcb\n"));
1218 LWIP_ASSERT(
"tcp_slowtmr: active pcb->state != CLOSED", pcb->state != CLOSED);
1219 LWIP_ASSERT(
"tcp_slowtmr: active pcb->state != LISTEN", pcb->state != LISTEN);
1220 LWIP_ASSERT(
"tcp_slowtmr: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
1221 if (pcb->last_timer == tcp_timer_ctr) {
1227 pcb->last_timer = tcp_timer_ctr;
1234 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: max SYN retries reached\n"));
1237 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: max DATA retries reached\n"));
1239 if (pcb->persist_backoff > 0) {
1240 LWIP_ASSERT(
"tcp_slowtimr: persist ticking with in-flight data", pcb->unacked == NULL);
1241 LWIP_ASSERT(
"tcp_slowtimr: persist ticking with empty send buffer", pcb->unsent != NULL);
1245 u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff - 1];
1246 if (pcb->persist_cnt < backoff_cnt) {
1249 if (pcb->persist_cnt >= backoff_cnt) {
1252 if (pcb->snd_wnd == 0) {
1253 if (tcp_zero_window_probe(pcb) !=
ERR_OK) {
1258 if (tcp_split_unsent_seg(pcb, (u16_t)pcb->snd_wnd) ==
ERR_OK) {
1259 if (tcp_output(pcb) ==
ERR_OK) {
1266 pcb->persist_cnt = 0;
1267 if (pcb->persist_backoff <
sizeof(tcp_persist_backoff)) {
1268 pcb->persist_backoff++;
1275 if ((pcb->rtime >= 0) && (pcb->rtime < 0x7FFF)) {
1279 if (pcb->rtime >= pcb->rto) {
1282 " pcb->rto %"S16_F
"\n",
1283 pcb->rtime, pcb->rto));
1287 if ((tcp_rexmit_rto_prepare(pcb) ==
ERR_OK) || ((pcb->unacked == NULL) && (pcb->unsent != NULL))) {
1290 if (pcb->state != SYN_SENT) {
1291 u8_t backoff_idx = LWIP_MIN(pcb->nrtx,
sizeof(tcp_backoff) - 1);
1292 int calc_rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx];
1293 pcb->rto = (s16_t)LWIP_MIN(calc_rto, 0x7FFF);
1300 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
1301 pcb->ssthresh = eff_wnd >> 1;
1302 if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) {
1303 pcb->ssthresh = (tcpwnd_size_t)(pcb->mss << 1);
1305 pcb->cwnd = pcb->mss;
1307 " ssthresh %"TCPWNDSIZE_F
"\n",
1308 pcb->cwnd, pcb->ssthresh));
1309 pcb->bytes_acked = 0;
1313 tcp_rexmit_rto_commit(pcb);
1319 if (pcb->state == FIN_WAIT_2) {
1321 if (pcb->flags & TF_RXCLOSED) {
1324 if ((u32_t)(tcp_ticks - pcb->tmr) >
1325 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
1327 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
1334 ((pcb->state == ESTABLISHED) ||
1335 (pcb->state == CLOSE_WAIT))) {
1336 if ((u32_t)(tcp_ticks - pcb->tmr) >
1337 (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) {
1338 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: KEEPALIVE timeout. Aborting connection to "));
1339 ip_addr_debug_print_val(
TCP_DEBUG, pcb->remote_ip);
1344 }
else if ((u32_t)(tcp_ticks - pcb->tmr) >
1345 (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb))
1346 / TCP_SLOW_INTERVAL) {
1347 err = tcp_keepalive(pcb);
1349 pcb->keep_cnt_sent++;
1358 if (pcb->ooseq != NULL &&
1359 (tcp_ticks - pcb->tmr >= (u32_t)pcb->rto * TCP_OOSEQ_TIMEOUT)) {
1360 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_slowtmr: dropping OOSEQ queued data\n"));
1361 tcp_free_ooseq(pcb);
1366 if (pcb->state == SYN_RCVD) {
1367 if ((u32_t)(tcp_ticks - pcb->tmr) >
1368 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
1370 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
1375 if (pcb->state == LAST_ACK) {
1376 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
1378 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
1384 struct tcp_pcb *pcb2;
1385#if LWIP_CALLBACK_API
1386 tcp_err_fn err_fn = pcb->errf;
1389 enum tcp_state last_state;
1393 LWIP_ASSERT(
"tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
1394 prev->next = pcb->next;
1397 LWIP_ASSERT(
"tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
1398 tcp_active_pcbs = pcb->next;
1402 tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
1403 pcb->local_port, pcb->remote_port);
1406 err_arg = pcb->callback_arg;
1407 last_state = pcb->state;
1412 tcp_active_pcbs_changed = 0;
1413 TCP_EVENT_ERR(last_state, err_fn, err_arg,
ERR_ABRT);
1414 if (tcp_active_pcbs_changed) {
1415 goto tcp_slowtmr_start;
1424 if (prev->polltmr >= prev->pollinterval) {
1426 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_slowtmr: polling application\n"));
1427 tcp_active_pcbs_changed = 0;
1428 TCP_EVENT_POLL(prev, err);
1429 if (tcp_active_pcbs_changed) {
1430 goto tcp_slowtmr_start;
1444 while (pcb != NULL) {
1445 LWIP_ASSERT(
"tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
1449 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
1455 struct tcp_pcb *pcb2;
1459 LWIP_ASSERT(
"tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
1460 prev->next = pcb->next;
1463 LWIP_ASSERT(
"tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
1464 tcp_tw_pcbs = pcb->next;
1485 struct tcp_pcb *pcb;
1490 pcb = tcp_active_pcbs;
1492 while (pcb != NULL) {
1493 if (pcb->last_timer != tcp_timer_ctr) {
1494 struct tcp_pcb *next;
1495 pcb->last_timer = tcp_timer_ctr;
1497 if (pcb->flags & TF_ACK_DELAY) {
1498 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_fasttmr: delayed ACK\n"));
1501 tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
1504 if (pcb->flags & TF_CLOSEPEND) {
1505 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_fasttmr: pending FIN\n"));
1506 tcp_clear_flags(pcb, TF_CLOSEPEND);
1507 tcp_close_shutdown_fin(pcb);
1513 if (pcb->refused_data != NULL) {
1514 tcp_active_pcbs_changed = 0;
1515 tcp_process_refused_data(pcb);
1516 if (tcp_active_pcbs_changed) {
1518 goto tcp_fasttmr_start;
1532 struct tcp_pcb *pcb;
1534 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
1535 if (pcb->flags & TF_NAGLEMEMERR) {
1543tcp_process_refused_data(
struct tcp_pcb *pcb)
1545#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1549 LWIP_ERROR(
"tcp_process_refused_data: invalid pcb", pcb != NULL,
return ERR_ARG);
1551#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1552 while (pcb->refused_data != NULL)
1556 u8_t refused_flags = pcb->refused_data->flags;
1559 struct pbuf *refused_data = pcb->refused_data;
1560#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1561 pbuf_split_64k(refused_data, &rest);
1562 pcb->refused_data = rest;
1564 pcb->refused_data = NULL;
1568 TCP_EVENT_RECV(pcb, refused_data,
ERR_OK, err);
1578 if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) {
1581 TCP_EVENT_CLOSED(pcb, err);
1590 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: drop incoming packets, because pcb is \"full\"\n"));
1594#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1599 pcb->refused_data = refused_data;
1612tcp_segs_free(
struct tcp_seg *seg)
1614 while (seg != NULL) {
1615 struct tcp_seg *next = seg->next;
1627tcp_seg_free(
struct tcp_seg *seg)
1630 if (seg->p != NULL) {
1648tcp_setprio(
struct tcp_pcb *pcb, u8_t prio)
1652 LWIP_ERROR(
"tcp_setprio: invalid pcb", pcb != NULL,
return);
1666tcp_seg_copy(
struct tcp_seg *seg)
1668 struct tcp_seg *cseg;
1670 LWIP_ASSERT(
"tcp_seg_copy: invalid seg", seg != NULL);
1672 cseg = (
struct tcp_seg *)
memp_malloc(MEMP_TCP_SEG);
1676 SMEMCPY((u8_t *)cseg, (
const u8_t *)seg,
sizeof(
struct tcp_seg));
1682#if LWIP_CALLBACK_API
1688tcp_recv_null(
void *arg,
struct tcp_pcb *pcb,
struct pbuf *p, err_t err)
1692 LWIP_ERROR(
"tcp_recv_null: invalid pcb", pcb != NULL,
return ERR_ARG);
1695 tcp_recved(pcb, p->tot_len);
1697 }
else if (err ==
ERR_OK) {
1698 return tcp_close(pcb);
1710tcp_kill_prio(u8_t prio)
1712 struct tcp_pcb *pcb, *inactive;
1716 mprio = LWIP_MIN(TCP_PRIO_MAX, prio);
1734 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
1736 if ((pcb->prio < mprio) ||
1738 ((pcb->prio == mprio) && ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity))) {
1739 inactivity = tcp_ticks - pcb->tmr;
1744 if (inactive != NULL) {
1745 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_kill_prio: killing oldest PCB %p (%"S32_F
")\n",
1746 (
void *)inactive, inactivity));
1747 tcp_abort(inactive);
1756tcp_kill_state(
enum tcp_state state)
1758 struct tcp_pcb *pcb, *inactive;
1761 LWIP_ASSERT(
"invalid state", (state == CLOSING) || (state == LAST_ACK));
1767 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
1768 if (pcb->state == state) {
1769 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
1770 inactivity = tcp_ticks - pcb->tmr;
1775 if (inactive != NULL) {
1776 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_kill_closing: killing oldest %s PCB %p (%"S32_F
")\n",
1777 tcp_state_str[state], (
void *)inactive, inactivity));
1779 tcp_abandon(inactive, 0);
1788tcp_kill_timewait(
void)
1790 struct tcp_pcb *pcb, *inactive;
1796 for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
1797 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
1798 inactivity = tcp_ticks - pcb->tmr;
1802 if (inactive != NULL) {
1803 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F
")\n",
1804 (
void *)inactive, inactivity));
1805 tcp_abort(inactive);
1815tcp_handle_closepend(
void)
1817 struct tcp_pcb *pcb = tcp_active_pcbs;
1819 while (pcb != NULL) {
1820 struct tcp_pcb *next = pcb->next;
1822 if (pcb->flags & TF_CLOSEPEND) {
1823 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_handle_closepend: pending FIN\n"));
1824 tcp_clear_flags(pcb, TF_CLOSEPEND);
1825 tcp_close_shutdown_fin(pcb);
1840 struct tcp_pcb *pcb;
1844 pcb = (
struct tcp_pcb *)
memp_malloc(MEMP_TCP_PCB);
1847 tcp_handle_closepend();
1850 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_alloc: killing off oldest TIME-WAIT connection\n"));
1851 tcp_kill_timewait();
1853 pcb = (
struct tcp_pcb *)
memp_malloc(MEMP_TCP_PCB);
1856 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_alloc: killing off oldest LAST-ACK connection\n"));
1857 tcp_kill_state(LAST_ACK);
1859 pcb = (
struct tcp_pcb *)
memp_malloc(MEMP_TCP_PCB);
1862 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_alloc: killing off oldest CLOSING connection\n"));
1863 tcp_kill_state(CLOSING);
1865 pcb = (
struct tcp_pcb *)
memp_malloc(MEMP_TCP_PCB);
1868 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_alloc: killing oldest connection with prio lower than %d\n", prio));
1869 tcp_kill_prio(prio);
1871 pcb = (
struct tcp_pcb *)
memp_malloc(MEMP_TCP_PCB);
1874 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
1879 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
1884 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
1889 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
1894 memset(pcb, 0,
sizeof(
struct tcp_pcb));
1896 pcb->snd_buf = TCP_SND_BUF;
1899 pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND);
1903 pcb->mss = INITIAL_MSS;
1910 pcb->tmr = tcp_ticks;
1911 pcb->last_timer = tcp_timer_ctr;
1919 pcb->ssthresh = TCP_SND_BUF;
1921#if LWIP_CALLBACK_API
1922 pcb->recv = tcp_recv_null;
1926 pcb->keep_idle = TCP_KEEPIDLE_DEFAULT;
1928#if LWIP_TCP_KEEPALIVE
1929 pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
1930 pcb->keep_cnt = TCP_KEEPCNT_DEFAULT;
1955 return tcp_alloc(TCP_PRIO_NORMAL);
1971tcp_new_ip_type(u8_t type)
1973 struct tcp_pcb *pcb;
1974 pcb = tcp_alloc(TCP_PRIO_NORMAL);
1975#if LWIP_IPV4 && LWIP_IPV6
1977 IP_SET_TYPE_VAL(pcb->local_ip, type);
1978 IP_SET_TYPE_VAL(pcb->remote_ip, type);
1997tcp_arg(
struct tcp_pcb *pcb,
void *arg)
2003 pcb->callback_arg = arg;
2006#if LWIP_CALLBACK_API
2020tcp_recv(
struct tcp_pcb *pcb, tcp_recv_fn recv)
2024 LWIP_ASSERT(
"invalid socket state for recv callback", pcb->state != LISTEN);
2040tcp_sent(
struct tcp_pcb *pcb, tcp_sent_fn sent)
2044 LWIP_ASSERT(
"invalid socket state for sent callback", pcb->state != LISTEN);
2066tcp_err(
struct tcp_pcb *pcb, tcp_err_fn err)
2070 LWIP_ASSERT(
"invalid socket state for err callback", pcb->state != LISTEN);
2086tcp_accept(
struct tcp_pcb *pcb, tcp_accept_fn accept)
2089 if ((pcb != NULL) && (pcb->state == LISTEN)) {
2090 struct tcp_pcb_listen *lpcb = (
struct tcp_pcb_listen *)pcb;
2091 lpcb->accept = accept;
2115tcp_poll(
struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)
2119 LWIP_ERROR(
"tcp_poll: invalid pcb", pcb != NULL,
return);
2120 LWIP_ASSERT(
"invalid socket state for poll", pcb->state != LISTEN);
2122#if LWIP_CALLBACK_API
2127 pcb->pollinterval = interval;
2137tcp_pcb_purge(
struct tcp_pcb *pcb)
2139 LWIP_ERROR(
"tcp_pcb_purge: invalid pcb", pcb != NULL,
return);
2141 if (pcb->state != CLOSED &&
2142 pcb->state != TIME_WAIT &&
2143 pcb->state != LISTEN) {
2145 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_pcb_purge\n"));
2147 tcp_backlog_accepted(pcb);
2149 if (pcb->refused_data != NULL) {
2150 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_pcb_purge: data left on ->refused_data\n"));
2152 pcb->refused_data = NULL;
2154 if (pcb->unsent != NULL) {
2155 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_pcb_purge: not all data sent\n"));
2157 if (pcb->unacked != NULL) {
2158 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_pcb_purge: data left on ->unacked\n"));
2161 if (pcb->ooseq != NULL) {
2162 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_pcb_purge: data left on ->ooseq\n"));
2163 tcp_free_ooseq(pcb);
2171 tcp_segs_free(pcb->unsent);
2172 tcp_segs_free(pcb->unacked);
2173 pcb->unacked = pcb->unsent = NULL;
2175 pcb->unsent_oversize = 0;
2187tcp_pcb_remove(
struct tcp_pcb **pcblist,
struct tcp_pcb *pcb)
2189 LWIP_ASSERT(
"tcp_pcb_remove: invalid pcb", pcb != NULL);
2190 LWIP_ASSERT(
"tcp_pcb_remove: invalid pcblist", pcblist != NULL);
2192 TCP_RMV(pcblist, pcb);
2197 if ((pcb->state != TIME_WAIT) &&
2198 (pcb->state != LISTEN) &&
2199 (pcb->flags & TF_ACK_DELAY)) {
2204 if (pcb->state != LISTEN) {
2205 LWIP_ASSERT(
"unsent segments leaking", pcb->unsent == NULL);
2206 LWIP_ASSERT(
"unacked segments leaking", pcb->unacked == NULL);
2208 LWIP_ASSERT(
"ooseq segments leaking", pcb->ooseq == NULL);
2212 pcb->state = CLOSED;
2214 pcb->local_port = 0;
2216 LWIP_ASSERT(
"tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
2225tcp_next_iss(
struct tcp_pcb *pcb)
2227#ifdef LWIP_HOOK_TCP_ISN
2228 LWIP_ASSERT(
"tcp_next_iss: invalid pcb", pcb != NULL);
2229 return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port);
2231 static u32_t iss = 6510;
2233 LWIP_ASSERT(
"tcp_next_iss: invalid pcb", pcb != NULL);
2241#if TCP_CALCULATE_EFF_SEND_MSS
2248tcp_eff_send_mss_netif(u16_t sendmss,
struct netif *outif,
const ip_addr_t *dest)
2255 LWIP_ASSERT(
"tcp_eff_send_mss_netif: invalid dst_ip", dest != NULL);
2263 mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif);
2271 if (outif == NULL) {
2285 offset = IP6_HLEN + TCP_HLEN;
2293 offset = IP_HLEN + TCP_HLEN;
2296 mss_s = (mtu > offset) ? (u16_t)(mtu - offset) : 0;
2301 sendmss = LWIP_MIN(sendmss, mss_s);
2309tcp_netif_ip_addr_changed_pcblist(
const ip_addr_t *old_addr,
struct tcp_pcb *pcb_list)
2311 struct tcp_pcb *pcb;
2314 LWIP_ASSERT(
"tcp_netif_ip_addr_changed_pcblist: invalid old_addr", old_addr != NULL);
2316 while (pcb != NULL) {
2318 if (ip_addr_eq(&pcb->local_ip, old_addr)
2321 && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)))
2325 struct tcp_pcb *next = pcb->next;
2341tcp_netif_ip_addr_changed(
const ip_addr_t *old_addr,
const ip_addr_t *new_addr)
2343 struct tcp_pcb_listen *lpcb;
2345 if (!ip_addr_isany(old_addr)) {
2346 tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs);
2347 tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs);
2349 if (!ip_addr_isany(new_addr)) {
2351 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
2353 if (ip_addr_eq(&lpcb->local_ip, old_addr)) {
2356 ip_addr_copy(lpcb->local_ip, *new_addr);
2364tcp_debug_state_str(
enum tcp_state s)
2366 return tcp_state_str[s];
2370tcp_tcp_get_tcp_addrinfo(
struct tcp_pcb *pcb,
int local, ip_addr_t *addr, u16_t *port)
2375 *addr = pcb->local_ip;
2378 *port = pcb->local_port;
2382 *addr = pcb->remote_ip;
2385 *port = pcb->remote_port;
2396tcp_free_ooseq(
struct tcp_pcb *pcb)
2399 tcp_segs_free(pcb->ooseq);
2401#if LWIP_TCP_SACK_OUT
2402 memset(pcb->rcv_sacks, 0,
sizeof(pcb->rcv_sacks));
2408#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
2415tcp_debug_print(
struct tcp_hdr *tcphdr)
2417 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP header:\n"));
2418 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2419 LWIP_DEBUGF(
TCP_DEBUG, (
"| %5"U16_F
" | %5"U16_F
" | (src port, dest port)\n",
2420 lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest)));
2421 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2422 LWIP_DEBUGF(
TCP_DEBUG, (
"| %010"U32_F
" | (seq no)\n",
2423 lwip_ntohl(tcphdr->seqno)));
2424 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2425 LWIP_DEBUGF(
TCP_DEBUG, (
"| %010"U32_F
" | (ack no)\n",
2426 lwip_ntohl(tcphdr->ackno)));
2427 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2428 LWIP_DEBUGF(
TCP_DEBUG, (
"| %2"U16_F
" | |%"U16_F
"%"U16_F
"%"U16_F
"%"U16_F
"%"U16_F
"%"U16_F
"| %5"U16_F
" | (hdrlen, flags (",
2429 TCPH_HDRLEN(tcphdr),
2430 (u16_t)(TCPH_FLAGS(tcphdr) >> 5 & 1),
2431 (u16_t)(TCPH_FLAGS(tcphdr) >> 4 & 1),
2432 (u16_t)(TCPH_FLAGS(tcphdr) >> 3 & 1),
2433 (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1),
2434 (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1),
2435 (u16_t)(TCPH_FLAGS(tcphdr) & 1),
2436 lwip_ntohs(tcphdr->wnd)));
2437 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
2439 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2440 LWIP_DEBUGF(
TCP_DEBUG, (
"| 0x%04"X16_F
" | %5"U16_F
" | (chksum, urgp)\n",
2441 lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp)));
2442 LWIP_DEBUGF(
TCP_DEBUG, (
"+-------------------------------+\n"));
2451tcp_debug_print_state(
enum tcp_state s)
2453 LWIP_DEBUGF(
TCP_DEBUG, (
"State: %s\n", tcp_state_str[s]));
2462tcp_debug_print_flags(u8_t flags)
2464 if (flags & TCP_FIN) {
2467 if (flags & TCP_SYN) {
2470 if (flags & TCP_RST) {
2473 if (flags & TCP_PSH) {
2476 if (flags & TCP_ACK) {
2479 if (flags & TCP_URG) {
2482 if (flags & TCP_ECE) {
2485 if (flags & TCP_CWR) {
2495tcp_debug_print_pcbs(
void)
2497 struct tcp_pcb *pcb;
2498 struct tcp_pcb_listen *pcbl;
2500 LWIP_DEBUGF(
TCP_DEBUG, (
"Active PCB states:\n"));
2501 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
2502 LWIP_DEBUGF(
TCP_DEBUG, (
"Local port %"U16_F
", foreign port %"U16_F
" snd_nxt %"U32_F
" rcv_nxt %"U32_F
" ",
2503 pcb->local_port, pcb->remote_port,
2504 pcb->snd_nxt, pcb->rcv_nxt));
2505 tcp_debug_print_state(pcb->state);
2508 LWIP_DEBUGF(
TCP_DEBUG, (
"Listen PCB states:\n"));
2509 for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) {
2510 LWIP_DEBUGF(
TCP_DEBUG, (
"Local port %"U16_F
" ", pcbl->local_port));
2511 tcp_debug_print_state(pcbl->state);
2514 LWIP_DEBUGF(
TCP_DEBUG, (
"TIME-WAIT PCB states:\n"));
2515 for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
2516 LWIP_DEBUGF(
TCP_DEBUG, (
"Local port %"U16_F
", foreign port %"U16_F
" snd_nxt %"U32_F
" rcv_nxt %"U32_F
" ",
2517 pcb->local_port, pcb->remote_port,
2518 pcb->snd_nxt, pcb->rcv_nxt));
2519 tcp_debug_print_state(pcb->state);
2529 struct tcp_pcb *pcb;
2530 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
2531 LWIP_ASSERT(
"tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
2532 LWIP_ASSERT(
"tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
2533 LWIP_ASSERT(
"tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
2535 for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
2536 LWIP_ASSERT(
"tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
2542#if LWIP_TCP_PCB_NUM_EXT_ARGS
2560static u8_t tcp_ext_arg_id;
2581tcp_ext_arg_alloc_id(
void)
2583 u8_t result = tcp_ext_arg_id;
2588#if LWIP_TCP_PCB_NUM_EXT_ARGS >= 255
2589#error LWIP_TCP_PCB_NUM_EXT_ARGS
2604tcp_ext_arg_set_callbacks(
struct tcp_pcb *pcb, u8_t
id,
const struct tcp_ext_arg_callbacks *
const callbacks)
2606 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
2608 LWIP_ASSERT(
"callbacks != NULL", callbacks != NULL);
2612 pcb->ext_args[id].callbacks = callbacks;
2623void tcp_ext_arg_set(
struct tcp_pcb *pcb, u8_t
id,
void *arg)
2625 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
2630 pcb->ext_args[id].data = arg;
2641void *tcp_ext_arg_get(
const struct tcp_pcb *pcb, u8_t
id)
2643 LWIP_ASSERT(
"pcb != NULL", pcb != NULL);
2648 return pcb->ext_args[id].data;
2655tcp_ext_arg_invoke_callbacks_destroyed(
struct tcp_pcb_ext_args *ext_args)
2658 LWIP_ASSERT(
"ext_args != NULL", ext_args != NULL);
2661 if (ext_args[i].callbacks != NULL) {
2662 if (ext_args[i].callbacks->destroy != NULL) {
2663 ext_args[i].callbacks->destroy((u8_t)i, ext_args[i].data);
2676tcp_ext_arg_invoke_callbacks_passive_open(
struct tcp_pcb_listen *lpcb,
struct tcp_pcb *cpcb)
2679 LWIP_ASSERT(
"lpcb != NULL", lpcb != NULL);
2680 LWIP_ASSERT(
"cpcb != NULL", cpcb != NULL);
2683 if (lpcb->ext_args[i].callbacks != NULL) {
2684 if (lpcb->ext_args[i].callbacks->passive_open != NULL) {
2685 err_t err = lpcb->ext_args[i].callbacks->passive_open((u8_t)i, lpcb, cpcb);
#define LWIP_UNUSED_ARG(x)
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
#define LWIP_TCP_PCB_NUM_EXT_ARGS
#define TCP_WND_UPDATE_THRESHOLD
#define LWIP_TCP_RTO_TIME
struct netif * netif_get_by_index(u8_t idx)
void pbuf_ref(struct pbuf *p)
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
u8 pbuf_free(struct pbuf *p)
#define ip_get_option(pcb, opt)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define PBUF_FLAG_TCP_FIN