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