Subversion Repositories Kolibri OS

Rev

Rev 837 | Rev 914 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  TCP.INC                                                     ;;
  7. ;;                                                              ;;
  8. ;;  TCP Processes for Menuet OS  TCP/IP stack                   ;;
  9. ;;                                                              ;;
  10. ;;  Version 0.6  4th July 2004                                  ;;
  11. ;;                                                              ;;
  12. ;;  Copyright 2002 Mike Hibbett, mikeh@oceanfree.net            ;;
  13. ;;                                                              ;;
  14. ;;  See file COPYING for details                                ;;
  15. ;;  v0.6 : Added reset handling in the established state        ;;
  16. ;;         Added a timer per socket to allow delays when        ;;
  17. ;;         rx window gets below 1KB                             ;;
  18. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  19.  
  20. $Revision: 871 $
  21.  
  22.  
  23. ; TCP TCB states
  24. TCB_LISTEN         equ        1
  25. TCB_SYN_SENT       equ        2
  26. TCB_SYN_RECEIVED   equ        3
  27. TCB_ESTABLISHED   equ        4
  28. TCB_FIN_WAIT_1     equ        5
  29. TCB_FIN_WAIT_2     equ        6
  30. TCB_CLOSE_WAIT     equ        7
  31. TCB_CLOSING       equ        8
  32. TCB_LAST_ACK       equ        9
  33. TCB_TIME_WAIT     equ        10
  34. TCB_CLOSED         equ        11
  35.  
  36. TWOMSL             equ     10      ; # of secs to wait before closing socket
  37.  
  38. TCP_RETRIES         equ         5               ; Number of times to resend a packet
  39. TCP_TIMEOUT         equ         10              ; resend if not replied to in x hs
  40.  
  41. ;*******************************************************************
  42. ;   Interface
  43. ;
  44. ;       tcp_tx_handler      Handles the TCP transmit queue
  45. ;       tcp_rx              The protocol handler for received data
  46. ;       buildTCPPacket      fills in the packet headers and data
  47. ;       tcpStateMachine     Main state machine for received TCP packets
  48. ;       tcp_tcb_handler     1s timer, to erase tcb's in TIME_WAIT state
  49. ;
  50. ;*******************************************************************
  51.  
  52.  
  53. ;   TCP Payload ( Data field in IP datagram )
  54. ;
  55. ;    0                   1                   2                   3
  56. ;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  57. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  58. ;20 |          Source Port          |       Destination Port        |
  59. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  60. ;24 |                        Sequence Number                        |
  61. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  62. ;28 |                    Acknowledgment Number                      |
  63. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64. ;32 |  Data |           |U|A|P|R|S|F|                               |
  65. ;   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
  66. ;   |       |           |G|K|H|T|N|N|                               |
  67. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  68. ;36 |           Checksum            |         Urgent Pointer        |
  69. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  70. ;40 |                    Options                    |    Padding    |
  71. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  72. ;   |                             data
  73.  
  74.  
  75. struc TCP_PACKET
  76. {  .SourcePort       dw  ?  ;+00
  77.    .DestinationPort  dw  ?  ;+02
  78.    .SequenceNumber   dd  ?  ;+04
  79.    .AckNumber        dd  ?  ;+08
  80.    .DataOffset       db  ?  ;+12 - DataOffset[0-3 bits] and Reserved[4-7]
  81.    .Flags            db  ?  ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
  82.    .Window           dw  ?  ;+14
  83.    .Checksum         dw  ?  ;+16
  84.    .UrgentPointer    dw  ?  ;+18
  85.    .Options          rb  3  ;+20
  86.    .Padding          db  ?  ;+23
  87.    .Data             db  ?  ;+24
  88. }
  89.  
  90. virtual at 0
  91.   TCP_PACKET TCP_PACKET
  92. end virtual
  93.  
  94.  
  95.  
  96. ;***************************************************************************
  97. ;   Function
  98. ;      tcp_tcb_handler
  99. ;
  100. ;   Description
  101. ;       Handles sockets in the timewait state, closing them
  102. ;       when the TCB timer expires
  103. ;
  104. ;***************************************************************************
  105. tcp_tcb_handler:
  106.     ; scan through all the sockets, decrementing active timers
  107.  
  108.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  109.     mov     ecx, NUM_SOCKETS
  110.  
  111. tth1:
  112.     sub     eax, SOCKETBUFFSIZE
  113.     cmp     [eax + sockets + 32], dword 0
  114.     jne     tth2
  115.  
  116. tth1a:
  117.     cmp     [eax + sockets + 72], dword 0
  118.     jne     tth4
  119.  
  120.     loop    tth1
  121.     ret
  122.  
  123. tth2:
  124.     ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
  125.     pusha
  126.     dec     dword [eax + sockets + 32]
  127.     cmp     [eax + sockets + 32], dword 0
  128.     jne     tth3
  129.  
  130.     cmp     [eax + sockets + 28], dword TCB_TIME_WAIT
  131.     jne     tth3
  132.  
  133.     ; OK, delete socket
  134.     mov     edi, eax
  135.     add     edi, sockets
  136.  
  137.     xor     eax, eax
  138.     mov     ecx, SOCKETHEADERSIZE
  139.     cld
  140.     rep     stosb
  141.  
  142. tth3:
  143.     popa
  144.  
  145.     jmp     tth1a
  146.  
  147.     loop    tth1
  148.     ret
  149.  
  150.     ; TODO - prove it works!
  151. tth4:
  152.     dec     dword [eax + sockets + 72]
  153.     loop    tth1
  154.     ret
  155.  
  156.  
  157.  
  158.  
  159. tth_exit:
  160.     ret
  161.  
  162.  
  163. ;***************************************************************************
  164. ;   Function
  165. ;      tcp_tx_handler
  166. ;
  167. ;   Description
  168. ;       Handles queued TCP data
  169. ;       This is a kernel function, called by stack_handler
  170. ;
  171. ;***************************************************************************
  172. tcp_tx_handler:
  173.     ; decrement all resend buffers timers. If they
  174.     ; expire, queue them for sending, and restart the timer.
  175.     ; If the retries counter reach 0, delete the entry
  176.  
  177.     mov     esi, resendQ
  178.     mov     ecx, 0
  179.  
  180. tth001:
  181.     cmp     ecx, NUMRESENDENTRIES
  182.     je      tth003              ; None left
  183.     cmp     [esi], byte 0xFF
  184.     jne     tth002              ; found one
  185.     inc     ecx
  186.     add     esi, 4
  187.     jmp     tth001
  188.  
  189. tth002:
  190.     ; we have one. decrement it's timer by 1
  191.     dec     word [esi+2]
  192.     mov     ax, [esi+2]
  193.     cmp     ax, 0
  194.     je      tth002a
  195.     inc     ecx
  196.     add     esi, 4
  197.     jmp     tth001              ; Timer not zero, so move on
  198.  
  199. tth002a:
  200.     mov     bl, 0xff
  201.     ; restart timer, and decrement retries
  202.     ; After the first resend, back of on next, by a factor of 5
  203.     mov     [esi+2], word TCP_TIMEOUT * 5
  204.     dec     byte [esi+1]
  205.     mov     al, [esi+1]
  206.     cmp     al, 0
  207.     jne     tth004
  208.  
  209.     ; retries now 0, so delete from queue
  210.     xchg     [esi], bl
  211. tth004:
  212.  
  213.     ; resend packet
  214.     pusha
  215.  
  216.     mov     eax, EMPTY_QUEUE
  217.     call    dequeue
  218.     cmp     ax, NO_BUFFER
  219.     jne      tth004z
  220.  
  221.     ; TODO - try again in 10ms.
  222.     cmp     bl, 0xff
  223.     jne     tth004za
  224.     mov     [esi], bl
  225.  
  226. tth004za:
  227.     ; Mark it to expire in 10ms - 1 tick
  228.     mov     [esi+1], byte 1
  229.     mov     [esi+2], word 1
  230.     jmp     tth005
  231.  
  232. tth004z:
  233.     ; we have a buffer # in ax
  234.  
  235.     push    eax
  236.     push    ecx
  237.     mov     ecx, IPBUFFSIZE
  238.     mul     ecx
  239.     add     eax, IPbuffs
  240.  
  241.     ; we have the buffer address in eax
  242.     mov     edi, eax
  243.     pop     ecx
  244.     ; get resend data address
  245.     inc     ecx
  246.     ; Now get buffer location, and copy buffer across. argh! more copying,,
  247.     mov     esi, resendBuffer - IPBUFFSIZE
  248. tth004a:
  249.     add     esi, IPBUFFSIZE
  250.     loop    tth004a
  251.  
  252.     ; we have resend buffer location in esi
  253.     mov     ecx, IPBUFFSIZE
  254.  
  255.     ; copy data across
  256.     cld
  257.     rep     movsb
  258.  
  259.     ; queue packet
  260.  
  261.  
  262.  
  263.     mov     eax, NET1OUT_QUEUE
  264.  
  265.     mov     edx, [stack_ip]
  266.     mov     ecx, [ edi + 16 ]
  267.     cmp     edx, ecx
  268.     jne     tth004b
  269.     mov     eax, IPIN_QUEUE
  270.  
  271. tth004b:
  272.     pop     ebx
  273.  
  274.     call    queue
  275.  
  276.  
  277. tth005:
  278.     popa
  279.  
  280.     inc     ecx
  281.     add     esi, 4
  282.     jmp     tth001
  283.  
  284. tth003:
  285.     ret
  286.  
  287.  
  288.  
  289.  
  290. ;***************************************************************************
  291. ;   Function
  292. ;      tcp_rx
  293. ;
  294. ;   Description
  295. ;       TCP protocol handler
  296. ;       This is a kernel function, called by ip_rx
  297. ;       IP buffer address given in edx
  298. ;          IP buffer number in eax
  299. ;          Free up (or re-use) IP buffer when finished
  300. ;
  301. ;***************************************************************************
  302. tcp_rx:
  303.     ; The process is as follows.
  304.     ; Look for a socket with matching remote IP, remote port, local port
  305.     ; if not found, then
  306.     ; look for remote IP + local port match ( where sockets remote port = 0)
  307.     ; if not found, then
  308.     ; look for a socket where local socket port == IP packets remote port
  309.     ; where sockets remote port, remote IP = 0
  310.     ; discard if not found
  311.     ; Call sockets tcbStateMachine, with pointer to packet.
  312.     ; the state machine will not delete the packet, so do that here.
  313.  
  314.     push        eax
  315.  
  316.     ; Look for a socket where
  317.     ; IP Packet TCP Destination Port = local Port
  318.     ; IP Packet SA = Remote IP
  319.     ; IP Packet TCP Source Port = remote Port
  320.  
  321.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  322.     mov     ecx, NUM_SOCKETS
  323. ss1:
  324.     sub     eax, SOCKETBUFFSIZE
  325.     movzx   ebx, word [edx + 22]     ; get the dest. port from the TCP hdr
  326.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  327.     jnz     nxttst1                        ; different - try next socket
  328.  
  329.     movzx   ebx, word [edx + 20]       ; get the source port from the TCP hdr
  330.     cmp     [eax + sockets + 20], bx ; compare with socket's remote port
  331.     jnz     nxttst1                        ; different - try next socket
  332.  
  333.  
  334.     mov     ebx, [edx + 12]           ; get the source IP Addr from the IP hdr
  335.     cmp     [eax + sockets + 16], ebx ; compare with socket's remote IP
  336.     jnz     nxttst1                        ; different - try next socket
  337.  
  338.     ; We have a complete match - use this socket
  339.     jmp     tcprx_001
  340.  
  341. nxttst1:
  342.     loop    ss1                     ; Return back if no match
  343.  
  344.     ; If we got here, there was no match
  345.     ; Look for a socket where
  346.     ; IP Packet TCP Destination Port = local Port
  347.     ; IP Packet SA = Remote IP
  348.     ; socket remote Port = 0
  349.  
  350.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  351.     mov     ecx, NUM_SOCKETS
  352.  
  353. ss2:
  354.     sub     eax, SOCKETBUFFSIZE
  355.  
  356.     movzx   ebx, word [edx + 22]     ; get the dest. port from the TCP hdr
  357.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  358.     jnz     nxttst2                        ; different - try next socket
  359.  
  360.     mov     ebx, [edx + 12]          ; get the source IP Addr from the IP hdr
  361.     cmp     [eax + sockets + 16], ebx ; compare with socket's remote IP
  362.     jnz     nxttst2                        ; different - try next socket
  363.  
  364.     mov     ebx, 0
  365.     cmp     [eax + sockets + 20], bx ; only match a remote socket of 0
  366.     jnz     nxttst2                        ; different - try next socket
  367.  
  368.     ; We have a complete match - use this socket
  369.     jmp     tcprx_001
  370.  
  371. nxttst2:
  372.     loop    ss2                     ; Return back if no match
  373.  
  374.     ; If we got here, there was no match
  375.     ; Look for a socket where
  376.     ; IP Packet TCP Destination Port = local Port
  377.     ; socket Remote IP = 0
  378.     ; socket remote Port = 0
  379.  
  380.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  381.     mov     ecx, NUM_SOCKETS
  382.  
  383. ss3:
  384.     sub     eax, SOCKETBUFFSIZE
  385.  
  386.     movzx   ebx, word [edx + 22]     ; get destination port from the TCP hdr
  387.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  388.     jnz     nxttst3                        ; different - try next socket
  389.  
  390.     mov     ebx, 0
  391.     cmp     [eax + sockets + 20], bx ; only match a remote socket of 0
  392.     jnz     nxttst3                        ; different - try next socket
  393.  
  394.     mov     ebx, 0
  395.     cmp     [eax + sockets + 16], ebx ; only match a socket remote IP of 0
  396.     jnz     nxttst3                        ; different - try next socket
  397.  
  398.     ; We have a complete match - use this socket
  399.     jmp     tcprx_001
  400.  
  401. nxttst3:
  402.     loop    ss3                     ; Return back if no match
  403.  
  404.     ; If we got here, we need to reject the packet
  405.     inc     dword [dumped_rx_count]
  406.     jmp     tcprx_exit
  407.  
  408. tcprx_001:
  409.     ; We have a valid socket/TCB, so call the TCB State Machine for that skt.
  410.     ; socket is pointed to by [eax + sockets]
  411.     ; IP packet is pointed to by [edx]
  412.     ; IP buffer number is on stack ( it will be popped at the end)
  413.     call    tcpStateMachine
  414.  
  415. tcprx_exit:
  416.     pop     eax
  417.     call    freeBuff
  418.  
  419.     ret
  420.  
  421.  
  422.  
  423. ;***************************************************************************
  424. ;   Function
  425. ;      buildTCPPacket
  426. ;
  427. ;   Description
  428. ;       builds an IP Packet with TCP data fully populated for transmission
  429. ;       You may destroy any and all registers
  430. ;          TCP control flags specified in bl
  431. ;          This TCB is in [sktAddr]
  432. ;          User data pointed to by esi
  433. ;       Data length in ecx
  434. ;          Transmit buffer number in eax
  435. ;
  436. ;***************************************************************************
  437. buildTCPPacket:
  438.     push    ecx                        ; Save data length
  439.  
  440.     ; convert buffer pointer eax to the absolute address
  441.     mov     ecx, IPBUFFSIZE
  442.     mul     ecx
  443.     add     eax, IPbuffs
  444.  
  445.     mov     edx, eax
  446.  
  447.     mov     [edx + 33], bl            ; TCP flags
  448.  
  449.     mov     ebx, [sktAddr]
  450.  
  451.     ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  452.  
  453.     ; Fill in the IP header ( some data is in the socket descriptor)
  454.     mov     eax, [ebx + 8]
  455.     mov     [edx + 12], eax      ; source IP
  456.     mov     eax, [ebx + 16]
  457.     mov     [edx + 16], eax      ; Destination IP
  458.  
  459.     mov     al, 0x45
  460.     mov     [edx], al         ; Version, IHL
  461.     xor     al, al
  462.     mov     [edx + 1], al     ; Type of service
  463.  
  464.     pop     eax                   ; Get the TCP data length
  465.     push    eax
  466.  
  467.     add     eax, 20 + 20           ; add IP header and TCP header lengths
  468.     mov     [edx + 2], ah
  469.     mov     [edx + 3], al
  470.     xor     al, al
  471.     mov     [edx + 4], al
  472.     mov     [edx + 5], al
  473.     mov     al, 0x40
  474.     mov     [edx + 6], al
  475.     xor     al, al
  476.     mov     [edx + 7], al
  477.     mov     al, 0x20
  478.     mov     [edx + 8], al
  479.     mov     al, 6                         ; TCP protocol
  480.     mov     [edx + 9], al
  481.  
  482.     ; Checksum left unfilled
  483.     xor     ax, ax
  484.     mov     [edx + 10], ax
  485.  
  486.     ; Fill in the TCP header ( some data is in the socket descriptor)
  487.     mov     ax, [ebx + 12]
  488.     mov     [edx + 20], ax        ; Local Port
  489.  
  490.     mov     ax, [ebx + 20]
  491.     mov     [edx + 20 + 2], ax    ; desitination Port
  492.  
  493.     ; Checksum left unfilled
  494.     xor     ax, ax
  495.     mov     [edx + 20 + 16], ax
  496.  
  497.     ; sequence number
  498.     mov     eax, [ebx + 48]
  499.     mov     [edx + 20 + 4], eax
  500.  
  501.     ; ack number
  502.     mov     eax, [ebx + 56]
  503.     mov     [edx + 20 + 8], eax
  504.  
  505.     ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
  506.     ; 768 bytes seems better
  507.     mov     ax, 0x0003
  508.     mov     [edx + 20 + 14], ax
  509.  
  510.     ; Urgent pointer (0)
  511.     mov     ax, 0
  512.     mov     [edx + 20 + 18], ax
  513.  
  514.     ; data offset ( 0x50 )
  515.     mov     al, 0x50
  516.     mov     [edx + 20 + 12], al
  517.  
  518.     pop     ecx                  ; count of bytes to send
  519.     mov     ebx, ecx            ; need the length later
  520.  
  521.     cmp     ebx, 0
  522.     jz      btp_001
  523.  
  524.     mov     edi, edx
  525.     add     edi, 40
  526.     cld
  527.     rep     movsb               ; copy the data across
  528.  
  529. btp_001:
  530.     ; we have edx as IPbuffer ptr.
  531.     ; Fill in the TCP checksum
  532.     ; First, fill in pseudoheader
  533.     mov     eax, [edx + 12]
  534.     mov     [pseudoHeader], eax
  535.     mov     eax, [edx + 16]
  536.     mov     [pseudoHeader+4], eax
  537.     mov     ax, 0x0600            ; 0 + protocol
  538.     mov     [pseudoHeader+8], ax
  539.     add     ebx, 20
  540.     mov     eax, ebx
  541.     mov     [pseudoHeader+10], ah
  542.     mov     [pseudoHeader+11], al
  543.  
  544.     mov     eax, pseudoHeader
  545.     mov     [checkAdd1], eax
  546.     mov     [checkSize1], word 12
  547.     mov     eax, edx
  548.     add     eax, 20
  549.     mov     [checkAdd2], eax
  550.     mov     eax, ebx
  551.     mov     [checkSize2], ax
  552.  
  553.     call    checksum
  554.  
  555.     ; store it in the TCP checksum ( in the correct order! )
  556.     mov     ax, [checkResult]
  557.  
  558.     mov     [edx + 20 + 16], ah
  559.     mov     [edx + 20 + 17], al
  560.  
  561.     ; Fill in the IP header checksum
  562.     GET_IHL eax,edx              ; get IP-Header length
  563.     stdcall checksum_jb,edx,eax  ; buf_ptr, buf_size
  564.  
  565.     mov     [edx + 10], ah
  566.     mov     [edx + 11], al
  567.  
  568.     ret
  569.  
  570.  
  571. ; Increments the 32 bit value pointed to by esi in internet order
  572. inc_inet_esi:
  573.     push    eax
  574.     add     esi, 3
  575.     mov     al, byte[esi]
  576.     inc     al
  577.     mov     byte[esi], al
  578.     cmp     al, 0
  579.     jnz     iie_exit
  580.     dec     esi
  581.     mov     al, byte[esi]
  582.     inc     al
  583.     mov     byte[esi], al
  584.     cmp     al, 0
  585.     jnz     iie_exit
  586.     dec     esi
  587.     mov     al, byte[esi]
  588.     inc     al
  589.     mov     byte[esi], al
  590.     cmp     al, 0
  591.     jnz     iie_exit
  592.     dec     esi
  593.     mov     al, byte[esi]
  594.     inc     al
  595.     mov     byte[esi], al
  596.  
  597. iie_exit:
  598.     pop     eax
  599.     ret
  600.  
  601.  
  602. ; Increments the 32 bit value pointed to by esi in internet order
  603. ; by the value in ecx
  604. add_inet_esi:
  605.     push    eax
  606.  
  607.     mov     al, [esi]
  608.     shl     eax, 8
  609.     inc     esi
  610.     mov     al, [esi]
  611.     shl     eax, 8
  612.     inc     esi
  613.     mov     al, [esi]
  614.     shl     eax, 8
  615.     inc     esi
  616.     mov     al, [esi]
  617.     add     eax, ecx
  618.     mov     [esi], al
  619.     dec     esi
  620.     shr     eax, 8
  621.     mov     [esi], al
  622.     dec     esi
  623.     shr     eax, 8
  624.     mov     [esi], al
  625.     dec     esi
  626.     shr     eax, 8
  627.     mov     [esi], al
  628.     pop     eax
  629.     ret
  630.  
  631.  
  632. iglobal
  633.   TCBStateHandler:
  634.     dd      stateTCB_LISTEN
  635.     dd      stateTCB_SYN_SENT
  636.     dd      stateTCB_SYN_RECEIVED
  637.     dd      stateTCB_ESTABLISHED
  638.     dd      stateTCB_FIN_WAIT_1
  639.     dd      stateTCB_FIN_WAIT_2
  640.     dd      stateTCB_CLOSE_WAIT
  641.     dd      stateTCB_CLOSING
  642.     dd      stateTCB_LAST_ACK
  643.     dd      stateTCB_TIME_WAIT
  644.     dd      stateTCB_CLOSED
  645. endg
  646.  
  647. ;***************************************************************************
  648. ;   Function
  649. ;      tcpStateMachine
  650. ;
  651. ;   Description
  652. ;       TCP state machine
  653. ;       This is a kernel function, called by tcp_rx
  654. ;
  655. ;       IP buffer address given in edx
  656. ;          Socket/TCB address in [eax + sockets]
  657. ;
  658. ;       The IP buffer will be released by the caller
  659. ;***************************************************************************
  660. tcpStateMachine:
  661.     mov     ebx, sockets
  662.     add     ebx, eax
  663.     mov     [sktAddr], ebx
  664.  
  665.     ; as a packet has been received, update the TCB timer
  666.     mov     ecx, TWOMSL
  667.     mov     [ebx + 32], ecx
  668.  
  669.     ; If the received packet has an ACK bit set,
  670.     ; remove any packets in the resend queue that this
  671.     ; received packet acknowledges
  672.     pusha
  673.     mov     cl, [edx + 33]
  674.     and     cl, 0x10
  675.     cmp     cl, 0x10
  676.     jne     tsm001                      ; No ACK, so no data yet
  677.  
  678.  
  679.     ; get skt number in al
  680.     shr     eax, 12
  681.  
  682.     ; The ack number is in [edx + 28], inet format
  683.     ; skt in al
  684.  
  685.     mov     esi, resendQ
  686.     mov     ecx, 0
  687.  
  688. t001:
  689.     cmp     ecx, NUMRESENDENTRIES
  690.     je      t003              ; None left
  691.     cmp     [esi], al
  692.     je      t002              ; found one
  693.     inc     ecx
  694.     add     esi, 4
  695.     jmp     t001
  696.  
  697. t002:                   ; Can we delete this buffer?
  698.  
  699.                         ; If yes, goto t004. No, goto t001
  700.     ; Get packet data address
  701.  
  702.     push    ecx
  703.     inc     ecx
  704.     ; Now get buffer location, and copy buffer across. argh! more copying,,
  705.     mov     edi, resendBuffer - IPBUFFSIZE
  706. t002a:
  707.     add     edi, IPBUFFSIZE
  708.     loop    t002a
  709.  
  710.     ; we have dest buffer location in edi. incoming packet in edx.
  711.     ; Get this packets sequence number
  712.     ; preserve al, ecx, esi, edx
  713.  
  714.     mov     cl, [edi + 24]
  715.     shl     ecx, 8
  716.     mov     cl, [edi + 25]
  717.     shl     ecx, 8
  718.     mov     cl, [edi + 26]
  719.     shl     ecx, 8
  720.     mov     cl, [edi + 27]
  721.     movzx   ebx, byte [edi + 3]
  722.     mov     bh, [edi + 2]
  723.     sub     ebx, 40
  724.     add     ecx, ebx          ; ecx is now seq# of last byte +1, intel format
  725.  
  726.     ; get recievd ack #, in intel format
  727.     mov     bl, [edx + 28]
  728.     shl     ebx, 8
  729.     mov     bl, [edx + 29]
  730.     shl     ebx, 8
  731.     mov     bl, [edx + 30]
  732.     shl     ebx, 8
  733.     mov     bl, [edx + 31]
  734.  
  735.     cmp     ebx, ecx        ; Finally. ecx = rx'ed ack. ebx = last byte in que
  736.                             ; DANGER! need to handle case that we have just
  737.                             ; passed the 2**32, and wrapped round!
  738.     pop     ecx
  739.  
  740.     jae     t004             ; if rx > old, delete old
  741.     inc     ecx
  742.     add     esi, 4
  743.     jmp     t001
  744.  
  745.  
  746. t004:
  747.     dec     dword [arp_rx_count] ; ************ TEST ONLY!
  748.  
  749.     mov     [esi], byte 0xFF
  750.     inc     ecx
  751.     add     esi, 4
  752.     jmp     t001
  753.  
  754. t003:
  755.  
  756. tsm001:
  757.     popa
  758.  
  759.     ; Call handler for given TCB state
  760.     mov     ebx, [eax + sockets+28]
  761.     cmp     ebx, TCB_LISTEN
  762.     jb      tsm_exit
  763.     cmp     ebx, TCB_CLOSED
  764.     ja      tsm_exit
  765.  
  766.     dec     ebx
  767.     call    dword [TCBStateHandler+ebx*4]
  768.  
  769. tsm_exit:
  770.     ret
  771.  
  772.  
  773.  
  774. stateTCB_LISTEN:
  775.     ; In this case, we are expecting a SYN packet
  776.     ; For now, if the packet is a SYN, process it, and send a response
  777.     ; If not, ignore it
  778.  
  779.     ; Look at control flags
  780.     mov     bl, [edx + 33]
  781.     and     bl, 0x02
  782.     cmp     bl, 0x02
  783.     jnz     stl_exit
  784.  
  785.     ; We have a SYN. update the socket with this IP packets details,
  786.     ; And send a response
  787.  
  788.     mov     ebx, [edx + 12] ; IP source address
  789.     mov     [eax + sockets + 16], ebx
  790.     mov     bx, [edx + 20] ; IP source port
  791.     mov     [eax + sockets + 20], bx
  792.     mov     ebx, [edx + 24] ; IRS
  793.     mov     [eax + sockets + 40], ebx
  794.     mov     [eax + sockets + 56], ebx
  795.     mov     esi, sockets
  796.     add     esi, eax
  797.     add     esi, 56
  798.     call    inc_inet_esi ; RCV.NXT
  799.     mov     ebx, [eax + sockets + 36]    ; ISS
  800.     mov     [eax + sockets + 48], ebx    ; SND.NXT
  801.  
  802.     ; Now construct the response, and queue for sending by IP
  803.     mov     eax, EMPTY_QUEUE
  804.     call    dequeue
  805.     cmp     ax, NO_BUFFER
  806.     je      stl_exit
  807.  
  808.     push    eax
  809.     mov     bl, 0x12        ; SYN + ACK
  810.     mov     ecx, 0
  811.     mov     esi, 0
  812.  
  813.     call    buildTCPPacket
  814.  
  815.     mov     eax, NET1OUT_QUEUE
  816.     mov     edx, [stack_ip]
  817.     mov     ecx, [ sktAddr ]
  818.     mov     ecx, [ ecx + 16 ]
  819.     cmp     edx, ecx
  820.     jne     stl_notlocal
  821.     mov     eax, IPIN_QUEUE
  822.  
  823. stl_notlocal:
  824.        ; Send it.
  825.     pop     ebx
  826.     call    queue
  827.  
  828.  
  829.     mov     ebx, TCB_SYN_RECEIVED
  830.     mov     esi, [sktAddr]
  831.     mov     [esi + 28], ebx
  832.  
  833.     ; increament SND.NXT in socket
  834.     add     esi, 48
  835.     call    inc_inet_esi
  836.  
  837. stl_exit:
  838.     ret
  839.  
  840.  
  841.  
  842. stateTCB_SYN_SENT:
  843.     ; We are awaiting an ACK to our SYN, with a SYM
  844.     ; Look at control flags - expecting an ACK
  845.     mov     bl, [edx + 33]
  846.     and     bl, 0x12
  847.     cmp     bl, 0x12
  848.     jnz     stss_exit
  849.  
  850.     mov     ebx, TCB_ESTABLISHED
  851.     mov     esi, [sktAddr]
  852.     mov     [esi + 28], ebx
  853.  
  854.     ; Store the recv.nxt field
  855.     mov     eax, [edx + 24]
  856.  
  857.     ; Update our recv.nxt field
  858.     mov     esi, [sktAddr]
  859.     add     esi, 56
  860.     mov     [esi], eax
  861.     call    inc_inet_esi
  862.  
  863.     ; Send an ACK
  864.     ; Now construct the response, and queue for sending by IP
  865.     mov     eax, EMPTY_QUEUE
  866.     call    dequeue
  867.     cmp     ax, NO_BUFFER
  868.     je      stss_exit
  869.  
  870.     push    eax
  871.  
  872.     mov     bl, 0x10        ; ACK
  873.     mov     ecx, 0
  874.     mov     esi, 0
  875.  
  876.     call    buildTCPPacket
  877.  
  878.     mov     eax, NET1OUT_QUEUE
  879.  
  880.     mov     edx, [stack_ip]
  881.     mov     ecx, [ sktAddr ]
  882.     mov     ecx, [ ecx + 16 ]
  883.     cmp     edx, ecx
  884.     jne     stss_notlocal
  885.     mov     eax, IPIN_QUEUE
  886.  
  887. stss_notlocal:
  888.        ; Send it.
  889.     pop     ebx
  890.     call    queue
  891.  
  892. stss_exit:
  893.     ret
  894.  
  895.  
  896.  
  897. stateTCB_SYN_RECEIVED:
  898.     ; In this case, we are expecting an ACK packet
  899.     ; For now, if the packet is an ACK, process it,
  900.     ; If not, ignore it
  901.  
  902.     ; Look at control flags - expecting an ACK
  903.     mov     bl, [edx + 33]
  904.     and     bl, 0x10
  905.     cmp     bl, 0x10
  906.     jnz     stsr_exit
  907.  
  908.     mov     ebx, TCB_ESTABLISHED
  909.     mov     esi, [sktAddr]
  910.     mov     [esi + 28], ebx
  911.  
  912. stsr_exit:
  913.     ret
  914.  
  915.  
  916.  
  917. stateTCB_ESTABLISHED:
  918.     ; Here we are expecting data, or a request to close
  919.     ; OR both...
  920.  
  921.     ; Did we receive a FIN or RST?
  922.     mov     bl, [edx + 33]
  923.     and     bl, 0x05
  924.     cmp     bl, 0
  925.     je      ste_chkack
  926.  
  927.     ; It was a fin or reset.
  928.  
  929.     ; Remove resend entries from the queue  - I dont want to send any more data
  930.     pusha
  931.  
  932.     mov     ebx, [sktAddr]
  933.     sub     ebx, sockets
  934.     shr     ebx, 12             ; get skt #
  935.  
  936.     mov     esi, resendQ
  937.     mov     ecx, 0
  938.  
  939. ste001:
  940.     cmp     ecx, NUMRESENDENTRIES
  941.     je      ste003              ; None left
  942.     cmp     [esi], bl
  943.     je      ste002              ; found one
  944.     inc     ecx
  945.     add     esi, 4
  946.     jmp     ste001
  947.  
  948. ste002:
  949.     dec     dword [arp_rx_count] ; ************ TEST ONLY!
  950.  
  951.     mov     [esi], byte 0xFF
  952.     jmp     ste001
  953.  
  954. ste003:
  955.     popa
  956.  
  957.     ; was it a reset?
  958.     mov     bl, [edx + 33]
  959.     and     bl, 0x04
  960.     cmp     bl, 0x04
  961.     jne     ste003a
  962.  
  963.     mov     esi, [sktAddr]
  964.     mov     ebx, TCB_CLOSED
  965.     mov     [esi + 28], ebx
  966.     jmp     ste_exit
  967.  
  968. ste003a:
  969.     ; Send an ACK to that fin, and enter closewait state
  970.  
  971.     mov     esi, [sktAddr]
  972.     mov     ebx, TCB_CLOSE_WAIT
  973.     mov     [esi + 28], ebx
  974.     add     esi, 56
  975.     mov     eax, [esi]              ; save original
  976.     call    inc_inet_esi
  977.     ;; jmp    ste_ack - NO, there may be data
  978.  
  979. ste_chkack:
  980.     ; Check that we received an ACK
  981.     mov     bl, [edx + 33]
  982.     and     bl, 0x10
  983.     cmp     bl, 0x10
  984.     jnz     ste_exit
  985.  
  986.  
  987.     ; TODO - done, I think!
  988.     ; First, look at the incoming window. If this is less than or equal to 1024,
  989.     ; Set the socket window timer to 1. This will stop an additional packets being
  990.     ; queued.
  991.     ; ** I may need to tweak this value, since I do not know how many packets are already queued
  992.     mov     ch, [edx + 34]
  993.     mov     cl, [edx + 35]
  994.     cmp     cx, 1024
  995.     ja      ste004
  996.  
  997.     mov     ecx, [sktAddr]
  998.     mov     [ecx+72], dword 1
  999.  
  1000. ste004:
  1001.  
  1002.     ; OK, here is the deal
  1003.     ; My recv.nct field holds the seq of the expected next rec byte
  1004.     ; if the recevied sequence number is not equal to this, do not
  1005.     ; increment the recv.nxt field, do not copy data - just send a
  1006.     ; repeat ack.
  1007.  
  1008.     ; recv.nxt is in dword [edx+24], in inext format
  1009.     ; recv seq is in [sktAddr]+56, in inet format
  1010.     ; just do a comparision
  1011.     mov     ecx, [sktAddr]
  1012.     add     ecx, 56
  1013.  
  1014.     cmp     [ecx - 56 + 28], dword TCB_CLOSE_WAIT
  1015.     mov     ecx, [ecx]
  1016.     jne     stenofin
  1017.     mov     ecx, eax
  1018.  
  1019. stenofin:
  1020.     cmp     ecx, [edx+24]
  1021.     jne     ste_ack
  1022.  
  1023.  
  1024.     ; Read the data bytes, store in socket buffer
  1025.     xor     ecx, ecx
  1026.     mov     ch, [edx + 2]
  1027.     mov     cl, [edx + 3]
  1028.     sub     ecx, 40                    ; Discard 40 bytes of header
  1029.  
  1030.     cmp     ecx, 0
  1031.     jnz     ste_data                ; Read data, if any
  1032.  
  1033.     ; If we had received a fin, we need to ACK it.
  1034.     mov     esi, [sktAddr]
  1035.     mov     ebx, [esi + 28]
  1036.     cmp     ebx, TCB_CLOSE_WAIT
  1037.     jz      ste_ack
  1038.     jnz     ste_exit
  1039.  
  1040. ste_data:
  1041.     push    ecx
  1042.     mov     esi, [sktAddr]
  1043.  
  1044.     add     [esi + 24], ecx      ; increment the count of bytes in buffer
  1045.  
  1046.     mov     eax, [esi + 4]       ; get socket owner PID
  1047.     push    eax
  1048.  
  1049.     mov     eax, [esi + 24]      ; get # of bytes already in buffer
  1050.  
  1051.     ; point to the location to store the data
  1052.     add     esi, eax
  1053.     sub     esi, ecx
  1054.     add     esi, SOCKETHEADERSIZE
  1055.  
  1056.     add     edx, 40        ; edx now points to the data
  1057.     mov     edi, esi
  1058.     mov     esi, edx
  1059.  
  1060.     cld
  1061.     rep     movsb          ; copy the data across
  1062.  
  1063.     ; flag an event to the application
  1064.     pop     eax
  1065.     mov     ecx,1
  1066.     mov     esi,TASK_DATA+TASKDATA.pid
  1067.  
  1068. news:
  1069.     cmp     [esi],eax
  1070.     je      foundPID1
  1071.     inc     ecx
  1072.     add     esi,0x20
  1073.     cmp     ecx,[TASK_COUNT]
  1074.     jbe     news
  1075.  
  1076. foundPID1:
  1077.     shl     ecx,8
  1078.     or      dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event
  1079.  
  1080.     pop     ecx
  1081.  
  1082.     ; Update our recv.nxt field
  1083.     mov     esi, [sktAddr]
  1084.     add     esi, 56
  1085.     call    add_inet_esi
  1086.  
  1087. ste_ack:
  1088.     ; Send an ACK
  1089.     ; Now construct the response, and queue for sending by IP
  1090.     mov     eax, EMPTY_QUEUE
  1091.     call    dequeue
  1092.     cmp     ax, NO_BUFFER
  1093.     je      ste_exit
  1094.  
  1095.     push    eax
  1096.  
  1097.     mov     bl, 0x10        ; ACK
  1098.     mov     ecx, 0
  1099.     mov     esi, 0
  1100.  
  1101.     call    buildTCPPacket
  1102.  
  1103.     mov     eax, NET1OUT_QUEUE
  1104.  
  1105.     mov     edx, [stack_ip]
  1106.     mov     ecx, [ sktAddr ]
  1107.     mov     ecx, [ ecx + 16 ]
  1108.     cmp     edx, ecx
  1109.     jne     ste_notlocal
  1110.     mov     eax, IPIN_QUEUE
  1111. ste_notlocal:
  1112.  
  1113.        ; Send it.
  1114.     pop     ebx
  1115.     call    queue
  1116.  
  1117. ste_exit:
  1118.     ret
  1119.  
  1120.  
  1121.  
  1122. stateTCB_FIN_WAIT_1:
  1123.     ; We can either receive an ACK of a fin, or a fin
  1124.     mov     bl, [edx + 33]
  1125.     and     bl, 0x10
  1126.     cmp     bl, 0x10
  1127.     jnz     stfw1_001
  1128.  
  1129.     ; It was an ACK
  1130.     mov     esi, [sktAddr]
  1131.     mov     ebx, TCB_FIN_WAIT_2
  1132.     mov     [esi + 28], ebx
  1133.     jmp     stfw1_exit
  1134.  
  1135. stfw1_001:
  1136.     ; It must be a fin then
  1137.     mov     esi, [sktAddr]
  1138.     mov     ebx, TCB_CLOSING
  1139.     mov     [esi + 28], ebx
  1140.     add     esi, 56
  1141.     call    inc_inet_esi
  1142.  
  1143.     ; Send an ACK
  1144.     mov     eax, EMPTY_QUEUE
  1145.     call    dequeue
  1146.     cmp     ax, NO_BUFFER
  1147.     je      stfw1_exit
  1148.  
  1149.     push    eax
  1150.  
  1151.     mov     bl, 0x10        ; ACK
  1152.     mov     ecx, 0
  1153.     mov     esi, 0
  1154.  
  1155.     call    buildTCPPacket
  1156.     mov     eax, NET1OUT_QUEUE
  1157.  
  1158.     mov     edx, [stack_ip]
  1159.     mov     ecx, [ sktAddr ]
  1160.     mov     ecx, [ ecx + 16 ]
  1161.     cmp     edx, ecx
  1162.     jne     stfw1_notlocal
  1163.     mov     eax, IPIN_QUEUE
  1164.  
  1165. stfw1_notlocal:
  1166.     ; Send it.
  1167.     pop     ebx
  1168.     call    queue
  1169.  
  1170. stfw1_exit:
  1171.     ret
  1172.  
  1173.  
  1174.  
  1175. stateTCB_FIN_WAIT_2:
  1176.     mov     esi, [sktAddr]
  1177.  
  1178.     ; Get data length
  1179.     xor     ecx, ecx
  1180.     mov     ch, [edx+2]
  1181.     mov     cl, [edx+3]
  1182.     sub     ecx, 40
  1183.  
  1184.     mov     bl, [edx + 33]
  1185.     and     bl, 0x01
  1186.     cmp     bl, 0x01
  1187.     jne     stfw2001
  1188.  
  1189.     ; Change state, as we have a fin
  1190.     mov     ebx, TCB_TIME_WAIT
  1191.     mov     [esi + 28], ebx
  1192.  
  1193.     inc     ecx                     ; FIN is part of the sequence space
  1194.  
  1195. stfw2001:
  1196.     add     esi, 56
  1197.     call    add_inet_esi
  1198.  
  1199.     ; Send an ACK
  1200.     mov     eax, EMPTY_QUEUE
  1201.     call    dequeue
  1202.     cmp     ax, NO_BUFFER
  1203.     je      stfw2_exit
  1204.  
  1205.     push    eax
  1206.  
  1207.     mov     bl, 0x10        ; ACK
  1208.     mov     ecx, 0
  1209.     mov     esi, 0
  1210.  
  1211.     call    buildTCPPacket
  1212.  
  1213.     mov     eax, NET1OUT_QUEUE
  1214.  
  1215.     mov     edx, [stack_ip]
  1216.     mov     ecx, [ sktAddr ]
  1217.     mov     ecx, [ ecx + 16 ]
  1218.     cmp     edx, ecx
  1219.     jne     stfw2_notlocal
  1220.     mov     eax, IPIN_QUEUE
  1221.  
  1222. stfw2_notlocal:
  1223.        ; Send it.
  1224.     pop     ebx
  1225.     call    queue
  1226.  
  1227.     ; Only delete the socket if we received the FIN
  1228.  
  1229.     mov     edx, [sktAddr]
  1230.     mov     bl, [edx + 33]
  1231.     and     bl, 0x01
  1232.     cmp     bl, 0x01
  1233.     jne     stfw2_exit
  1234.  
  1235. ;    mov     edi, [sktAddr]
  1236.  
  1237.     ; delete the socket. Should really wait for 2MSL
  1238. ;    xor     eax, eax
  1239. ;    mov     ecx,SOCKETHEADERSIZE
  1240. ;    cld
  1241. ;    rep     stosb
  1242.  
  1243. stfw2_exit:
  1244.     ret
  1245.  
  1246.  
  1247.  
  1248. stateTCB_CLOSE_WAIT:
  1249.     ; Intentionally left empty
  1250.     ; socket_close_tcp handles this
  1251.     ret
  1252.  
  1253.  
  1254.  
  1255. stateTCB_CLOSING:
  1256.     ; We can either receive an ACK of a fin, or a fin
  1257.     mov     bl, [edx + 33]
  1258.     and     bl, 0x10
  1259.     cmp     bl, 0x10
  1260.     jnz     stc_exit
  1261.  
  1262.     ; It was an ACK
  1263.  
  1264.     mov     edi, [sktAddr]
  1265.  
  1266.     ; delete the socket
  1267.     xor     eax, eax
  1268.     mov     ecx,SOCKETHEADERSIZE
  1269.     cld
  1270.     rep     stosb
  1271.  
  1272. stc_exit:
  1273.     ret
  1274.  
  1275.  
  1276.  
  1277. stateTCB_LAST_ACK:
  1278.     ; Look at control flags - expecting an ACK
  1279.     mov     bl, [edx + 33]
  1280.     and     bl, 0x10
  1281.     cmp     bl, 0x10
  1282.     jnz     stla_exit
  1283.  
  1284.     mov     edi, [sktAddr]
  1285.  
  1286.     ; delete the socket
  1287.     xor     eax, eax
  1288.     mov     ecx,SOCKETHEADERSIZE
  1289.     cld
  1290.     rep     stosb
  1291.  
  1292. stla_exit:
  1293.     ret
  1294.  
  1295.  
  1296.  
  1297. stateTCB_TIME_WAIT:
  1298.     ret
  1299.  
  1300.  
  1301.  
  1302. stateTCB_CLOSED:
  1303.     ret
  1304.