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 s = ntohs(*((uint16_t*)&cp[2]));
00299 if (s < sock->so_mss)
00300 sock->so_mss = s;
00301 cp += TCPOLEN_MAXSEG;
00302 break;
00303
00304 default:
00305 cp += *(uint8_t*) (cp + 1);
00306 break;
00307 }
00308 }
00309 }
00310
00319 static void NutTcpProcessAppData(TCPSOCKET * sock, NETBUF * nb)
00320 {
00321
00322
00323
00324 if (sock->so_rx_buf) {
00325 NETBUF *nbp = sock->so_rx_buf;
00326
00327 while (nbp->nb_next)
00328 nbp = nbp->nb_next;
00329 nbp->nb_next = nb;
00330 } else
00331 sock->so_rx_buf = nb;
00332
00333
00334
00335
00336
00337 sock->so_rx_cnt += nb->nb_ap.sz;
00338 sock->so_rx_nxt += nb->nb_ap.sz;
00339
00340
00341
00342
00343 if (nb->nb_ap.sz >= sock->so_rx_win)
00344 sock->so_rx_win = 0;
00345 else
00346 sock->so_rx_win -= nb->nb_ap.sz;
00347
00348
00349
00350
00351
00352
00353 sock->so_tx_flags |= SO_ACK;
00354 if (nb->nb_next)
00355 nb->nb_next = 0;
00356 else
00357 sock->so_tx_flags |= SO_FORCE;
00358
00359 if (++sock->so_rx_apc > TCP_COLLECT_INADV) {
00360 NETBUF *nbq;
00361 int_fast8_t apc = sock->so_rx_apc;
00362 int cnt = sock->so_rx_cnt;
00363
00364 for (nbq = sock->so_rx_buf; nbq; nbq = nbq->nb_next) {
00365 if (nbq->nb_ap.sz < TCP_COLLECT_SLIMIT) {
00366 sock->so_rx_apc -= NutNetBufCollect(nbq, cnt);
00367 break;
00368 }
00369 if (--apc < 8) {
00370 break;
00371 }
00372 cnt -= nbq->nb_ap.sz;
00373 }
00374 }
00375 NutTcpOutput(sock, 0, 0);
00376 }
00377
00378
00379
00380
00381 static void NutTcpProcessSyn(TCPSOCKET * sock, IPHDR * ih, TCPHDR * th)
00382 {
00383 uint16_t mss;
00384 NUTDEVICE *dev;
00385 IFNET *nif;
00386
00387 sock->so_local_addr = ih->ip_dst;
00388 sock->so_remote_port = th->th_sport;
00389 sock->so_remote_addr = ih->ip_src;
00390
00391 sock->so_rx_nxt = sock->so_tx_wl1 = sock->so_rx_isn = ntohl(th->th_seq);
00392 sock->so_rx_nxt++;
00393 sock->so_tx_win = ntohs(th->th_win);
00394
00395
00396
00397
00398
00399
00400 if ((dev = NutIpRouteQuery(ih->ip_src, 0)) != 0) {
00401 nif = dev->dev_icb;
00402 mss = nif->if_mtu - sizeof(IPHDR) - sizeof(TCPHDR);
00403 if (sock->so_mss == 0 || sock->so_mss > mss)
00404 sock->so_mss = mss;
00405
00406
00407 if (sock->so_devobsz > sock->so_mss)
00408 sock->so_devobsz = sock->so_mss;
00409 }
00410 }
00411
00419 static int NutTcpProcessAck(TCPSOCKET * sock, TCPHDR * th, uint16_t length)
00420 {
00421 NETBUF *nb;
00422 uint32_t h_seq;
00423 uint32_t h_ack;
00424
00425
00426
00427
00428 h_ack = ntohl(th->th_ack);
00429 if (SeqIsAfter(h_ack, sock->so_tx_nxt)) {
00430 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438
00439 if (h_ack == sock->so_tx_una) {
00440 h_seq = ntohl(th->th_seq);
00441 if (SeqIsAfter(h_seq, sock->so_tx_wl1) || (h_seq == sock->so_tx_wl1 && !SeqIsAfter(sock->so_tx_wl2, h_ack))) {
00442 sock->so_tx_win = ntohs(th->th_win);
00443 sock->so_tx_wl1 = h_seq;
00444 sock->so_tx_wl2 = h_ack;
00445 }
00446 }
00447
00448
00449
00450
00451
00452 if (SeqIsAfter(sock->so_tx_una, h_ack)) {
00453 return 0;
00454 }
00455
00456
00457
00458
00459 if (h_ack == sock->so_tx_una) {
00460
00461
00462
00463
00464 if (sock->so_tx_nbq && length == 0 && (th->th_flags & (TH_SYN | TH_FIN)) == 0) {
00465
00466
00467
00468
00469 if (++sock->so_tx_dup >= 3) {
00470 sock->so_tx_dup = 0;
00471 #ifdef NUTDEBUG
00472 if (__tcp_trf & NET_DBG_SOCKSTATE)
00473 NutDumpTcpHeader(__tcp_trs, "RET", sock, sock->so_tx_nbq);
00474 #endif
00475
00476
00477
00478
00479 if (NutTcpStateRetranTimeout(sock))
00480 return -1;
00481 }
00482 }
00483 return 0;
00484 }
00485
00486
00487
00488
00489 sock->so_tx_dup = 0;
00490 sock->so_tx_una = h_ack;
00491
00492
00493
00494
00495
00496
00497 sock->so_tx_win = ntohs(th->th_win);
00498
00499
00500
00501
00502 if (sock->so_rtt_seq && SeqIsAfter(h_ack, sock->so_rtt_seq))
00503 NutTcpCalcRtt (sock);
00504 sock->so_rtt_seq = 0;
00505
00506
00507
00508 while ((nb = sock->so_tx_nbq) != 0) {
00509
00510 h_seq = ntohl(((TCPHDR *) (nb->nb_tp.vp))->th_seq) + nb->nb_ap.sz;
00511 if (((TCPHDR *) (nb->nb_tp.vp))->th_flags & (TH_SYN | TH_FIN)) {
00512 h_seq++;
00513 }
00514
00515 if (SeqIsAfter(h_seq, h_ack)) {
00516 break;
00517 }
00518 sock->so_tx_nbq = nb->nb_next;
00519 NutNetBufFree(nb);
00520 }
00521
00522
00523
00524
00525 if (sock->so_tx_nbq) {
00526 sock->so_retran_time = (uint16_t) NutGetMillis() | 1;
00527 } else {
00528 sock->so_retran_time = 0;
00529 }
00530 sock->so_retransmits = 0;
00531
00532 return 0;
00533 }
00534
00535
00536
00537
00538
00539
00540
00549 static int NutTcpStateChange(TCPSOCKET * sock, uint8_t state)
00550 {
00551 int rc = 0;
00552 ureg_t txf = 0;
00553
00554 switch (sock->so_state) {
00555
00556 case TCPS_ESTABLISHED:
00557 switch (state) {
00558 case TCPS_FIN_WAIT_1:
00559
00560
00561
00562 sock->so_tx_flags |= SO_FIN | SO_ACK;
00563 txf = 1;
00564
00565 #ifdef RTLCONNECTHACK
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 NutDelay(5);
00576 #endif
00577 break;
00578 case TCPS_CLOSE_WAIT:
00579
00580
00581
00582 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00583 txf = 1;
00584 break;
00585 default:
00586 rc = -1;
00587 break;
00588 }
00589 break;
00590
00591 case TCPS_LISTEN:
00592
00593
00594
00595 if (state == TCPS_SYN_RECEIVED) {
00596 sock->so_tx_flags |= SO_SYN | SO_ACK;
00597 txf = 1;
00598 #ifdef RTLCONNECTHACK
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 NutDelay(5);
00609 #endif
00610 } else
00611 rc = -1;
00612 break;
00613
00614 case TCPS_SYN_SENT:
00615 switch (state) {
00616 case TCPS_LISTEN:
00617
00618
00619
00620 break;
00621 case TCPS_SYN_RECEIVED:
00622
00623
00624
00625 sock->so_tx_flags |= SO_SYN | SO_ACK;
00626 txf = 1;
00627 break;
00628 case TCPS_ESTABLISHED:
00629
00630
00631
00632 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00633 txf = 1;
00634 break;
00635 default:
00636 rc = -1;
00637 break;
00638 }
00639 break;
00640
00641 case TCPS_SYN_RECEIVED:
00642 switch (state) {
00643 case TCPS_LISTEN:
00644
00645
00646
00647 break;
00648 case TCPS_ESTABLISHED:
00649
00650
00651
00652 break;
00653 case TCPS_FIN_WAIT_1:
00654
00655
00656
00657 sock->so_tx_flags |= SO_FIN;
00658 txf = 1;
00659 break;
00660 case TCPS_CLOSE_WAIT:
00661
00662
00663
00664 sock->so_tx_flags |= SO_FIN | SO_ACK;
00665 txf = 1;
00666 break;
00667 default:
00668 rc = -1;
00669 break;
00670 }
00671 break;
00672
00673 case TCPS_FIN_WAIT_1:
00674 switch (state) {
00675 case TCPS_FIN_WAIT_1:
00676 case TCPS_FIN_WAIT_2:
00677
00678
00679
00680 break;
00681 case TCPS_CLOSING:
00682
00683
00684
00685 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00686 txf = 1;
00687 break;
00688 case TCPS_TIME_WAIT:
00689
00690
00691
00692 break;
00693 default:
00694 rc = -1;
00695 break;
00696 }
00697 break;
00698
00699 case TCPS_FIN_WAIT_2:
00700
00701
00702
00703 if (state != TCPS_TIME_WAIT)
00704 rc = -1;
00705 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00706 txf = 1;
00707 break;
00708
00709 case TCPS_CLOSE_WAIT:
00710
00711
00712
00713 if (state == TCPS_LAST_ACK) {
00714 sock->so_tx_flags |= SO_FIN | SO_ACK;
00715 txf = 1;
00716 } else
00717 rc = -1;
00718 break;
00719
00720 case TCPS_CLOSING:
00721
00722
00723
00724 if (state != TCPS_TIME_WAIT)
00725 rc = -1;
00726 break;
00727
00728 case TCPS_LAST_ACK:
00729 rc = -1;
00730 break;
00731
00732 case TCPS_TIME_WAIT:
00733 rc = -1;
00734 break;
00735
00736 case TCPS_CLOSED:
00737 switch (state) {
00738 case TCPS_LISTEN:
00739
00740
00741
00742 break;
00743 case TCPS_SYN_SENT:
00744
00745
00746
00747 sock->so_tx_flags |= SO_SYN;
00748 txf = 1;
00749 break;
00750 default:
00751 rc = -1;
00752 break;
00753 }
00754 break;
00755 }
00756 #ifdef NUTDEBUG
00757 if (__tcp_trf & NET_DBG_SOCKSTATE) {
00758 fprintf(__tcp_trs, " %04x-", (unsigned int) sock);
00759 if (rc)
00760 NutDumpSockState(__tcp_trs, sock->so_state, "**ERR ", "**>");
00761 NutDumpSockState(__tcp_trs, state, "[>", "]");
00762 }
00763 #endif
00764
00765 if (rc == 0) {
00766 sock->so_state = state;
00767 if (txf && NutTcpOutput(sock, 0, 0)) {
00768 if (state == TCPS_SYN_SENT) {
00769 rc = -1;
00770 sock->so_last_error = EHOSTDOWN;
00771 NutEventPostAsync(&sock->so_ac_tq);
00772 }
00773 }
00774 if (state == TCPS_CLOSE_WAIT) {
00775
00776
00777
00778 NutEventBroadcast(&sock->so_rx_tq);
00779 NutEventBroadcast(&sock->so_pc_tq);
00780 NutEventBroadcast(&sock->so_ac_tq);
00781 }
00782 }
00783 return rc;
00784 }
00785
00786
00787
00788
00789
00798 int NutTcpStatePassiveOpenEvent(TCPSOCKET * sock)
00799 {
00800 if (sock->so_state != TCPS_CLOSED)
00801 return (sock->so_last_error = EISCONN);
00802
00803 NutTcpStateChange(sock, TCPS_LISTEN);
00804
00805 #if TCP_BACKLOG_MAX
00806 {
00807
00808
00809 NETBUF *nb = NutTcpBacklogCheck(sock->so_local_port);
00810 if (nb) {
00811 NutTcpInputOptions(sock, nb);
00812 NutTcpStateProcess(sock, nb);
00813
00814 return 0;
00815 }
00816 }
00817 if (NutEventWait(&sock->so_pc_tq, sock->so_read_to)) {
00818 sock->so_state = TCPS_CLOSED;
00819 return (sock->so_last_error = ETIMEDOUT);
00820 }
00821 #else
00822
00823
00824
00825
00826 NutEventWait(&sock->so_pc_tq, 0);
00827 #endif
00828
00829 return 0;
00830 }
00831
00842 int NutTcpStateActiveOpenEvent(TCPSOCKET * sock)
00843 {
00844
00845
00846
00847
00848 NutTcpStateChange(sock, TCPS_SYN_SENT);
00849
00850
00851
00852
00853 if(sock->so_state == TCPS_SYN_SENT)
00854 NutEventWait(&sock->so_ac_tq, 0);
00855
00856 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT)
00857 return -1;
00858
00859 return 0;
00860 }
00861
00874 int NutTcpStateCloseEvent(TCPSOCKET * sock)
00875 {
00876 if (sock == 0)
00877 return -1;
00878
00879 NutThreadYield();
00880
00881 switch (sock->so_state) {
00882 case TCPS_LISTEN:
00883 case TCPS_SYN_SENT:
00884 case TCPS_CLOSED:
00885
00886
00887
00888 NutTcpDestroySocket(sock);
00889 break;
00890
00891 case TCPS_SYN_RECEIVED:
00892 case TCPS_ESTABLISHED:
00893
00894
00895
00896
00897 NutTcpStateChange(sock, TCPS_FIN_WAIT_1);
00898 break;
00899
00900 case TCPS_CLOSE_WAIT:
00901
00902
00903
00904
00905 NutTcpStateChange(sock, TCPS_LAST_ACK);
00906 break;
00907
00908 case TCPS_FIN_WAIT_1:
00909 case TCPS_FIN_WAIT_2:
00910 case TCPS_CLOSING:
00911 case TCPS_LAST_ACK:
00912 case TCPS_TIME_WAIT:
00913 sock->so_last_error = EALREADY;
00914 return -1;
00915
00916 default:
00917 sock->so_last_error = ENOTCONN;
00918 return -1;
00919 }
00920 return 0;
00921 }
00922
00929 int NutTcpStateWindowEvent(TCPSOCKET * sock)
00930 {
00931 if (sock == 0)
00932 return -1;
00933 sock->so_tx_flags |= SO_ACK | SO_FORCE;
00934 NutTcpOutput(sock, 0, 0);
00935
00936 return 0;
00937 }
00938
00939
00940
00941
00942
00954 int NutTcpStateRetranTimeout(TCPSOCKET * sock)
00955 {
00956 NETBUF *so_tx_next;
00957 if (sock->so_retransmits++ > TCP_RETRIES_MAX)
00958 {
00959
00960 NutTcpAbortSocket(sock, ETIMEDOUT);
00961 return -1;
00962 } else {
00963 #ifdef NUTDEBUG
00964 if (__tcp_trf & NET_DBG_SOCKSTATE)
00965 NutDumpTcpHeader(__tcp_trs, "RET", sock, sock->so_tx_nbq);
00966 #endif
00967
00968
00969
00970
00971 so_tx_next = sock->so_tx_nbq->nb_next;
00972 if (NutIpOutput(IPPROTO_TCP, sock->so_remote_addr, sock->so_tx_nbq)) {
00973
00974 sock->so_tx_nbq = so_tx_next;
00975
00976 NutTcpAbortSocket(sock, ENETDOWN);
00977 return -1;
00978 } else {
00979
00980 sock->so_retran_time = (uint16_t) NutGetMillis() | 1;
00981 return 0;
00982 }
00983 }
00984 }
00985
00986
00987
00988
00989
00990
01000 static void NutTcpStateListen(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01001 {
01002
01003
01004
01005
01006 if ((flags & (TH_SYN | TH_ACK | TH_RST)) == TH_SYN) {
01007 NutTcpProcessSyn(sock, nb->nb_nw.vp, th);
01008 NutTcpStateChange(sock, TCPS_SYN_RECEIVED);
01009 NutNetBufFree(nb);
01010 } else
01011 NutTcpReject(nb);
01012 }
01013
01014
01023 static void NutTcpStateSynSent(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01024 {
01025
01026
01027
01028 if (flags & TH_ACK) {
01029 if (!SeqIsBetween(ntohl(th->th_ack), sock->so_tx_isn + 1, sock->so_tx_nxt)) {
01030 NutTcpReject(nb);
01031 return;
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040 if (flags & TH_RST) {
01041 if (flags & TH_ACK) {
01042
01043
01044
01045 NutTcpAbortSocket(sock, ECONNREFUSED);
01046 }
01047 NutNetBufFree(nb);
01048 return;
01049 }
01050
01051
01052
01053
01054
01055
01056 if (flags & TH_SYN) {
01057 NutTcpProcessSyn(sock, nb->nb_nw.vp, th);
01058 if (flags & TH_ACK) {
01059 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01060 NutTcpStateChange(sock, TCPS_ESTABLISHED);
01061
01062 NutEventPost(&sock->so_ac_tq);
01063 } else {
01064 NutTcpStateChange(sock, TCPS_SYN_RECEIVED);
01065 }
01066 }
01067 NutNetBufFree(nb);
01068 }
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 static void NutTcpStateSynReceived(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01082 {
01083
01084
01085
01086
01087 if (flags & TH_RST) {
01088 if (sock->so_pc_tq)
01089 NutTcpStateChange(sock, TCPS_LISTEN);
01090 else
01091 NutTcpAbortSocket(sock, ECONNREFUSED);
01092 NutNetBufFree(nb);
01093 sock->so_retran_time = 0;
01094 NutTcpDiscardBuffers(sock);
01095 return;
01096 }
01097
01098
01099
01100
01101 if (flags & TH_SYN) {
01102 NutTcpReject(nb);
01103 return;
01104 }
01105
01106
01107
01108
01109 if ((flags & TH_ACK) == 0) {
01110 NutNetBufFree(nb);
01111 return;
01112 }
01113
01114
01115
01116
01117 if (!SeqIsBetween(ntohl(th->th_ack), sock->so_tx_una + 1, sock->so_tx_nxt)) {
01118 NutTcpReject(nb);
01119 return;
01120 }
01121
01122
01123 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01124
01125
01126
01127
01128
01129
01130
01131 if (nb->nb_ap.sz)
01132 NutTcpProcessAppData(sock, nb);
01133 else
01134 NutNetBufFree(nb);
01135
01136
01137
01138
01139 if (flags & TH_FIN) {
01140 sock->so_rx_nxt++;
01141 NutTcpStateChange(sock, TCPS_CLOSE_WAIT);
01142 } else {
01143 NutTcpStateChange(sock, TCPS_ESTABLISHED);
01144 NutEventPost(&sock->so_pc_tq);
01145 NutEventPost(&sock->so_ac_tq);
01146 }
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 static void NutTcpStateEstablished(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01164 {
01165 if (flags & TH_RST) {
01166 NutNetBufFree(nb);
01167 NutTcpAbortSocket(sock, ECONNRESET);
01168 return;
01169 }
01170
01171
01172
01173
01174
01175 if (flags & TH_SYN) {
01176 if (ntohl(th->th_seq) != sock->so_rx_isn)
01177 NutTcpReject(nb);
01178 else
01179 NutNetBufFree(nb);
01180 return;
01181 }
01182
01183
01184
01185
01186 if ((flags & TH_ACK) == 0) {
01187 NutNetBufFree(nb);
01188 return;
01189 }
01190
01191 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01192
01193
01194
01195
01196
01197
01198
01199 if (SeqIsAfter(ntohl(th->th_seq),sock->so_rx_nxt)) {
01200 NETBUF *nbq;
01201 NETBUF **nbqp;
01202 TCPHDR *thq;
01203 uint32_t th_seq;
01204 uint32_t thq_seq;
01205
01206 if (nb->nb_ap.sz) {
01207
01208
01209 tcp_adv_cnt += nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01210 if (tcp_adv_cnt > tcp_adv_max) {
01211
01212 NutNetBufFree(nb);
01213 tcp_adv_cnt -= nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01214 } else {
01215 nbq = sock->so_rx_nbq;
01216 nbqp = &sock->so_rx_nbq;
01217 while (nbq) {
01218 thq = (TCPHDR *) (nbq->nb_tp.vp);
01219 th_seq = ntohl(th->th_seq);
01220 thq_seq = ntohl(thq->th_seq);
01221 if (SeqIsAfter(thq_seq, th_seq)) {
01222 *nbqp = nb;
01223 nb->nb_next = nbq;
01224 break;
01225 }
01226 if (th_seq == thq_seq) {
01227 NutNetBufFree(nb);
01228 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01229 NutTcpOutput(sock, 0, 0);
01230 return;
01231 }
01232 nbqp = &nbq->nb_next;
01233 nbq = nbq->nb_next;
01234 }
01235 if (nbq == 0) {
01236 *nbqp = nb;
01237 nb->nb_next = 0;
01238 }
01239 }
01240 } else
01241 NutNetBufFree(nb);
01242
01243 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01244 NutTcpOutput(sock, 0, 0);
01245 return;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255 if (ntohl(th->th_seq) != sock->so_rx_nxt) {
01256 sock->so_tx_flags |= SO_ACK | SO_FORCE;
01257
01258 sock->so_oos_drop++;
01259 NutNetBufFree(nb);
01260 NutTcpOutput(sock, 0, 0);
01261 }
01262
01263
01264
01265
01266 else if (nb->nb_ap.sz) {
01267 NutTcpProcessAppData(sock, nb);
01268
01269
01270
01271 while ((nb = sock->so_rx_nbq) != 0) {
01272 th = (TCPHDR *) (nb->nb_tp.vp);
01273 if (SeqIsAfter(ntohl(th->th_seq), sock->so_rx_nxt))
01274 break;
01275 sock->so_rx_nbq = nb->nb_next;
01276
01277
01278 tcp_adv_cnt -= nb->nb_dl.sz + sizeof(IPHDR) + sizeof (TCPHDR) + nb->nb_ap.sz;
01279 if (ntohl(th->th_seq) == sock->so_rx_nxt) {
01280 NutTcpProcessAppData(sock, nb);
01281 flags |= th->th_flags;
01282 } else
01283 NutNetBufFree(nb);
01284 }
01285
01286 NutEventPost(&sock->so_rx_tq);
01287 } else {
01288 NutNetBufFree(nb);
01289
01290
01291 }
01292 if (flags & TH_FIN) {
01293
01294 sock->so_rx_nxt++;
01295 NutTcpStateChange(sock, TCPS_CLOSE_WAIT);
01296 }
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 static void NutTcpStateFinWait1(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01315 {
01316
01317 if (flags & TH_RST) {
01318 NutNetBufFree(nb);
01319 NutTcpDestroySocket(sock);
01320 return;
01321 }
01322
01323
01324
01325
01326 if (flags & TH_SYN) {
01327 NutTcpReject(nb);
01328 return;
01329 }
01330
01331
01332
01333
01334 if ((flags & TH_ACK) == 0) {
01335 NutNetBufFree(nb);
01336 return;
01337 }
01338
01339
01340
01341
01342
01343 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01344
01345
01346
01347
01348
01349 if (sock->so_tx_nxt == sock->so_tx_una) {
01350
01351 NutTcpStateChange(sock, TCPS_FIN_WAIT_2);
01352 }
01353
01354
01355
01356
01357
01358 if (nb->nb_ap.sz) {
01359 NutTcpProcessAppData(sock, nb);
01360
01361 NutEventPost(&sock->so_rx_tq);
01362 }
01363 else
01364 NutNetBufFree(nb);
01365
01366 if (flags & TH_FIN) {
01367 sock->so_rx_nxt++;
01368
01369
01370
01371 sock->so_time_wait = 0;
01372
01373 if (sock->so_state == TCPS_FIN_WAIT_2)
01374 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01375 else
01376 NutTcpStateChange(sock, TCPS_CLOSING);
01377 }
01378 }
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 static void NutTcpStateFinWait2(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01394 {
01395
01396 if (flags & TH_RST) {
01397 NutNetBufFree(nb);
01398 NutTcpDestroySocket(sock);
01399 return;
01400 }
01401
01402
01403
01404
01405 if (flags & TH_SYN) {
01406 NutTcpReject(nb);
01407 return;
01408 }
01409
01410
01411
01412
01413 if ((flags & TH_ACK) == 0) {
01414 NutNetBufFree(nb);
01415 return;
01416 }
01417
01418
01419
01420
01421
01422
01423 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01424
01425
01426
01427 if (nb->nb_ap.sz) {
01428 NutTcpProcessAppData(sock, nb);
01429
01430 NutEventPost(&sock->so_rx_tq);
01431 }
01432 else
01433 NutNetBufFree(nb);
01434
01435 if (flags & TH_FIN) {
01436 sock->so_rx_nxt++;
01437 sock->so_time_wait = 0;
01438
01439 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01440 }
01441 }
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 static void NutTcpStateCloseWait(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01454 {
01455
01456 if (flags & TH_RST) {
01457 NutNetBufFree(nb);
01458 NutTcpAbortSocket(sock, ECONNRESET);
01459 return;
01460 }
01461
01462
01463
01464
01465 if (flags & TH_SYN) {
01466 NutTcpReject(nb);
01467 return;
01468 }
01469
01470
01471
01472
01473 if ((flags & TH_ACK) == 0) {
01474 NutNetBufFree(nb);
01475 return;
01476 }
01477
01478 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01479
01480 NutNetBufFree(nb);
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495 static void NutTcpStateClosing(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01496 {
01497
01498 if (flags & TH_RST) {
01499 NutNetBufFree(nb);
01500 NutTcpDestroySocket(sock);
01501 return;
01502 }
01503
01504
01505
01506
01507 if (flags & TH_SYN) {
01508 NutTcpReject(nb);
01509 return;
01510 }
01511
01512
01513
01514
01515 if ((flags & TH_ACK) == 0) {
01516 NutNetBufFree(nb);
01517 return;
01518 }
01519
01520 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01521
01522
01523
01524
01525 if (sock->so_tx_nxt == sock->so_tx_una) {
01526 sock->so_time_wait = 0;
01527 NutTcpStateChange(sock, TCPS_TIME_WAIT);
01528
01529 }
01530
01531
01532 NutNetBufFree(nb);
01533 }
01534
01549 static void NutTcpStateLastAck(TCPSOCKET * sock, uint8_t flags, TCPHDR * th, NETBUF * nb)
01550 {
01551
01552 if (flags & TH_RST) {
01553 NutNetBufFree(nb);
01554 NutTcpDestroySocket(sock);
01555 return;
01556 }
01557
01558
01559
01560
01561 if (flags & TH_SYN) {
01562 NutTcpReject(nb);
01563 return;
01564 }
01565
01566
01567
01568
01569 if ((flags & TH_ACK) == 0) {
01570 NutNetBufFree(nb);
01571 return;
01572 }
01573
01574 NutTcpProcessAck(sock, th, nb->nb_ap.sz);
01575 NutNetBufFree(nb);
01576
01577 if (sock->so_tx_nxt == sock->so_tx_una)
01578 NutTcpDestroySocket(sock);
01579
01580 }
01581
01592 static void NutTcpStateProcess(TCPSOCKET * sock, NETBUF * nb)
01593 {
01594 uint32_t tx_win;
01595 uint32_t tx_una;
01596 TCPHDR *th = (TCPHDR *) nb->nb_tp.vp;
01597 uint8_t flags = th->th_flags;
01598
01599 #ifdef NUTDEBUG
01600 if (__tcp_trf & NET_DBG_SOCKSTATE) {
01601 fprintf(__tcp_trs, " %04x-", (unsigned int) sock);
01602 NutDumpSockState(__tcp_trs, sock->so_state, "[", ">]");
01603 }
01604 #endif
01605 switch (sock->so_state) {
01606
01607 case TCPS_ESTABLISHED:
01608 tx_win = sock->so_tx_win;
01609 tx_una = sock->so_tx_una;
01610 NutTcpStateEstablished(sock, flags, th, nb);
01611
01612 if(sock->so_state != TCPS_ESTABLISHED ||
01613 sock->so_tx_win > tx_win ||
01614 sock->so_tx_una != tx_una) {
01615 NutEventBroadcast(&sock->so_tx_tq);
01616 }
01617 break;
01618 case TCPS_LISTEN:
01619 NutTcpStateListen(sock, flags, th, nb);
01620 break;
01621 case TCPS_SYN_SENT:
01622 NutTcpStateSynSent(sock, flags, th, nb);
01623 break;
01624 case TCPS_SYN_RECEIVED:
01625 NutTcpStateSynReceived(sock, flags, th, nb);
01626 break;
01627 case TCPS_FIN_WAIT_1:
01628 NutTcpStateFinWait1(sock, flags, th, nb);
01629 break;
01630 case TCPS_FIN_WAIT_2:
01631 NutTcpStateFinWait2(sock, flags, th, nb);
01632 break;
01633 case TCPS_CLOSE_WAIT:
01634 NutTcpStateCloseWait(sock, flags, th, nb);
01635 break;
01636 case TCPS_CLOSING:
01637 NutTcpStateClosing(sock, flags, th, nb);
01638 break;
01639 case TCPS_LAST_ACK:
01640 NutTcpStateLastAck(sock, flags, th, nb);
01641 break;
01642 case TCPS_TIME_WAIT:
01643
01644
01645
01646 NutNetBufFree(nb);
01647 break;
01648 case TCPS_CLOSED:
01649
01650
01651
01652 NutTcpReject(nb);
01653 break;
01654 default:
01655 NutNetBufFree(nb);
01656 break;
01657 }
01658 }
01659
01666 THREAD(NutTcpSm, arg)
01667 {
01668 NETBUF *nb;
01669 NETBUF *nbx;
01670 TCPHDR *th;
01671 IPHDR *ih;
01672 TCPSOCKET *sock;
01673 uint8_t tac = 0;
01674
01675
01676
01677
01678
01679 NutThreadSetPriority (32);
01680
01681 for (;;) {
01682 if (++tac > 3 || NutEventWait(&tcp_in_rdy, 200)) {
01683 tac = 0;
01684
01685 #if TCP_BACKLOG_MAX
01686
01687
01688
01689
01690
01691 nb = NutTcpBacklogTimer();
01692 if (nb) {
01693 NutTcpReject(nb);
01694 }
01695 #endif
01696
01697 for (sock = tcpSocketList; sock; sock = sock->so_next) {
01698
01699
01700
01701
01702 if (sock->so_tx_flags & SO_ACK) {
01703 sock->so_tx_flags |= SO_FORCE;
01704 NutTcpOutput(sock, 0, 0);
01705 }
01706
01707
01708
01709
01710 if (sock->so_tx_nbq && sock->so_retran_time) {
01711 if ((uint16_t)((uint16_t)NutGetMillis() - (sock->so_retran_time & ~1)) >= sock->so_rtto) {
01712 NutTcpStateRetranTimeout(sock);
01713 }
01714 }
01715
01716
01717
01718
01719
01720 if (sock->so_state == TCPS_TIME_WAIT || sock->so_state == TCPS_FIN_WAIT_2) {
01721 if (sock->so_time_wait++ >= 9) {
01722 NutTcpDestroySocket(sock);
01723 break;
01724 }
01725 }
01726
01727
01728
01729
01730 else if (sock->so_state == TCPS_SYN_RECEIVED) {
01731 if (sock->so_time_wait++ >= 45) {
01732 sock->so_state = TCPS_LISTEN;
01733 sock->so_time_wait = 0;
01734 }
01735 }
01736 }
01737 } else {
01738 nb = tcp_in_nbq;
01739 tcp_in_nbq = 0;
01740 tcp_in_cnt = 0;
01741 while (nb) {
01742 ih = (IPHDR *) nb->nb_nw.vp;
01743 th = (TCPHDR *) nb->nb_tp.vp;
01744 sock = NutTcpFindSocket(th->th_dport, th->th_sport, ih->ip_src);
01745 #ifdef NUTDEBUG
01746 if (__tcp_trf & NET_DBG_SOCKSTATE)
01747 NutDumpTcpHeader(__tcp_trs, " IN", sock, nb);
01748 #endif
01749 nbx = nb->nb_next;
01750
01751 if (sock) {
01752 NutTcpInputOptions(sock, nb);
01753 NutTcpStateProcess(sock, nb);
01754 }
01755 #if TCP_BACKLOG_MAX
01756
01757 else if (NutTcpBacklogAdd(nb) == 0) {
01758 }
01759 #endif
01760
01761 else {
01762 NutTcpReject(nb);
01763 }
01764 nb = nbx;
01765 }
01766 }
01767 }
01768 }
01769
01781 void NutTcpStateMachine(NETBUF * nb)
01782 {
01783 NETBUF *nbp;
01784 uint16_t size;
01785
01786 nb->nb_next = 0;
01787
01788
01789
01790
01791
01792
01793
01794 if (tcpThread == 0) {
01795 NutTcpReject(nb);
01796 return;
01797 }
01798
01799 if ((nbp = tcp_in_nbq) == 0) {
01800 tcp_in_nbq = nb;
01801 NutEventPost(&tcp_in_rdy);
01802 } else {
01803 size = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
01804 if (tcp_in_cnt + size + 2048 < NutHeapAvailable()) {
01805 tcp_in_cnt += size;
01806 while (nbp->nb_next)
01807 nbp = nbp->nb_next;
01808 nbp->nb_next = nb;
01809 NutEventPost(&tcp_in_rdy);
01810 } else
01811 NutNetBufFree(nb);
01812 }
01813 }
01814
01823 int NutTcpInitStateMachine(void)
01824 {
01825 if (tcpThread == 0 && (tcpThread = NutThreadCreate("tcpsm", NutTcpSm, NULL,
01826 (NUT_THREAD_TCPSMSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) == 0)
01827 return -1;
01828 return 0;
01829 }
01830
01844 int NutTcpAbortSocket(TCPSOCKET * sock, uint16_t last_error)
01845 {
01846 sock->so_last_error = last_error;
01847 sock->so_retran_time = 0;
01848 sock->so_time_wait = 0;
01849
01850
01851
01852
01853
01854 if (sock->so_state >= TCPS_FIN_WAIT_1)
01855 sock->so_state = TCPS_TIME_WAIT;
01856 else
01857 sock->so_state = TCPS_CLOSED;
01858 NutTcpDiscardBuffers(sock);
01859 NutEventBroadcast(&sock->so_rx_tq);
01860 NutEventBroadcast(&sock->so_tx_tq);
01861 NutEventBroadcast(&sock->so_pc_tq);
01862 NutEventBroadcast(&sock->so_ac_tq);
01863 return 0;
01864 }
01865