Subversion Repositories Kolibri OS

Rev

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