Subversion Repositories Kolibri OS

Rev

Rev 129 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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