Subversion Repositories Kolibri OS

Rev

Rev 425 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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