00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #include <cfg/os.h>
00102 #include <cfg/tcp.h>
00103
00104 #include <sys/thread.h>
00105 #include <sys/heap.h>
00106 #include <sys/event.h>
00107 #include <sys/timer.h>
00108
00109 #include <errno.h>
00110 #include <netinet/in.h>
00111 #include <netinet/ip.h>
00112 #include <net/route.h>
00113 #include <sys/socket.h>
00114 #include <netinet/tcputil.h>
00115 #include <netinet/tcp.h>
00116
00117 #ifdef NUTDEBUG
00118 #include <net/netdebug.h>
00119 #endif
00120
00121 #ifndef NUT_THREAD_TCPSMSTACK
00122 #if defined(__AVR__)
00123 #if defined(__GNUC__)
00124
00125 #define NUT_THREAD_TCPSMSTACK 256
00126 #else
00127
00128 #define NUT_THREAD_TCPSMSTACK 512
00129 #endif
00130 #else
00131
00132 #define NUT_THREAD_TCPSMSTACK 384
00133 #endif
00134 #endif
00135
00136 #ifndef TCP_RETRIES_MAX
00137 #define TCP_RETRIES_MAX 7
00138 #endif
00139
00140 extern TCPSOCKET *tcpSocketList;
00141
00146
00147 HANDLE tcp_in_rdy;
00148 NETBUF *volatile tcp_in_nbq;
00149 static uint16_t tcp_in_cnt;
00150 static HANDLE tcpThread = 0;
00151
00152 #ifndef TCP_COLLECT_INADV
00153 #define TCP_COLLECT_INADV 8
00154 #endif
00155
00156 #ifndef TCP_COLLECT_SLIMIT
00157 #define TCP_COLLECT_SLIMIT 256
00158 #endif
00159
00160 #ifndef TCP_BACKLOG_MAX
00161 #define TCP_BACKLOG_MAX 8
00162 #endif
00163
00164 #if TCP_BACKLOG_MAX
00165 #ifndef TCP_BACKLOG_TIME
00166 #define TCP_BACKLOG_TIME 5
00167 #endif
00168 static NETBUF *tcp_backlog[TCP_BACKLOG_MAX];
00169 static uint_fast8_t tcp_backlog_time[TCP_BACKLOG_MAX];
00170 #endif
00171
00172 static size_t tcp_adv_cnt;
00173 static size_t tcp_adv_max = TCP_WINSIZE;
00174
00175 static void NutTcpStateProcess(TCPSOCKET * sock, NETBUF * nb);
00176
00177
00178
00179
00180
00181
00182 #if TCP_BACKLOG_MAX
00183 static int NutTcpBacklogAdd(NETBUF *nb)
00184 {
00185 uint_fast8_t i;
00186 uint_fast8_t n = TCP_BACKLOG_MAX;
00187 IPHDR *ih = (IPHDR *) nb->nb_nw.vp;
00188 TCPHDR *th = (TCPHDR *) nb->nb_tp.vp;
00189
00190
00191 if ((th->th_flags & (TH_SYN | TH_ACK | TH_RST)) == TH_SYN) {
00192 for (i = 0; i < TCP_BACKLOG_MAX; i++) {
00193 if (tcp_backlog[i] == NULL) {
00194
00195 if (n == TCP_BACKLOG_MAX) {
00196 n = i;
00197 }
00198 }
00199 else if (((IPHDR *) tcp_backlog[i]->nb_nw.vp)->ip_src == ih->ip_src &&
00200 ((TCPHDR *) tcp_backlog[i]->nb_tp.vp)->th_sport == th->th_sport) {
00201
00202
00203 NutNetBufFree(tcp_backlog[i]);
00204 tcp_backlog[i] = NULL;
00205 return -1;
00206 }
00207 }
00208
00209
00210 if (n != TCP_BACKLOG_MAX) {
00211 tcp_backlog[n] = nb;
00212 tcp_backlog_time[n] = 0;
00213 return 0;
00214 }
00215 }
00216 return -1;
00217 }
00218
00219 static NETBUF *NutTcpBacklogCheck(uint16_t port)
00220 {
00221 NETBUF *nb;
00222 uint_fast8_t i;
00223 uint_fast8_t n = TCP_BACKLOG_MAX;
00224
00225 for (i = 0; i < TCP_BACKLOG_MAX; i++) {
00226 if (tcp_backlog[i]) {
00227 if (((TCPHDR *) tcp_backlog[i]->nb_tp.vp)->th_dport == port) {
00228 if (n == TCP_BACKLOG_MAX || tcp_backlog_time[i] > tcp_backlog_time[n]) {
00229 n = i;
00230 }
00231 }
00232 }
00233 }
00234 if (n == TCP_BACKLOG_MAX) {
00235 nb = NULL;
00236 } else {
00237 nb = tcp_backlog[n];
00238 tcp_backlog[n] = NULL;
00239 }
00240 return nb;
00241 }
00242
00243 static NETBUF *NutTcpBacklogTimer(void)
00244 {
00245 NETBUF *nb;
00246 uint_fast8_t i;
00247 uint_fast8_t n = TCP_BACKLOG_MAX;
00248
00249 for (i = 0; i < TCP_BACKLOG_MAX; i++) {
00250 if (tcp_backlog[i]) {
00251 if (tcp_backlog_time[i] < TCP_BACKLOG_TIME) {
00252 tcp_backlog_time[i]++;
00253 } else {
00254 n = i;
00255 }
00256 }
00257 }
00258 if (n == TCP_BACKLOG_MAX) {
00259 nb = NULL;
00260 } else {
00261 nb = tcp_backlog[n];
00262 tcp_backlog[n] = NULL;
00263 }
00264 return nb;
00265 }
00266 #endif
00267
00276 static void NutTcpInputOptions(TCPSOCKET * sock, NETBUF * nb)
00277 {
00278 uint8_t *cp;
00279 uint16_t s;
00280
00281
00282 if (nb->nb_tp.sz <= sizeof (TCPHDR))
00283 return;
00284
00285
00286 for (cp = ((uint8_t*) nb->nb_tp.vp) + sizeof(TCPHDR); (*cp != TCPOPT_EOL)
00287 && (cp - (uint8_t *)nb->nb_tp.vp < (int)nb->nb_tp.sz); )
00288 {
00289 switch (*cp)
00290 {
00291
00292 case TCPOPT_NOP:
00293 cp++;
00294 continue;
00295
00296
00297 case TCPOPT_MAXSEG:
00298
00299 s = cp[2];
00300 s <<= 8;
00301 s |= cp[3];
00302 if (s < sock->so_mss)
00303 sock->so_mss = s;
00304 cp += TCPOLEN_MAXSEG;
00305 break;
00306
00307 default:
00308 cp += *(uint8_t*) (cp + 1);
00309 break;
00310 }
00311 }
00312 }
00313
00322 static void NutTcpProcessAppData(TCPSOCKET * sock, NETBUF * nb)
00323 {
00324
00325
00326
00327 if (sock->so_rx_buf) {
00328 NETBUF *nbp = sock->so_rx_buf;
00329
00330 while (nbp->nb_next)
00331 nbp = nbp->nb_next;
00332 nbp->nb_next = nb;
00333 } else
00334 sock->so_rx_buf = nb;
00335
00336
00337
00338
00339
00340 sock->so_rx_cnt += nb->nb_ap.sz;
00341 sock->so_rx_nxt += nb->nb_ap.sz;
00342
00343
00344
00345
00346 if (nb->nb_ap.sz >= sock->so_rx_win)
00347 sock->so_rx_win = 0;
00348 else
00349 sock->so_rx_win -= nb->nb_ap.sz;
00350
00351
00352
00353
00354
00355
00356 sock->so_tx_flags |= SO_ACK;
00357 if (nb->nb_next)
00358 nb->nb_next = 0;
00359 else
00360 sock->so_tx_flags |= SO_FORCE;
00361
00362 if (++sock->so_rx_apc > TCP_COLLECT_INADV) {
00363 NETBUF *nbq;
00364 int_fast8_t apc = sock->so_rx_apc;
00365 int cnt = sock->so_rx_cnt;
00366
00367 for (nbq = sock->so_rx_buf; nbq; nbq = nbq->nb_next) {
00368 if (nbq->nb_ap.sz < TCP_COLLECT_SLIMIT) {
00369 sock->so_rx_apc -= NutNetBufCollect(nbq, cnt);
00370 break;
00371 }
00372 if (--apc < 8) {
00373 break;
00374 }
00375 cnt -= nbq->nb_ap.sz;
00376 }
00377 }
00378 NutTcpOutput(sock, 0, 0);
00379 }
00380
00381
00382
00383
00384 static void NutTcpProcessSyn(TCPSOCKET * sock, IPHDR * ih, TCPHDR * th)
00385 {
00386 uint16_t mss;
00387 NUTDEVICE *dev;
00388 IFNET *nif;
00389
00390 sock->so_local_addr = ih->ip_dst;
00391 sock->so_remote_port = th->th_sport;
00392 sock->so_remote_addr = ih->ip_src;
00393
00394 sock->so_rx_nxt = sock->so_tx_wl1 = sock->so_rx_isn = ntohl(th->th_seq);
00395 sock->so_rx_nxt++;
00396 sock->so_tx_win = ntohs(th->th_win);
00397
00398
00399
00400
00401
00402
00403 if ((dev = NutIpRouteQuery(ih->ip_src, 0)) != 0) {
00404 nif = dev->dev_icb;
00405 mss = nif->if_mtu - sizeof(IPHDR) - sizeof(TCPHDR);
00406 if (sock->so_mss == 0 || sock->so_mss > mss)
00407 sock->so_mss = mss;
00408
00409
00410 if (sock->so_devobsz > sock->so_mss)
00411 sock->so_devobsz = sock->so_mss;
00412 }
00413 }
00414
00422 static int NutTcpProcessAck(TCPSOCKET * sock, TCPHDR * th, uint16_t length)
00423 {
00424 NETBUF *nb;
00425 uint32_t h_seq;
00426 uint32_t h_ack;
00427
00428
00429
00430
00431 h_ack = ntohl(th->th_ack);
00432 if (SeqIsAfter(h_ack, sock->so_tx_nxt)) {
00433 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00434 return 0;
00435 }
00436
00437
00438
00439
00440
00441
00442 if (h_ack == sock->so_tx_una) {
00443 h_seq = ntohl(th->th_seq);
00444 if (SeqIsAfter(h_seq, sock->so_tx_wl1) || (h_seq == sock->so_tx_wl1 && !SeqIsAfter(sock->so_tx_wl2, h_ack))) {
00445 sock->so_tx_win = ntohs(th->th_win);
00446 sock->so_tx_wl1 = h_seq;
00447 sock->so_tx_wl2 = h_ack;
00448 }
00449 }
00450
00451
00452
00453
00454
00455 if (SeqIsAfter(sock->so_tx_una, h_ack)) {
00456 return 0;
00457 }
00458
00459
00460
00461
00462 if (h_ack == sock->so_tx_una) {
00463
00464
00465
00466
00467 if (sock->so_tx_nbq && length == 0 && (th->th_flags & (TH_SYN | TH_FIN)) == 0) {
00468
00469
00470
00471
00472 if (++sock->so_tx_dup >= 3) {
00473 sock->so_tx_dup = 0;
00474 #ifdef NUTDEBUG
00475 if (__tcp_trf & NET_DBG_SOCKSTATE)
00476 NutDumpTcpHeader(__tcp_trs, "RET", sock, sock->so_tx_nbq);
00477 #endif
00478
00479
00480
00481
00482 if (NutTcpStateRetranTimeout(sock))
00483 return -1;
00484 }
00485 }
00486 return 0;
00487 }
00488
00489
00490
00491
00492 sock->so_tx_dup = 0;
00493 sock->so_tx_una = h_ack;
00494
00495
00496
00497
00498
00499
00500 sock->so_tx_win = ntohs(th->th_win);
00501
00502
00503
00504
00505 if (sock->so_rtt_seq && SeqIsAfter(h_ack, sock->so_rtt_seq))
00506 NutTcpCalcRtt (sock);
00507 sock->so_rtt_seq = 0;
00508
00509
00510
00511 while ((nb = sock->so_tx_nbq) != 0) {
00512
00513 h_seq = ntohl(((TCPHDR *) (nb->nb_tp.vp))->th_seq) + nb->nb_ap.sz;
00514 if (((TCPHDR *) (nb->nb_tp.vp))->th_flags & (TH_SYN | TH_FIN)) {
00515 h_seq++;
00516 }
00517
00518 if (SeqIsAfter(h_seq, h_ack)) {
00519 break;
00520 }
00521 sock->so_tx_nbq = nb->nb_next;
00522 NutNetBufFree(nb);
00523 }
00524
00525
00526
00527
00528 if (sock->so_tx_nbq) {
00529 sock->so_retran_time = (uint16_t) NutGetMillis() | 1;
00530 } else {
00531 sock->so_retran_time = 0;
00532 }
00533 sock->so_retransmits = 0;
00534
00535 return 0;
00536 }
00537
00538
00539
00540
00541
00542
00543
00552 static int NutTcpStateChange(TCPSOCKET * sock, uint8_t state)
00553 {
00554 int rc = 0;
00555 ureg_t txf = 0;
00556
00557 switch (sock->so_state) {
00558
00559 case TCPS_ESTABLISHED:
00560 switch (state) {
00561 case TCPS_FIN_WAIT_1:
00562
00563
00564
00565 sock->so_tx_flags |= SO_FIN | SO_ACK;
00566 txf = 1;
00567
00568 #ifdef RTLCONNECTHACK
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 NutDelay(5);
00579 #endif
00580 break;
00581 case TCPS_CLOSE_WAIT:
00582
00583
00584
00585 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00586 txf = 1;
00587 break;
00588 default:
00589 rc = -1;
00590 break;
00591 }
00592 break;
00593
00594 case TCPS_LISTEN:
00595
00596
00597
00598 if (state == TCPS_SYN_RECEIVED) {
00599 sock->so_tx_flags |= SO_SYN | SO_ACK;
00600 txf = 1;
00601 #ifdef RTLCONNECTHACK
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 NutDelay(5);
00612 #endif
00613 } else
00614 rc = -1;
00615 break;
00616
00617 case TCPS_SYN_SENT:
00618 switch (state) {
00619 case TCPS_LISTEN:
00620
00621
00622
00623 break;
00624 case TCPS_SYN_RECEIVED:
00625
00626
00627
00628 sock->so_tx_flags |= SO_SYN | SO_ACK;
00629 txf = 1;
00630 break;
00631 case TCPS_ESTABLISHED:
00632
00633
00634
00635 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00636 txf = 1;
00637 break;
00638 default:
00639 rc = -1;
00640 break;
00641 }
00642 break;
00643
00644 case TCPS_SYN_RECEIVED:
00645 switch (state) {
00646 case TCPS_LISTEN:
00647
00648
00649
00650 break;
00651 case TCPS_ESTABLISHED:
00652
00653
00654
00655 break;
00656 case TCPS_FIN_WAIT_1:
00657
00658
00659
00660 sock->so_tx_flags |= SO_FIN;
00661 txf = 1;
00662 break;
00663 case TCPS_CLOSE_WAIT:
00664
00665
00666
00667 sock->so_tx_flags |= SO_FIN | SO_ACK;
00668 txf = 1;
00669 break;
00670 default:
00671 rc = -1;
00672 break;
00673 }
00674 break;
00675
00676 case TCPS_FIN_WAIT_1:
00677 switch (state) {
00678 case TCPS_FIN_WAIT_1:
00679 case TCPS_FIN_WAIT_2:
00680
00681
00682
00683 break;
00684 case TCPS_CLOSING:
00685
00686
00687
00688 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00689 txf = 1;
00690 break;
00691 case TCPS_TIME_WAIT:
00692
00693
00694
00695 break;
00696 default:
00697 rc = -1;
00698 break;
00699 }
00700 break;
00701
00702 case TCPS_FIN_WAIT_2:
00703
00704
00705
00706 if (state != TCPS_TIME_WAIT)
00707 rc = -1;
00708 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00709 txf = 1;
00710 break;
00711
00712 case TCPS_CLOSE_WAIT:
00713
00714
00715
00716 if (state == TCPS_LAST_ACK) {
00717 sock->so_tx_flags |= SO_FIN | SO_ACK;
00718 txf = 1;
00719 } else
00720 rc = -1;
00721 break;
00722
00723 case TCPS_CLOSING:
00724
00725
00726
00727 if (state != TCPS_TIME_WAIT)
00728 rc = -1;
00729 break;
00730
00731 case TCPS_LAST_ACK:
00732 rc = -1;
00733 break;
00734
00735 case TCPS_TIME_WAIT:
00736 rc = -1;
00737 break;
00738
00739 case TCPS_CLOSED:
00740 switch (state) {
00741 case TCPS_LISTEN:
00742
00743
00744
00745 break;
00746 case TCPS_SYN_SENT:
00747
00748
00749
00750 sock->so_tx_flags |= SO_SYN;
00751 txf = 1;
00752 break;
00753 default:
00754 rc = -1;
00755 break;
00756 }
00757 break;
00758 }
00759 #ifdef NUTDEBUG
00760 if (__tcp_trf & NET_DBG_SOCKSTATE) {
00761 fprintf(__tcp_trs, " %04x-", (unsigned int) sock);
00762 if (rc)
00763 NutDumpSockState(__tcp_trs, sock->so_state, "**ERR ", "**>");
00764 NutDumpSockState(__tcp_trs, state, "[>", "]");
00765 }
00766 #endif
00767
00768 if (rc == 0) {
00769 sock->so_state = state;
00770 if (txf && NutTcpOutput(sock, 0, 0)) {
00771 if (state == TCPS_SYN_SENT) {
00772 rc = -1;
00773 sock->so_last_error = EHOSTDOWN;
00774 NutEventPostAsync(&sock->so_ac_tq);
00775 }
00776 }
00777 if (state == TCPS_CLOSE_WAIT) {
00778
00779
00780
00781 NutEventBroadcast(&sock->so_rx_tq);
00782 NutEventBroadcast(&sock->so_pc_tq);
00783 NutEventBroadcast(&sock->so_ac_tq);
00784 }
00785 }
00786 return rc;
00787 }
00788
00789
00790
00791
00792
00801 int NutTcpStatePassiveOpenEvent(TCPSOCKET * sock)
00802 {
00803 if (sock->so_state != TCPS_CLOSED)
00804 return (sock->so_last_error = EISCONN);
00805
00806 NutTcpStateChange(sock, TCPS_LISTEN);
00807
00808 #if TCP_BACKLOG_MAX
00809 {
00810
00811
00812 NETBUF *nb = NutTcpBacklogCheck(sock->so_local_port);
00813 if (nb) {
00814 NutTcpInputOptions(sock, nb);
00815 NutTcpStateProcess(sock, nb);
00816
00817 return 0;
00818 }
00819 }
00820 if (NutEventWait(&sock->so_pc_tq, sock->so_read_to)) {
00821 sock->so_state = TCPS_CLOSED;
00822 return (sock->so_last_error = ETIMEDOUT);
00823 }
00824 #else
00825
00826
00827
00828
00829 NutEventWait(&sock->so_pc_tq, 0);
00830 #endif
00831
00832 return 0;
00833 }
00834
00845 int NutTcpStateActiveOpenEvent(TCPSOCKET * sock)
00846 {
00847
00848
00849
00850
00851 NutTcpStateChange(sock, TCPS_SYN_SENT);
00852
00853
00854
00855
00856 if(sock->so_state == TCPS_SYN_SENT)
00857 NutEventWait(&sock->so_ac_tq, 0);
00858
00859 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT)
00860 return -1;
00861
00862 return 0;
00863 }
00864
00877 int NutTcpStateCloseEvent(TCPSOCKET * sock)
00878 {
00879 if (sock == 0)
00880 return -1;
00881
00882 NutThreadYield();
00883
00884 switch (sock->so_state) {
00885 case TCPS_LISTEN:
00886 case TCPS_SYN_SENT:
00887 case TCPS_CLOSED:
00888
00889
00890
00891 NutTcpDestroySocket(sock);
00892 break;
00893
00894 case TCPS_SYN_RECEIVED:
00895 case TCPS_ESTABLISHED:
00896
00897
00898
00899
00900 NutTcpStateChange(sock, TCPS_FIN_WAIT_1);
00901 break;
00902
00903 case TCPS_CLOSE_WAIT:
00904
00905
00906
00907
00908 NutTcpStateChange(sock, TCPS_LAST_ACK);
00909 break;
00910
00911 case TCPS_FIN_WAIT_1:
00912 case TCPS_FIN_WAIT_2:
00913 case TCPS_CLOSING:
00914 case TCPS_LAST_ACK:
00915 case TCPS_TIME_WAIT:
00916 sock->so_last_error = EALREADY;
00917 return -1;
00918
00919 default:
00920 sock->so_last_error = ENOTCONN;
00921 return -1;
00922 }
00923 return 0;
00924 }
00925
00932 int NutTcpStateWindowEvent(TCPSOCKET * sock)
00933 {
00934 if (sock == 0)
00935 return -1;
00936 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00937 NutTcpOutput(sock, 0, 0);
00938
00939 return 0;
00940 }
00941
00942
00943
00944
00945
00957 int NutTcpStateRetranTimeout(TCPSOCKET * sock)
00958 {
00959 NETBUF *so_tx_next;
00960 if (sock->so_retransmits++ > TCP_RETRIES_MAX)
00961 {
00962
00963 NutTcpAbortSocket(sock, ETIMEDOUT);
00964 return -1;
00965 } else {
00966 #ifdef NUTDEBUG
00967 if (__tcp_trf & NET_DBG_SOCKSTATE)
00968 NutDumpTcpHeader(__tcp_trs, "RET", sock, sock->so_tx_nbq);
00969 #endif
00970
00971
00972
00973
00974 so_tx_next = sock->so_tx_nbq->nb_next;
00975 if (NutIpOutput(IPPROTO_TCP, sock->so_remote_addr, sock->so_tx_nbq)) {
00976
00977 sock->so_tx_nbq = so_tx_next;
00978
00979 NutTcpAbortSocket(sock, ENETDOWN);
00980 return -1;
00981 } else {
00982
00983 sock->so_retran_time = (uint16_t) NutGetMillis() | 1;
00984 return 0;
00985 }
00986 }
00987 }
00988
00989
00990
00991
00992
00993
01003 static void NutTcpStateListen(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01004 {
01005
01006
01007
01008
01009 if ((flags & (TH_SYN | TH_ACK | TH_RST)) == TH_SYN) {
01010 NutTcpProcessSyn(sock, nb->nb_nw.vp, th);
01011 NutTcpStateChange(sock, TCPS_SYN_RECEIVED);
01012 NutNetBufFree(nb);
01013 } else
01014 NutTcpReject(nb);
01015 }
01016
01017
01026 static void NutTcpStateSynSent(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01027 {
01028
01029
01030
01031 if (flags & TH_ACK) {
01032 if (!SeqIsBetween(ntohl(th->th_ack), sock->so_tx_isn + 1, sock->so_tx_nxt)) {
01033 NutTcpReject(nb);
01034 return;
01035 }
01036 }
01037
01038
01039
01040
01041
01042
01043 if (flags & TH_RST) {
01044 if (flags & TH_ACK) {
01045
01046
01047
01048 NutTcpAbortSocket(sock, ECONNREFUSED);
01049 }
01050 NutNetBufFree(nb);
01051 return;
01052 }
01053
01054
01055
01056
01057
01058
01059 if (flags & TH_SYN) {
01060 NutTcpProcessSyn(sock, nb->nb_nw.vp, th);
01061 if (flags & TH_ACK) {
01062 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01063 NutTcpStateChange(sock, TCPS_ESTABLISHED);
01064
01065 NutEventPost(&sock->so_ac_tq);
01066 } else {
01067 NutTcpStateChange(sock, TCPS_SYN_RECEIVED);
01068 }
01069 }
01070 NutNetBufFree(nb);
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static void NutTcpStateSynReceived(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01085 {
01086
01087
01088
01089
01090 if (flags & TH_RST) {
01091 if (sock->so_pc_tq)
01092 NutTcpStateChange(sock, TCPS_LISTEN);
01093 else
01094 NutTcpAbortSocket(sock, ECONNREFUSED);
01095 NutNetBufFree(nb);
01096 sock->so_retran_time = 0;
01097 NutTcpDiscardBuffers(sock);
01098 return;
01099 }
01100
01101
01102
01103
01104 if (flags & TH_SYN) {
01105 NutTcpReject(nb);
01106 return;
01107 }
01108
01109
01110
01111
01112 if ((flags & TH_ACK) == 0) {
01113 NutNetBufFree(nb);
01114 return;
01115 }
01116
01117
01118
01119
01120 if (!SeqIsBetween(ntohl(th->th_ack), sock->so_tx_una + 1, sock->so_tx_nxt)) {
01121 NutTcpReject(nb);
01122 return;
01123 }
01124
01125
01126 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01127
01128
01129
01130
01131
01132
01133
01134 if (nb->nb_ap.sz)
01135 NutTcpProcessAppData(sock, nb);
01136 else
01137 NutNetBufFree(nb);
01138
01139
01140
01141
01142 if (flags & TH_FIN) {
01143 sock->so_rx_nxt++;
01144 NutTcpStateChange(sock, TCPS_CLOSE_WAIT);
01145 } else {
01146 NutTcpStateChange(sock, TCPS_ESTABLISHED);
01147 NutEventPost(&sock->so_pc_tq);
01148 NutEventPost(&sock->so_ac_tq);
01149 }
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static void NutTcpStateEstablished(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01167 {
01168 if (flags & TH_RST) {
01169 NutNetBufFree(nb);
01170 NutTcpAbortSocket(sock, ECONNRESET);
01171 return;
01172 }
01173
01174
01175
01176
01177
01178 if (flags & TH_SYN) {
01179 if (ntohl(th->th_seq) != sock->so_rx_isn)
01180 NutTcpReject(nb);
01181 else
01182 NutNetBufFree(nb);
01183 return;
01184 }
01185
01186
01187
01188
01189 if ((flags & TH_ACK) == 0) {
01190 NutNetBufFree(nb);
01191 return;
01192 }
01193
01194 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01195
01196
01197
01198
01199
01200
01201
01202 if (SeqIsAfter(ntohl(th->th_seq),sock->so_rx_nxt)) {
01203 NETBUF *nbq;
01204 NETBUF **nbqp;
01205 TCPHDR *thq;
01206 uint32_t th_seq;
01207 uint32_t thq_seq;
01208
01209 if (nb->nb_ap.sz) {
01210
01211
01212 tcp_adv_cnt += nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01213 if (tcp_adv_cnt > tcp_adv_max) {
01214
01215 NutNetBufFree(nb);
01216 tcp_adv_cnt -= nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01217 } else {
01218 nbq = sock->so_rx_nbq;
01219 nbqp = &sock->so_rx_nbq;
01220 while (nbq) {
01221 thq = (TCPHDR *) (nbq->nb_tp.vp);
01222 th_seq = ntohl(th->th_seq);
01223 thq_seq = ntohl(thq->th_seq);
01224 if (SeqIsAfter(thq_seq, th_seq)) {
01225 *nbqp = nb;
01226 nb->nb_next = nbq;
01227 break;
01228 }
01229 if (th_seq == thq_seq) {
01230 NutNetBufFree(nb);
01231 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01232 NutTcpOutput(sock, 0, 0);
01233 return;
01234 }
01235 nbqp = &nbq->nb_next;
01236 nbq = nbq->nb_next;
01237 }
01238 if (nbq == 0) {
01239 *nbqp = nb;
01240 nb->nb_next = 0;
01241 }
01242 }
01243 } else
01244 NutNetBufFree(nb);
01245
01246 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01247 NutTcpOutput(sock, 0, 0);
01248 return;
01249 }
01250
01251
01252
01253
01254
01255
01256
01257
01258 if (ntohl(th->th_seq) != sock->so_rx_nxt) {
01259 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01260
01261 sock->so_oos_drop++;
01262 NutNetBufFree(nb);
01263 NutTcpOutput(sock, 0, 0);
01264 }
01265
01266
01267
01268
01269 else if (nb->nb_ap.sz) {
01270 NutTcpProcessAppData(sock, nb);
01271
01272
01273
01274 while ((nb = sock->so_rx_nbq) != 0) {
01275 th = (TCPHDR *) (nb->nb_tp.vp);
01276 if (SeqIsAfter(ntohl(th->th_seq), sock->so_rx_nxt))
01277 break;
01278 sock->so_rx_nbq = nb->nb_next;
01279
01280
01281 tcp_adv_cnt -= nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01282 if (ntohl(th->th_seq) == sock->so_rx_nxt) {
01283 NutTcpProcessAppData(sock, nb);
01284 flags |= th->th_flags;
01285 } else
01286 NutNetBufFree(nb);
01287 }
01288
01289 NutEventPost(&sock->so_rx_tq);
01290 } else {
01291 NutNetBufFree(nb);
01292
01293
01294 }
01295 if (flags & TH_FIN) {
01296
01297 sock->so_rx_nxt++;
01298 NutTcpStateChange(sock, TCPS_CLOSE_WAIT);
01299 }
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 static void NutTcpStateFinWait1(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01318 {
01319
01320 if (flags & TH_RST) {
01321 NutNetBufFree(nb);
01322 NutTcpDestroySocket(sock);
01323 return;
01324 }
01325
01326
01327
01328
01329 if (flags & TH_SYN) {
01330 NutTcpReject(nb);
01331 return;
01332 }
01333
01334
01335
01336
01337 if ((flags & TH_ACK) == 0) {
01338 NutNetBufFree(nb);
01339 return;
01340 }
01341
01342
01343
01344
01345
01346 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01347
01348
01349
01350
01351
01352 if (sock->so_tx_nxt == sock->so_tx_una) {
01353
01354 NutTcpStateChange(sock, TCPS_FIN_WAIT_2);
01355 }
01356
01357
01358
01359
01360
01361 if (nb->nb_ap.sz) {
01362 NutTcpProcessAppData(sock, nb);
01363
01364 NutEventPost(&sock->so_rx_tq);
01365 }
01366 else
01367 NutNetBufFree(nb);
01368
01369 if (flags & TH_FIN) {
01370 sock->so_rx_nxt++;
01371
01372
01373
01374 sock->so_time_wait = 0;
01375
01376 if (sock->so_state == TCPS_FIN_WAIT_2)
01377 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01378 else
01379 NutTcpStateChange(sock, TCPS_CLOSING);
01380 }
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 static void NutTcpStateFinWait2(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01397 {
01398
01399 if (flags & TH_RST) {
01400 NutNetBufFree(nb);
01401 NutTcpDestroySocket(sock);
01402 return;
01403 }
01404
01405
01406
01407
01408 if (flags & TH_SYN) {
01409 NutTcpReject(nb);
01410 return;
01411 }
01412
01413
01414
01415
01416 if ((flags & TH_ACK) == 0) {
01417 NutNetBufFree(nb);
01418 return;
01419 }
01420
01421
01422
01423
01424
01425
01426 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01427
01428
01429
01430 if (nb->nb_ap.sz) {
01431 NutTcpProcessAppData(sock, nb);
01432
01433 NutEventPost(&sock->so_rx_tq);
01434 }
01435 else
01436 NutNetBufFree(nb);
01437
01438 if (flags & TH_FIN) {
01439 sock->so_rx_nxt++;
01440 sock->so_time_wait = 0;
01441
01442 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01443 }
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456 static void NutTcpStateCloseWait(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01457 {
01458
01459 if (flags & TH_RST) {
01460 NutNetBufFree(nb);
01461 NutTcpAbortSocket(sock, ECONNRESET);
01462 return;
01463 }
01464
01465
01466
01467
01468 if (flags & TH_SYN) {
01469 NutTcpReject(nb);
01470 return;
01471 }
01472
01473
01474
01475
01476 if ((flags & TH_ACK) == 0) {
01477 NutNetBufFree(nb);
01478 return;
01479 }
01480
01481 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01482
01483 NutNetBufFree(nb);
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 static void NutTcpStateClosing(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01499 {
01500
01501 if (flags & TH_RST) {
01502 NutNetBufFree(nb);
01503 NutTcpDestroySocket(sock);
01504 return;
01505 }
01506
01507
01508
01509
01510 if (flags & TH_SYN) {
01511 NutTcpReject(nb);
01512 return;
01513 }
01514
01515
01516
01517
01518 if ((flags & TH_ACK) == 0) {
01519 NutNetBufFree(nb);
01520 return;
01521 }
01522
01523 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01524
01525
01526
01527
01528 if (sock->so_tx_nxt == sock->so_tx_una) {
01529 sock->so_time_wait = 0;
01530 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01531
01532 }
01533
01534
01535 NutNetBufFree(nb);
01536 }
01537
01552 static void NutTcpStateLastAck(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01553 {
01554
01555 if (flags & TH_RST) {
01556 NutNetBufFree(nb);
01557 NutTcpDestroySocket(sock);
01558 return;
01559 }
01560
01561
01562
01563
01564 if (flags & TH_SYN) {
01565 NutTcpReject(nb);
01566 return;
01567 }
01568
01569
01570
01571
01572 if ((flags & TH_ACK) == 0) {
01573 NutNetBufFree(nb);
01574 return;
01575 }
01576
01577 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01578 NutNetBufFree(nb);
01579
01580 if (sock->so_tx_nxt == sock->so_tx_una)
01581 NutTcpDestroySocket(sock);
01582
01583 }
01584
01595 static void NutTcpStateProcess(TCPSOCKET * sock, NETBUF * nb)
01596 {
01597 uint32_t tx_win;
01598 uint32_t tx_una;
01599 TCPHDR *th = (TCPHDR *) nb->nb_tp.vp;
01600 uint8_t flags = th->th_flags;
01601
01602 #ifdef NUTDEBUG
01603 if (__tcp_trf & NET_DBG_SOCKSTATE) {
01604 fprintf(__tcp_trs, " %04x-", (unsigned int) sock);
01605 NutDumpSockState(__tcp_trs, sock->so_state, "[", ">]");
01606 }
01607 #endif
01608 switch (sock->so_state) {
01609
01610 case TCPS_ESTABLISHED:
01611 tx_win = sock->so_tx_win;
01612 tx_una = sock->so_tx_una;
01613 NutTcpStateEstablished(sock, flags, th, nb);
01614
01615 if(sock->so_state != TCPS_ESTABLISHED ||
01616 sock->so_tx_win > tx_win ||
01617 sock->so_tx_una != tx_una) {
01618 NutEventBroadcast(&sock->so_tx_tq);
01619 }
01620 break;
01621 case TCPS_LISTEN:
01622 NutTcpStateListen(sock, flags, th, nb);
01623 break;
01624 case TCPS_SYN_SENT:
01625 NutTcpStateSynSent(sock, flags, th, nb);
01626 break;
01627 case TCPS_SYN_RECEIVED:
01628 NutTcpStateSynReceived(sock, flags, th, nb);
01629 break;
01630 case TCPS_FIN_WAIT_1:
01631 NutTcpStateFinWait1(sock, flags, th, nb);
01632 break;
01633 case TCPS_FIN_WAIT_2:
01634 NutTcpStateFinWait2(sock, flags, th, nb);
01635 break;
01636 case TCPS_CLOSE_WAIT:
01637 NutTcpStateCloseWait(sock, flags, th, nb);
01638 break;
01639 case TCPS_CLOSING:
01640 NutTcpStateClosing(sock, flags, th, nb);
01641 break;
01642 case TCPS_LAST_ACK:
01643 NutTcpStateLastAck(sock, flags, th, nb);
01644 break;
01645 case TCPS_TIME_WAIT:
01646
01647
01648
01649 NutNetBufFree(nb);
01650 break;
01651 case TCPS_CLOSED:
01652
01653
01654
01655 NutTcpReject(nb);
01656 break;
01657 default:
01658 NutNetBufFree(nb);
01659 break;
01660 }
01661 }
01662
01669 THREAD(NutTcpSm, arg)
01670 {
01671 NETBUF *nb;
01672 NETBUF *nbx;
01673 TCPHDR *th;
01674 IPHDR *ih;
01675 TCPSOCKET *sock;
01676 uint8_t tac = 0;
01677
01678
01679
01680
01681
01682 NutThreadSetPriority (32);
01683
01684 for (;;) {
01685 if (++tac > 3 || NutEventWait(&tcp_in_rdy, 200)) {
01686 tac = 0;
01687
01688 #if TCP_BACKLOG_MAX
01689
01690
01691
01692
01693
01694 nb = NutTcpBacklogTimer();
01695 if (nb) {
01696 NutTcpReject(nb);
01697 }
01698 #endif
01699
01700 for (sock = tcpSocketList; sock; sock = sock->so_next) {
01701
01702
01703
01704
01705 if (sock->so_tx_flags & SO_ACK) {
01706 sock->so_tx_flags |= SO_FORCE;
01707 NutTcpOutput(sock, 0, 0);
01708 }
01709
01710
01711
01712
01713 if (sock->so_tx_nbq && sock->so_retran_time) {
01714 if ((uint16_t)((uint16_t)NutGetMillis() - (sock->so_retran_time & ~1)) >= sock->so_rtto) {
01715 NutTcpStateRetranTimeout(sock);
01716 }
01717 }
01718
01719
01720
01721
01722
01723 if (sock->so_state == TCPS_TIME_WAIT || sock->so_state == TCPS_FIN_WAIT_2) {
01724 if (sock->so_time_wait++ >= 9) {
01725 NutTcpDestroySocket(sock);
01726 break;
01727 }
01728 }
01729
01730
01731
01732
01733 else if (sock->so_state == TCPS_SYN_RECEIVED) {
01734 if (sock->so_time_wait++ >= 45) {
01735 sock->so_state = TCPS_LISTEN;
01736 sock->so_time_wait = 0;
01737 }
01738 }
01739 }
01740 } else {
01741 nb = tcp_in_nbq;
01742 tcp_in_nbq = 0;
01743 tcp_in_cnt = 0;
01744 while (nb) {
01745 ih = (IPHDR *) nb->nb_nw.vp;
01746 th = (TCPHDR *) nb->nb_tp.vp;
01747 sock = NutTcpFindSocket(th->th_dport, th->th_sport, ih->ip_src);
01748 #ifdef NUTDEBUG
01749 if (__tcp_trf & NET_DBG_SOCKSTATE)
01750 NutDumpTcpHeader(__tcp_trs, " IN", sock, nb);
01751 #endif
01752 nbx = nb->nb_next;
01753
01754 if (sock) {
01755 NutTcpInputOptions(sock, nb);
01756 NutTcpStateProcess(sock, nb);
01757 }
01758 #if TCP_BACKLOG_MAX
01759
01760 else if (NutTcpBacklogAdd(nb) == 0) {
01761 }
01762 #endif
01763
01764 else {
01765 NutTcpReject(nb);
01766 }
01767 nb = nbx;
01768 }
01769 }
01770 }
01771 }
01772
01784 void NutTcpStateMachine(NETBUF * nb)
01785 {
01786 NETBUF *nbp;
01787 uint16_t size;
01788
01789 nb->nb_next = 0;
01790
01791
01792
01793
01794
01795
01796
01797 if (tcpThread == 0) {
01798 NutTcpReject(nb);
01799 return;
01800 }
01801
01802 if ((nbp = tcp_in_nbq) == 0) {
01803 tcp_in_nbq = nb;
01804 NutEventPost(&tcp_in_rdy);
01805 } else {
01806 size = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
01807 if (tcp_in_cnt + size + 2048 < NutHeapAvailable()) {
01808 tcp_in_cnt += size;
01809 while (nbp->nb_next)
01810 nbp = nbp->nb_next;
01811 nbp->nb_next = nb;
01812 NutEventPost(&tcp_in_rdy);
01813 } else
01814 NutNetBufFree(nb);
01815 }
01816 }
01817
01826 int NutTcpInitStateMachine(void)
01827 {
01828 if (tcpThread == 0 && (tcpThread = NutThreadCreate("tcpsm", NutTcpSm, NULL,
01829 (NUT_THREAD_TCPSMSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) == 0)
01830 return -1;
01831 return 0;
01832 }
01833
01847 int NutTcpAbortSocket(TCPSOCKET * sock, uint16_t last_error)
01848 {
01849 sock->so_last_error = last_error;
01850 sock->so_retran_time = 0;
01851 sock->so_time_wait = 0;
01852
01853
01854
01855
01856
01857 if (sock->so_state >= TCPS_FIN_WAIT_1)
01858 sock->so_state = TCPS_TIME_WAIT;
01859 else
01860 sock->so_state = TCPS_CLOSED;
01861 NutTcpDiscardBuffers(sock);
01862 NutEventBroadcast(&sock->so_rx_tq);
01863 NutEventBroadcast(&sock->so_tx_tq);
01864 NutEventBroadcast(&sock->so_pc_tq);
01865 NutEventBroadcast(&sock->so_ac_tq);
01866 return 0;
01867 }
01868