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