Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  TCP.INC                                                        ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;    Written by hidnplayr@kolibrios.org                           ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17.  
  18. $Revision: 1206 $
  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_TIMED_WAIT          equ 10
  32. TCB_CLOSED              equ 11
  33.  
  34. TH_FIN                  equ 0x01
  35. TH_SYN                  equ 0x02
  36. TH_RST                  equ 0x04
  37. TH_PUSH                 equ 0x08
  38. TH_ACK                  equ 0x10
  39. TH_URG                  equ 0x20
  40.  
  41. TWOMSL                  equ 10          ; # of secs to wait before closing socket
  42.  
  43. TCP_RETRIES             equ 5           ; Number of times to resend a Packet
  44. TCP_TIMEOUT             equ 10          ; resend if not replied to in x hs
  45.  
  46. TCP_QUEUE_SIZE          equ 16
  47.  
  48. struct  TCP_Packet
  49.         .SourcePort             dw ?
  50.         .DestinationPort        dw ?
  51.         .SequenceNumber         dd ?
  52.         .AckNumber              dd ?
  53.         .DataOffset             db ?    ; DataOffset[0-3 bits] and Reserved[4-7]
  54.         .Flags                  db ?    ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
  55.         .Window                 dw ?
  56.         .Checksum               dw ?
  57.         .UrgentPointer          dw ?
  58.         .Options                rb 3
  59.         .Padding                db ?
  60.         .Data:
  61. ends
  62.  
  63. align 4
  64. uglobal
  65.         TCP_PACKETS_TX          rd  MAX_IP
  66.         TCP_PACKETS_RX          rd  MAX_IP
  67.  
  68.         TCP_IN_QUEUE    rd  3*TCP_QUEUE_SIZE+3
  69.         TCP_OUT_QUEUE   rd  3*TCP_QUEUE_SIZE+3
  70. endg
  71.  
  72.  
  73.  
  74.  
  75.  
  76. ;-----------------------------------------------------------------
  77. ;
  78. ; TCP_init
  79. ;
  80. ;  This function resets all TCP variables
  81. ;
  82. ;  IN:  /
  83. ;  OUT: /
  84. ;
  85. ;-----------------------------------------------------------------
  86.  
  87. align 4
  88. TCP_init:
  89.  
  90.         xor     eax, eax
  91.         mov     edi, TCP_PACKETS_TX
  92.         mov     ecx, 2*MAX_IP
  93.         rep     stosd
  94.  
  95.         mov     dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE
  96.         mov     dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data
  97.         mov     dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data
  98.  
  99.         mov     dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
  100.         mov     dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data
  101.         mov     dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data
  102.  
  103.         ret
  104.  
  105.  
  106. ;-----------------------------------------------------------------
  107. ;
  108. ;      tcp_tcb_handler
  109. ;
  110. ;       Handles sockets in the timewait state, closing them
  111. ;       when the TCB timer expires
  112. ;
  113. ;-----------------------------------------------------------------
  114.  
  115. align 4
  116. tcp_tcb_handler:
  117.         ; scan through all the sockets, decrementing active timers
  118.  
  119.         mov     ebx, net_sockets
  120.  
  121.         cmp     [ebx + SOCKET.NextPtr], 0
  122.         je      .exit
  123.         DEBUGF  1, "K : sockets:\n"
  124.  
  125.   .next_socket:
  126.         mov     ebx, [ebx + SOCKET.NextPtr]
  127.         or      ebx, ebx
  128.         jz      .exit
  129.  
  130. ;        DEBUGF  1, "K :   %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState]
  131.  
  132.         cmp     [ebx + SOCKET.TCBTimer], 0
  133.         jne     .decrement_tcb
  134.         cmp     [ebx + SOCKET.wndsizeTimer], 0
  135.         jne     .decrement_wnd
  136.         jmp     .next_socket
  137.  
  138.   .decrement_tcb:
  139.         ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
  140.         dec     [ebx + SOCKET.TCBTimer]
  141.         jnz     .next_socket
  142.  
  143.         cmp     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
  144.         jne     .next_socket
  145.  
  146.         push    [ebx + SOCKET.PrevPtr]
  147.         stdcall net_socket_free, ebx
  148.         pop     ebx
  149.         jmp     .next_socket
  150.  
  151.   .decrement_wnd:
  152.         ; TODO - prove it works!
  153.         dec     [ebx + SOCKET.wndsizeTimer]
  154.         jmp     .next_socket
  155.  
  156.   .exit:
  157.         ret
  158.  
  159.  
  160. ;***************************************************************************
  161. ;   Function
  162. ;      tcp_tx_handler
  163. ;
  164. ;   Description
  165. ;       Handles queued TCP data
  166. ;       This is a kernel function, called by stack_handler
  167. ;
  168. ;***************************************************************************
  169.  
  170. align 4
  171. tcp_tx_handler:
  172.     ; decrement all resend buffers timers. If they
  173.     ; expire, queue them for sending, and restart the timer.
  174.     ; If the retries counter reach 0, delete the entry
  175.  
  176.         mov     esi, resendQ
  177.         mov     ecx, 0
  178.  
  179.   .next_resendq:
  180. ;        cmp     ecx, NUMRESENDENTRIES
  181.         je      .exit               ; None left
  182.         cmp     dword[esi + 4], 0
  183.         jne     @f                   ; found one
  184.         inc     ecx
  185.         add     esi, 8
  186.         jmp     .next_resendq
  187.  
  188.     @@: ; we have one. decrement it's timer by 1
  189.         dec     word[esi + 2]
  190.         jz      @f
  191.         inc     ecx
  192.         add     esi, 8
  193.         jmp     .next_resendq       ; Timer not zero, so move on
  194.  
  195.     @@:
  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 + 4], ebx
  205.  
  206.     @@: ; resend Packet
  207.         pushad
  208.  
  209. ;        mov     eax, EMPTY_QUEUE
  210. ;        call    dequeue
  211. ;        cmp     ax, NO_BUFFER
  212.         jne     .tth004z
  213.  
  214.         ; TODO - try again in 10ms.
  215.         test    ebx, ebx
  216.         jnz     @f
  217.         mov     [esi + 4], ebx
  218.  
  219.     @@: ; Mark it to expire in 10ms - 1 tick
  220.         mov     byte[esi + 1], 1
  221.         mov     word[esi + 2], 1
  222.         jmp     .tth005
  223.  
  224.   .tth004z:
  225.         ; we have a buffer # in ax
  226. ;        push    eax ecx
  227. ;        mov     ecx, IPBUFFSIZE
  228. ;        mul     ecx
  229. ;        add     eax, IPbuffs
  230.  
  231.         ; we have the buffer address in eax
  232.         mov     edi, eax
  233.         pop     ecx
  234.         ; Now get buffer location, and copy buffer across. argh! more copying,,
  235. ;        mov     esi, resendBuffer
  236. ;    @@: add     esi, IPBUFFSIZE
  237.         loop    @b
  238.  
  239.         ; we have resend buffer location in esi
  240. ;        mov     ecx, IPBUFFSIZE
  241.  
  242.         ; copy data across
  243.         push    edi
  244.         cld
  245.         rep     movsb
  246.         pop     edi
  247.  
  248.         ; queue Packet
  249. ;        mov     eax, NET1OUT_QUEUE
  250. ;        mov     edx, [IP_LIST]
  251. ;        cmp     edx, [edi + IP_Packet.DestinationAddress]
  252. ;        jne     .not_local
  253. ;        mov     eax, IPIN_QUEUE
  254.  
  255.   .not_local:
  256.         pop     ebx
  257. ;        call    queue
  258.  
  259.   .tth005:
  260.         popad
  261.  
  262.         inc     ecx
  263.         add     esi, 8
  264.         jmp     .next_resendq
  265.  
  266.   .exit:
  267.         ret
  268.  
  269.  
  270.  
  271. ;-----------------------------------------------------------------
  272. ;
  273. ; TCP_Handler:
  274. ;
  275. ;  Called by IPv4_handler,
  276. ;  this procedure will inject the tcp data diagrams in the application sockets.
  277. ;
  278. ;  IN:  Pointer to buffer in [esp]
  279. ;       size of buffer in [esp+4]
  280. ;       pointer to device struct in ebx
  281. ;       TCP Packet size in ecx
  282. ;       pointer to TCP Packet data in edx
  283. ;       SourceAddres in esi
  284. ;  OUT: /
  285. ;
  286. ;-----------------------------------------------------------------
  287.  
  288. TCP_Handler :
  289.  
  290.  
  291.        DEBUGF 1,"TCP_Handler\n"
  292.  
  293.         jmp .exit ;;;;
  294.  
  295.         ; Look for a socket where
  296.         ; IP Packet TCP Destination Port = local Port
  297.         ; IP Packet SA = Remote IP
  298.         ; IP Packet TCP Source Port = remote Port
  299.  
  300.         mov     ebx, net_sockets
  301.  
  302.   .next_socket.1:
  303.         mov     ebx, [ebx + SOCKET.NextPtr]
  304.         or      ebx, ebx
  305.         jz      .next_socket.1.exit
  306.  
  307. ;        DEBUGF  1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
  308.  
  309.         mov     ax, [edx + TCP_Packet.DestinationPort]  ; get the dest. port from the TCP hdr
  310.         cmp     [ebx + SOCKET.LocalPort], ax            ; get the dest. port from the TCP hdr
  311.         jne     .next_socket.1                          ; different - try next socket
  312.  
  313. ;        DEBUGF  1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
  314.  
  315.         mov     eax, esi ;[edx + IP_Packet.SourceAddress]    ; get the source IP Addr from the IP hdr
  316.         cmp     [ebx + SOCKET.RemoteIP], eax            ; compare with socket's remote IP
  317.         jne     .next_socket.1                          ; different - try next socket
  318.  
  319. ;        DEBUGF  1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_Packet.SourcePort]:4, [ebx + SOCKET.RemotePort]:4
  320.  
  321.         mov     ax, [edx + TCP_Packet.SourcePort]  ; get the source port from the TCP hdr
  322.         cmp     [ebx + SOCKET.RemotePort], ax           ; compare with socket's remote port
  323.         jne     .next_socket.1                          ; different - try next socket
  324.  
  325.         ; We have a complete match - use this socket
  326.         jmp     .change_state
  327.  
  328.   .next_socket.1.exit:
  329.  
  330.         ; If we got here, there was no match
  331.         ; Look for a socket where
  332.         ; IP Packet TCP Destination Port = local Port
  333.         ; IP Packet SA = Remote IP
  334.         ; socket remote Port = 0
  335.  
  336.         mov     ebx, net_sockets
  337.  
  338.   .next_socket.2:
  339.         mov     ebx, [ebx + SOCKET.NextPtr]
  340.         or      ebx, ebx
  341.         jz      .next_socket.2.exit
  342.  
  343. ;        DEBUGF  1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
  344.  
  345.         mov     ax, [edx + TCP_Packet.DestinationPort]  ; get the dest. port from the TCP hdr
  346.         cmp     [ebx + SOCKET.LocalPort], ax            ; compare with socket's local port
  347.         jne     .next_socket.2                          ; different - try next socket
  348.  
  349. ;        DEBUGF  1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
  350.  
  351. ;        mov     eax, esi ;[edx + IP_Packet.SourceAddress]    ; get the source IP Addr from the IP hdr
  352.         cmp     [ebx + SOCKET.RemoteIP], esi            ; compare with socket's remote IP
  353.         jne     .next_socket.2                          ; different - try next socket
  354.  
  355. ;        DEBUGF  1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
  356.  
  357.         cmp     [ebx + SOCKET.RemotePort], 0            ; only match a remote socket of 0
  358.         jne     .next_socket.2                          ; different - try next socket
  359.  
  360.         ; We have a complete match - use this socket
  361.         jmp     .change_state
  362.  
  363.   .next_socket.2.exit:
  364.  
  365.         ; If we got here, there was no match
  366.         ; Look for a socket where
  367.         ; IP Packet TCP Destination Port = local Port
  368.         ; socket Remote IP = 0
  369.         ; socket remote Port = 0
  370.  
  371.         mov     ebx, net_sockets
  372.  
  373.   .next_socket.3:
  374.         mov     ebx, [ebx + SOCKET.NextPtr]
  375.         or      ebx, ebx
  376.         jz      .next_socket.3.exit
  377.  
  378. ;        DEBUGF  1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
  379.  
  380.         mov     ax, [edx + TCP_Packet.DestinationPort]  ; get destination port from the TCP hdr
  381.         cmp     [ebx + SOCKET.LocalPort], ax            ; compare with socket's local port
  382.         jne     .next_socket.3                          ; different - try next socket
  383.  
  384. ;        DEBUGF  1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
  385.  
  386.         cmp     [ebx + SOCKET.RemoteIP], 0              ; only match a socket remote IP of 0
  387.         jne     .next_socket.3                          ; different - try next socket
  388.  
  389. ;        DEBUGF  1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
  390.  
  391.         cmp     [ebx + SOCKET.RemotePort], 0            ; only match a remote socket of 0
  392.         jne     .next_socket.3                          ; different - try next socket
  393.  
  394.         ; We have a complete match - use this socket
  395.         jmp     .change_state
  396.  
  397.   .next_socket.3.exit:
  398.  
  399.         ; If we got here, we need to reject the Packet
  400.  
  401.         DEBUGF  1, "K : tcp_rx - dumped\n"
  402. ;        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
  403.  
  404. ;        inc     [dumped_rx_count]
  405.         jmp     .exit
  406.  
  407.   .change_state:
  408.  
  409.         ; We have a valid socket/TCB, so call the TCB State Machine for that skt.
  410.         ; socket is pointed to by ebx
  411.         ; IP Packet is pointed to by edx
  412.         ; IP buffer number is on stack ( it will be popped at the end)
  413.  
  414.         stdcall tcpStateMachine, ebx
  415.  
  416.   .exit:
  417.  
  418.         call    kernel_free
  419.         add     esp, 4 ; pop (balance stack)
  420.  
  421. ret
  422.  
  423.  
  424.  
  425. ;-----------------------------------------------------------------
  426. ;
  427. ; IN: eax = dest ip
  428. ;     ebx = source ip
  429. ;     ecx = data length
  430. ;     edx = remote port shl 16 + local port
  431. ;     esi = data offset
  432. ;
  433. ;-----------------------------------------------------------------
  434.  
  435. TCP_create_Packet:
  436.  
  437.         DEBUGF 1,"Create TCP Packet\n"
  438. ;***************************************************************************
  439. ;   Function
  440. ;      buildTCPPacket
  441. ;
  442. ;   Description
  443. ;       builds an IP Packet with TCP data fully populated for transmission
  444. ;       You may destroy any and all registers
  445. ;          TCP control flags specified in bl
  446. ;          This TCB is in [sktAddr]
  447. ;          User data pointed to by esi
  448. ;       Data length in ecx
  449. ;          Transmit buffer number in eax
  450. ;
  451. ;***************************************************************************
  452.  
  453.         push    ecx                        ; Save data length
  454.  
  455.         add     ecx, UDP_Packet.Data
  456.         mov     di , IP_PROTO_UDP
  457.  
  458. ;       dx  = fragment id
  459.  
  460.         call    IPv4_create_Packet                              ; TODO: figure out a way to choose between IPv4 and IPv6
  461.         cmp     edi, -1
  462.         je      .exit
  463.  
  464.         mov     [edi + TCP_Packet.Flags], bl               ; TCP flags
  465.  
  466. ;        mov     ebx, [sockAddr];---------------------------------------------------------- eof
  467.  
  468.         ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  469.  
  470.         ; Fill in the IP header ( some data is in the socket descriptor)
  471.         mov     eax, [ebx + SOCKET.LocalIP]
  472. ;        mov     [edx + IP_Packet.SourceAddress], eax
  473.         mov     eax, [ebx + SOCKET.RemoteIP]
  474. ;        mov     [edx + IP_Packet.DestinationAddress], eax
  475.  
  476. ;        mov     [edx + IP_Packet.VersionAndIHL], 0x45
  477. ;        mov     [edx + IP_Packet.TypeOfService], 0
  478.  
  479.         pop     eax                   ; Get the TCP data length
  480.         push    eax
  481.  
  482.         add     eax, 20 + 20           ; add IP header and TCP header lengths
  483.         rol     ax, 8
  484. ;        mov     [edx + IP_Packet.TotalLength], ax
  485. ;        mov     [edx + IP_Packet.Identification], 0
  486. ;        mov     [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040
  487. ;        mov     [edx + IP_Packet.TimeToLive], 0x20
  488. ;        mov     [edx + IP_Packet.Protocol], PROTOCOL_TCP
  489.  
  490.         ; Checksum left unfilled
  491. ;        mov     [edx + IP_Packet.HeaderChecksum], 0
  492.  
  493.         ; Fill in the TCP header (some data is in the socket descriptor)
  494.         mov     ax, [ebx + SOCKET.LocalPort]
  495.         mov     [edx + 20 + TCP_Packet.SourcePort], ax          ; Local Port
  496.  
  497.         mov     ax, [ebx + SOCKET.RemotePort]
  498.         mov     [edx + 20 + TCP_Packet.DestinationPort], ax     ; desitination Port
  499.  
  500.         ; Checksum left unfilled
  501.         mov     [edx + 20 + TCP_Packet.Checksum], 0
  502.  
  503.         ; sequence number
  504.         mov     eax, [ebx + SOCKET.SND_NXT]
  505.         mov     [edx + 20 + TCP_Packet.SequenceNumber], eax
  506.  
  507.         ; ack number
  508.         mov     eax, [ebx + SOCKET.RCV_NXT]
  509.         mov     [edx + 20 + TCP_Packet.AckNumber], eax
  510.  
  511.         ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
  512.         ; 768 bytes seems better
  513.         mov     [edx + 20 + TCP_Packet.Window], 0x0003
  514.  
  515.         ; Urgent pointer (0)
  516.         mov     [edx + 20 + TCP_Packet.UrgentPointer], 0
  517.  
  518.         ; data offset ( 0x50 )
  519.         mov     [edx + 20 + TCP_Packet.DataOffset], 0x50
  520.  
  521.         pop     ecx                  ; count of bytes to send
  522.         mov     ebx, ecx            ; need the length later
  523.  
  524.         cmp     ebx, 0
  525.         jz      @f
  526.  
  527.         mov     edi, edx
  528.         add     edi, 40
  529.         cld
  530.         rep     movsb               ; copy the data across
  531.  
  532.     @@: ; we have edx as IPbuffer ptr.
  533.         ; Fill in the TCP checksum
  534.         ; First, fill in pseudoheader
  535. ;        mov     eax, [edx + IP_Packet.SourceAddress]
  536. ;        mov     [pseudoHeader], eax
  537. ;        mov     eax, [edx + IP_Packet.DestinationAddress]
  538. ;        mov     [pseudoHeader + 4], eax
  539. ;        mov     word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0
  540. ;        add     ebx, 20
  541. ;        mov     [pseudoHeader + 10], bh
  542. ;        mov     [pseudoHeader + 11], bl
  543. ;
  544. ;        mov     eax, pseudoHeader
  545. ;        mov     [checkAdd1], eax
  546. ;        mov     word[checkSize1], 12
  547. ;        mov     eax, edx
  548. ;        add     eax, 20
  549. ;        mov     [checkAdd2], eax
  550. ;        mov     eax, ebx
  551. ;        mov     [checkSize2], ax
  552. ;
  553. ;        call    checksum
  554.  
  555.         ; store it in the TCP checksum ( in the correct order! )
  556. ;        mov     ax, [checkResult]
  557. ;        rol     ax, 8
  558. ;        mov     [edx + 20 + TCP_Packet.Checksum], ax
  559.  
  560.         ; Fill in the IP header checksum
  561. ;    movzx   eax, byte [edx + IP_Packet.VersionAndIHL]  ; Calculate Header length by using IHL field
  562. ;    and     eax, 0x0000000F  ;
  563. ;    shl     eax, 2           ;
  564. ;
  565.         stdcall checksum_jb, edx, eax  ; buf_ptr, buf_size
  566.         rol     ax, 8
  567. ;        mov     [edx + IP_Packet.HeaderChecksum], ax
  568.  
  569.  
  570.        .exit:
  571.  
  572.         call    kernel_free
  573.         add     esp, 4 ; pop (balance stack)
  574.  
  575.         ret
  576. ;endp
  577.  
  578.  
  579. ; Increments the 32 bit value pointed to by esi in internet order
  580. proc inc_inet_esi stdcall
  581. ;        push    eax
  582. ;        mov     eax, [esi]
  583. ;        bswap   eax
  584. ;        inc     eax
  585. ;        bswap   eax
  586. ;        mov     [esi], eax
  587. ;        pop     eax
  588. ;        ret
  589.         inc     byte[esi+0]
  590.         adc     byte[esi+1],0
  591.         adc     byte[esi+2],0
  592.         adc     byte[esi+3],0
  593. endp
  594.  
  595.  
  596. ; Increments the 32 bit value pointed to by esi in internet order
  597. ; by the value in ecx
  598. proc add_inet_esi stdcall
  599.         push    eax
  600.         mov     eax, [esi]
  601.         bswap   eax
  602.         add     eax, ecx
  603.         bswap   eax
  604.         mov     [esi], eax
  605.         pop     eax
  606.         ret
  607. endp
  608.  
  609.  
  610. iglobal
  611.   TCBStateHandler dd \
  612.     stateTCB_LISTEN, \
  613.     stateTCB_SYN_SENT, \
  614.     stateTCB_SYN_RECEIVED, \
  615.     stateTCB_ESTABLISHED, \
  616.     stateTCB_FIN_WAIT_1, \
  617.     stateTCB_FIN_WAIT_2, \
  618.     stateTCB_CLOSE_WAIT, \
  619.     stateTCB_CLOSING, \
  620.     stateTCB_LAST_ACK, \
  621.     stateTCB_TIME_WAIT, \
  622.     stateTCB_CLOSED
  623. endg
  624.  
  625.  
  626. ;***************************************************************************
  627. ;   Function
  628. ;      tcpStateMachine
  629. ;
  630. ;   Description
  631. ;       TCP state machine
  632. ;       This is a kernel function, called by tcp_rx
  633. ;
  634. ;       IP buffer address given in edx
  635. ;          Socket/TCB address in ebx
  636. ;
  637. ;       The IP buffer will be released by the caller
  638. ;***************************************************************************
  639.  
  640. proc tcpStateMachine stdcall, sockAddr:DWORD
  641.         ; as a Packet has been received, update the TCB timer
  642.         mov     [ebx + SOCKET.TCBTimer], TWOMSL
  643.  
  644.         ; If the received Packet has an ACK bit set,
  645.         ; remove any Packets in the resend queue that this
  646.         ; received Packet acknowledges
  647.         pushad
  648.         test    [edx + 20 + TCP_Packet.Flags], TH_ACK
  649.         jz      .call_handler                                   ; No ACK, so no data yet
  650.  
  651.         ; get skt number in eax
  652.         stdcall net_socket_addr_to_num, ebx
  653.  
  654.         ; The ack number is in [edx + 28], inet format
  655.         ; skt in eax
  656.  
  657.         mov     esi, resendQ
  658.         xor     ecx, ecx
  659.  
  660.   .next_resendq:
  661. ;        cmp     ecx, NUMRESENDENTRIES
  662.         je      .call_handler     ; None left
  663.         cmp     [esi + 4], eax
  664.         je      @f                ; found one
  665.         inc     ecx
  666.         add     esi, 8
  667.         jmp     .next_resendq
  668.  
  669.     @@:                   ; Can we delete this buffer?
  670.  
  671.                           ; If yes, goto @@. No, goto .next_resendq
  672.         ; Get Packet data address
  673.  
  674.         push    ecx
  675.         ; Now get buffer location, and copy buffer across. argh! more copying,,
  676. ;        imul    edi, ecx, IPBUFFSIZE
  677. ;        add     edi, resendBuffer
  678.  
  679.         ; we have dest buffer location in edi. incoming Packet in edx.
  680.         ; Get this Packets sequence number
  681.         ; preserve al, ecx, esi, edx
  682.         mov     ecx, [edi + 20 + TCP_Packet.SequenceNumber]
  683.         bswap   ecx
  684.         movzx   ebx, word[edi + 2]
  685.         xchg    bl, bh
  686.         sub     ebx, 40
  687.         add     ecx, ebx          ; ecx is now seq# of last byte +1, intel format
  688.  
  689.         ; get recievd ack #, in intel format
  690.         mov     ebx, [edx + 20 + TCP_Packet.AckNumber]
  691.         bswap   ebx
  692.  
  693.         cmp     ebx, ecx        ; Finally. ecx = rx'ed ack. ebx = last byte in que
  694.                                 ; DANGER! need to handle case that we have just
  695.                                 ; passed the 2**32, and wrapped round!
  696.         pop     ecx
  697.         jae     @f              ; if rx > old, delete old
  698.  
  699.         inc     ecx
  700.         add     esi, 8
  701.         jmp     .next_resendq
  702.  
  703.     @@: mov     dword[esi + 4], 0
  704.         inc     ecx
  705.         add     esi, 8
  706.         jmp     .next_resendq
  707.  
  708.   .call_handler:
  709.         popad
  710.  
  711.         ; Call handler for given TCB state
  712.  
  713.         mov     eax, [ebx + SOCKET.TCBState]
  714.         cmp     eax, TCB_LISTEN
  715.         jb      .exit
  716.         cmp     eax, TCB_CLOSED
  717.         ja      .exit
  718.  
  719.         stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
  720.  
  721.   .exit:
  722.         ret
  723. endp
  724.  
  725.  
  726. proc stateTCB_LISTEN stdcall, sockAddr:DWORD
  727.         ; In this case, we are expecting a SYN Packet
  728.         ; For now, if the Packet is a SYN, process it, and send a response
  729.         ; If not, ignore it
  730.  
  731.         ; Look at control flags
  732.         test    [edx + 20 + TCP_Packet.Flags], TH_SYN
  733.         jz      .exit
  734.  
  735.         ; We have a SYN. update the socket with this IP Packets details,
  736.         ; And send a response
  737.  
  738. ;        mov     eax, [edx + IP_Packet.SourceAddress]
  739.  ;       mov     [ebx + SOCKET.RemoteIP], eax
  740. ;        mov     ax, [edx + 20 + TCP_Packet.SourcePort]
  741. ;        mov     [ebx + SOCKET.RemotePort], ax
  742. ;        mov     eax, [edx + 20 + TCP_Packet.SequenceNumber]
  743. ;        mov     [ebx + SOCKET.IRS], eax
  744. ;        mov     [ebx + SOCKET.RCV_NXT], eax
  745. ;        lea     esi, [ebx + SOCKET.RCV_NXT]
  746. ;        call    inc_inet_esi ; RCV.NXT
  747. ;        mov     eax, [ebx + SOCKET.ISS]
  748. ;        mov     [ebx + SOCKET.SND_NXT], eax
  749. ;
  750.         ; Now construct the response, and queue for sending by IP
  751. ;        mov     eax, EMPTY_QUEUE
  752. ;        call    dequeue
  753. ;        cmp     ax, NO_BUFFER
  754.  ;       je      .exit
  755.  
  756.         push    eax
  757.         mov     bl, TH_SYN + TH_ACK
  758.         xor     ecx, ecx
  759.         xor     esi, esi
  760. ;        stdcall build_tcp_Packet, [sockAddr]
  761.  
  762. ;        mov     eax, NET1OUT_QUEUE
  763. ;;;        mov     edx, [stack_ip]
  764.         mov     ecx, [sockAddr]
  765.         cmp     edx, [ecx + SOCKET.RemoteIP]
  766.         jne     .not_local
  767. ;        mov     eax, IPIN_QUEUE
  768.  
  769.   .not_local:
  770.         ; Send it.
  771.         pop     ebx
  772. ;;;        call    queue
  773.  
  774.         mov     esi, [sockAddr]
  775.         mov     [esi + SOCKET.TCBState], TCB_SYN_RECEIVED
  776.  
  777.         ; increment SND.NXT in socket
  778.         add     esi, SOCKET.SND_NXT
  779.         call    inc_inet_esi
  780.  
  781.   .exit:
  782.         ret
  783. endp
  784.  
  785.  
  786. proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
  787.         ; We are awaiting an ACK to our SYN, with a SYM
  788.         ; Look at control flags - expecting an ACK
  789.  
  790.         mov     al, [edx + 20 + TCP_Packet.Flags]
  791.         and     al, TH_SYN + TH_ACK
  792.         cmp     al, TH_SYN + TH_ACK
  793.         je      .syn_ack
  794.  
  795.         test    al, TH_SYN
  796.         jz      .exit
  797.  
  798.         mov     [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
  799.         push    TH_SYN + TH_ACK
  800.         jmp     .send
  801.  
  802.   .syn_ack:
  803.         mov     [ebx + SOCKET.TCBState], TCB_ESTABLISHED
  804.         push    TH_ACK
  805.  
  806.   .send:
  807.         ; Store the recv.nxt field
  808.         mov     eax, [edx + 20 + TCP_Packet.SequenceNumber]
  809.  
  810.         ; Update our recv.nxt field
  811.         mov     [ebx + SOCKET.RCV_NXT], eax
  812.         lea     esi, [ebx + SOCKET.RCV_NXT]
  813.         call    inc_inet_esi
  814.  
  815.         ; Send an ACK
  816.         ; Now construct the response, and queue for sending by IP
  817. ;        mov     eax, EMPTY_QUEUE
  818. ;        call    dequeue
  819.  ;       cmp     ax, NO_BUFFER
  820.         pop     ebx
  821.         je      .exit
  822.  
  823.         push    eax
  824.  
  825.         xor     ecx, ecx
  826.         xor     esi, esi
  827. ;        stdcall build_tcp_Packet, [sockAddr]
  828.  
  829. ;        mov     eax, NET1OUT_QUEUE
  830. ;;;        mov     edx, [stack_ip]
  831. ;        mov     ecx, [sockAddr]
  832.  ;       cmp     edx, [ecx + SOCKET.RemoteIP]
  833.   ;      jne     .not_local
  834.    ;     mov     eax, IPIN_QUEUE
  835.  
  836.   .not_local:
  837.         ; Send it.
  838.         pop     ebx
  839. ;;;        call    queue
  840.  
  841.   .exit:
  842.         ret
  843. endp
  844.  
  845.  
  846. proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
  847.         ; In this case, we are expecting an ACK Packet
  848.         ; For now, if the Packet is an ACK, process it,
  849.         ; If not, ignore it
  850.  
  851.         test    [edx + 20 + TCP_Packet.Flags], TH_RST
  852.         jz      .check_ack
  853.  
  854.         push    [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
  855.         pop     [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
  856.  
  857.         mov     [ebx + SOCKET.TCBState], TCB_LISTEN
  858.         jmp     .exit
  859.  
  860.   .check_ack:
  861.         ; Look at control flags - expecting an ACK
  862.         test    [edx + 20 + TCP_Packet.Flags], TH_ACK
  863.         jz      .exit
  864.  
  865.         mov     [ebx + SOCKET.TCBState], TCB_ESTABLISHED
  866.  
  867.   .exit:
  868.         ret
  869. endp
  870.  
  871.  
  872. proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
  873.         ; Here we are expecting data, or a request to close
  874.         ; OR both...
  875.  
  876.         ; Did we receive a FIN or RST?
  877.         test    [edx + 20 + TCP_Packet.Flags], TH_FIN
  878.         jz      .check_ack
  879.  
  880.         ; It was a fin or reset.
  881.  
  882.         ; Remove resend entries from the queue  - I dont want to send any more data
  883.         pushad
  884.  
  885.         ; get skt #
  886.         stdcall net_socket_addr_to_num, ebx
  887.  
  888.         mov     esi, resendQ
  889.         mov     ecx, 0
  890.  
  891.   .next_resendq:
  892. ;        cmp     ecx, NUMRESENDENTRIES
  893. ;        je      .last_resendq       ; None left
  894. ;        cmp     [esi + 4], eax
  895. ;        je      @f                  ; found one
  896. ;        inc     ecx
  897. ;        add     esi, 8
  898. ;        jmp     .next_resendq
  899.  
  900.     @@: mov     dword[esi + 4], 0
  901.         inc     ecx
  902.         add     esi, 8
  903.         jmp     .next_resendq
  904.  
  905.   .last_resendq:
  906.         popad
  907.  
  908.     @@: ; Send an ACK to that fin, and enter closewait state
  909.  
  910.         mov     [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
  911.         lea     esi, [ebx + SOCKET.RCV_NXT]
  912.         mov     eax, [esi]              ; save original
  913.         call    inc_inet_esi
  914.         ;; jmp    ste_ack - NO, there may be data
  915.  
  916.   .check_ack:
  917.         ; Check that we received an ACK
  918.         test    [edx + 20 + TCP_Packet.Flags], TH_ACK
  919.         jz      .exit
  920.  
  921.         ; TODO - done, I think!
  922.         ; First, look at the incoming window. If this is less than or equal to 1024,
  923.         ; Set the socket window timer to 1. This will stop an additional Packets being queued.
  924.         ; ** I may need to tweak this value, since I do not know how many Packets are already queued
  925.         mov     cx, [edx + 20 + TCP_Packet.Window]
  926.         xchg    cl, ch
  927.         cmp     cx, 1024
  928.         ja      @f
  929.  
  930.         mov     [ebx + SOCKET.wndsizeTimer], 1
  931.  
  932.     @@: ; OK, here is the deal
  933.         ; My recv.nct field holds the seq of the expected next rec byte
  934.         ; if the recevied sequence number is not equal to this, do not
  935.         ; increment the recv.nxt field, do not copy data - just send a
  936.         ; repeat ack.
  937.  
  938.         ; recv.nxt is in dword [edx+24], in inet format
  939.         ; recv seq is in [sktAddr]+56, in inet format
  940.         ; just do a comparision
  941.         mov     ecx, [ebx + SOCKET.RCV_NXT]
  942.         cmp     [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
  943.         jne     @f
  944.         mov     ecx, eax
  945.  
  946.     @@: cmp     ecx, [edx + 20 + TCP_Packet.SequenceNumber]
  947.         jne     .ack
  948.  
  949.  
  950.         ; Read the data bytes, store in socket buffer
  951. ;        movzx   ecx, [edx + IP_Packet.TotalLength]
  952.         xchg    cl, ch
  953.         sub     ecx, 40                    ; Discard 40 bytes of header
  954.         ja      .data                      ; Read data, if any
  955.  
  956.         ; If we had received a fin, we need to ACK it.
  957.         cmp     [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
  958.         je      .ack
  959.         jmp     .exit
  960.  
  961.   .data:
  962.         push    ebx
  963.         add     ebx, SOCKET.lock
  964.         call    wait_mutex
  965.         pop     ebx
  966.  
  967.         push    ecx
  968.         push    [ebx + SOCKET.PID]      ; get socket owner PID
  969.         mov     eax, [ebx + SOCKET.rxDataCount]
  970.         add     eax, ecx
  971.         cmp     eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
  972.         ja      .overflow
  973.  
  974.         mov     [ebx + SOCKET.rxDataCount], eax      ; increment the count of bytes in buffer
  975.  
  976.         ; point to the location to store the data
  977.         lea     edi, [ebx + eax + SOCKETHEADERSIZE]
  978.         sub     edi, ecx
  979.  
  980.         add     edx, 40        ; edx now points to the data
  981.         mov     esi, edx
  982.  
  983.         cld
  984.         rep     movsb          ; copy the data across
  985.         mov     [ebx + SOCKET.lock], 0  ; release mutex
  986.  
  987.         ; flag an event to the application
  988.         pop     eax
  989.         mov     ecx, 1
  990.         mov     esi, TASK_DATA + TASKDATA.pid
  991.  
  992.   .next_pid:
  993.         cmp     [esi], eax
  994.         je      .found_pid
  995.         inc     ecx
  996.         add     esi, 0x20
  997.         cmp     ecx, [TASK_COUNT]
  998.         jbe     .next_pid
  999.  
  1000.   .found_pid:
  1001.         shl     ecx, 8
  1002.         or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
  1003.  
  1004.         pop     ecx
  1005.  
  1006.         ; Update our recv.nxt field
  1007.         lea     esi, [ebx + SOCKET.RCV_NXT]
  1008.         call    add_inet_esi
  1009.  
  1010.   .ack:
  1011.         ; Send an ACK
  1012.         ; Now construct the response, and queue for sending by IP
  1013. ;        mov     eax, EMPTY_QUEUE
  1014. ;        call    dequeue
  1015. ;        cmp     ax, NO_BUFFER
  1016.         je      .exit
  1017.  
  1018.         push    eax
  1019.  
  1020.         mov     bl, TH_ACK
  1021.         xor     ecx, ecx
  1022.         xor     esi, esi
  1023. ;        stdcall build_tcp_Packet, [sockAddr]
  1024.  
  1025. ;        mov     eax, NET1OUT_QUEUE
  1026.  
  1027. ;;;        mov     edx, [stack_ip]
  1028. ;        mov     ecx, [sockAddr]
  1029. ;        cmp     edx, [ecx + SOCKET.RemoteIP]
  1030. ;        jne     .not_local
  1031.  ;       mov     eax, IPIN_QUEUE
  1032.  
  1033.   .not_local:
  1034.         ; Send it.
  1035.         pop     ebx
  1036. ;;;        call    queue
  1037.  
  1038.   .exit:
  1039.         ret
  1040.   .overflow:
  1041.         ; no place in buffer
  1042.         ; so simply restore stack and exit
  1043.         pop     eax ecx
  1044.         mov     [ebx + SOCKET.lock], 0
  1045.         ret
  1046. endp
  1047.  
  1048.  
  1049. proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
  1050.         ; We can either receive an ACK of a fin, or a fin
  1051.         mov     al, [edx + 20 + TCP_Packet.Flags]
  1052.         and     al, TH_FIN + TH_ACK
  1053.  
  1054.         cmp     al, TH_ACK
  1055.         jne     @f
  1056.  
  1057.         ; It was an ACK
  1058.         mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
  1059.         jmp     .exit
  1060.  
  1061.     @@: mov     [ebx + SOCKET.TCBState], TCB_CLOSING
  1062.         cmp     al, TH_FIN
  1063.         je      @f
  1064.         mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
  1065.  
  1066.     @@: lea     esi, [ebx + SOCKET.RCV_NXT]
  1067.         call    inc_inet_esi
  1068.  
  1069.         ; Send an ACK
  1070. ;        mov     eax, EMPTY_QUEUE
  1071. ;        call    dequeue
  1072. ;        cmp     ax, NO_BUFFER
  1073.         je      .exit
  1074.  
  1075.         push    eax
  1076.  
  1077.         mov     bl, TH_ACK
  1078.         xor     ecx, ecx
  1079.         xor     esi, esi
  1080. ;        stdcall build_tcp_Packet, [sockAddr]
  1081.  
  1082. ;        mov     eax, NET1OUT_QUEUE
  1083. ;;;        mov     edx, [stack_ip]
  1084. ;        mov     ecx, [sockAddr]
  1085.  ;       cmp     edx, [ecx + SOCKET.RemoteIP]
  1086.  ;       jne     .not_local
  1087. ;        mov     eax, IPIN_QUEUE
  1088.  
  1089.   .not_local:
  1090.         ; Send it.
  1091.         pop     ebx
  1092. ;;;        call    queue
  1093.  
  1094.   .exit:
  1095.         ret
  1096. endp
  1097.  
  1098.  
  1099. proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
  1100.         test    [edx + 20 + TCP_Packet.Flags], TH_FIN
  1101.         jz      .exit
  1102.  
  1103.         ; Change state, as we have a fin
  1104.         mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
  1105.  
  1106.         lea     esi, [ebx + SOCKET.RCV_NXT]
  1107.         call    inc_inet_esi
  1108.  
  1109.         ; Send an ACK
  1110. ;        mov     eax, EMPTY_QUEUE
  1111. ;        call    dequeue
  1112.  ;;       cmp     ax, NO_BUFFER
  1113.   ;      je      .exit
  1114.  
  1115.         push    eax
  1116.  
  1117.         mov     bl, TH_ACK
  1118.         xor     ecx, ecx
  1119.         xor     esi, esi
  1120. ;        stdcall build_tcp_Packet, [sockAddr]
  1121.  
  1122. ;        mov     eax, NET1OUT_QUEUE
  1123. ;;;        mov     edx, [stack_ip]
  1124.         mov     ecx, [sockAddr]
  1125.         cmp     edx, [ecx + SOCKET.RemoteIP]
  1126.         jne     .not_local
  1127. ;        mov     eax, IPIN_QUEUE
  1128.  
  1129.   .not_local:
  1130.         ; Send it.
  1131.         pop     ebx
  1132. ;;;        call    queue
  1133.  
  1134.   .exit:
  1135.         ret
  1136. endp
  1137.  
  1138.  
  1139. proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
  1140.         ; Intentionally left empty
  1141.         ; socket_close_tcp handles this
  1142.         ret
  1143. endp
  1144.  
  1145.  
  1146. proc stateTCB_CLOSING stdcall, sockAddr:DWORD
  1147.         ; We can either receive an ACK of a fin, or a fin
  1148.         test    [edx + 20 + TCP_Packet.Flags], TH_ACK
  1149.         jz      .exit
  1150.  
  1151.         mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
  1152.  
  1153.   .exit:
  1154.         ret
  1155. endp
  1156.  
  1157.  
  1158. proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
  1159.         ; Look at control flags - expecting an ACK
  1160.         test    [edx + 20 + TCP_Packet.Flags], TH_ACK
  1161.         jz      .exit
  1162.  
  1163.         ; delete the socket
  1164.         stdcall net_socket_free, ebx
  1165.  
  1166.   .exit:
  1167.         ret
  1168. endp
  1169.  
  1170.  
  1171. proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
  1172.         ret
  1173. endp
  1174.  
  1175.  
  1176. proc stateTCB_CLOSED stdcall, sockAddr:DWORD
  1177.         ret
  1178. endp
  1179.  
  1180.  
  1181.  
  1182. ;; [53.7] Send data through STREAM socket
  1183. ;
  1184. ; @param EBX is socket number
  1185. ; @param ECX is application data size (number of bytes to send)
  1186. ; @param EDX is pointer to application data buffer
  1187. ; @return 0 (sent successfully) or -1 (error) in EAX
  1188. ;;
  1189. ;proc socket_write_tcp stdcall
  1190. ;local sockAddr dd ?
  1191.  
  1192. ;        DEBUGF  1, "socket_write_tcp(0x%x)\n", ebx
  1193.         stdcall net_socket_num_to_addr, ebx
  1194.         or      eax, eax
  1195.         jz      .error
  1196.  
  1197.         mov     ebx, eax
  1198. ;        mov     [sockAddr], ebx
  1199.  
  1200.         ; If the sockets window timer is nonzero, do not queue Packet
  1201.         cmp     [ebx + SOCKET.wndsizeTimer], 0
  1202.         jne     .error
  1203.  
  1204. ;        mov     eax, EMPTY_QUEUE
  1205. ;        call    dequeue
  1206. ;        cmp     ax, NO_BUFFER
  1207.  ;       je      .error
  1208.  
  1209.         push    eax
  1210.  
  1211.         ; Get the address of the callers data
  1212.         mov     edi, [TASK_BASE]
  1213.         add     edi, TASKDATA.mem_start
  1214.         add     edx, [edi]
  1215.         mov     esi, edx
  1216.  
  1217.         pop     eax
  1218.         push    eax
  1219.  
  1220.         push    ecx
  1221.         mov     bl, TH_ACK
  1222. ;        stdcall build_tcp_Packet, [sockAddr]
  1223.         pop     ecx
  1224.  
  1225.         ; Check destination IP address.
  1226.         ; If it is the local host IP, route it back to IP_RX
  1227.  
  1228.         pop     ebx
  1229.         push    ecx
  1230.  
  1231. ;        mov     eax, NET1OUT_QUEUE
  1232. ;;; TODO: get device id in edx
  1233.         xor     edx, edx
  1234.  
  1235.         shl     edx, 2
  1236.         mov     edx, [IP_LIST+edx]
  1237. ;        mov     ecx, [sockAddr]
  1238.  ;       cmp     edx, [ecx + SOCKET.RemoteIP]
  1239.   ;      jne     .not_local
  1240.    ;     mov     eax, IPIN_QUEUE
  1241.  
  1242.   .not_local:
  1243.         pop     ecx
  1244.         push    ebx                 ; save ipbuffer number
  1245.  
  1246. ;;;;        call    queue
  1247.  
  1248. ;        mov     esi, [sockAddr]
  1249.  
  1250.         ; increament SND.NXT in socket
  1251.         ; Amount to increment by is in ecx
  1252.         add     esi, SOCKET.SND_NXT
  1253.         call    add_inet_esi
  1254.  
  1255.         pop     ebx
  1256.  
  1257.         ; Copy the IP buffer to a resend queue
  1258.         ; If there isn't one, dont worry about it for now
  1259.         mov     esi, resendQ
  1260.         mov     ecx, 0
  1261.  
  1262.   .next_resendq:
  1263. ;        cmp     ecx, NUMRESENDENTRIES
  1264.         je      .exit              ; None found
  1265.         cmp     dword[esi + 4], 0
  1266.         je      @f                 ; found one
  1267.         inc     ecx
  1268.         add     esi, 8
  1269.         jmp     .next_resendq
  1270.  
  1271.     @@: push    ebx
  1272.  
  1273.         ; OK, we have a buffer descriptor ptr in esi.
  1274.         ; resend entry # in ecx
  1275.         ;  Populate it
  1276.         ;  socket #
  1277.         ;  retries count
  1278.         ;  retry time
  1279.         ;  fill IP buffer associated with this descriptor
  1280.  
  1281. ;        stdcall net_socket_addr_to_num, [sockAddr]
  1282.         mov     [esi + 4], eax
  1283.         mov     byte[esi + 1], TCP_RETRIES
  1284.         mov     word[esi + 2], TCP_TIMEOUT
  1285.  
  1286.         inc     ecx
  1287.         ; Now get buffer location, and copy buffer across. argh! more copying,,
  1288. ;        mov     edi, resendBuffer - IPBUFFSIZE
  1289.  
  1290. ;    @@: add     edi, IPBUFFSIZE
  1291.         loop    @b
  1292.  
  1293.         ; we have dest buffer location in edi
  1294.         pop     eax
  1295.         ; convert source buffer pointer eax to the absolute address
  1296. ;        mov     ecx, IPBUFFSIZE
  1297. ;        mul     ecx
  1298. ;        add     eax, IPbuffs
  1299. ;        mov     esi, eax
  1300.  
  1301.         ; do copy
  1302. ;        mov     ecx, IPBUFFSIZE
  1303. ;        cld
  1304.         rep     movsb
  1305.  
  1306.   .exit:
  1307.         xor     eax, eax
  1308.         ret
  1309.  
  1310.   .error:
  1311.         or      eax, -1
  1312.         ret
  1313. ;endp
  1314.  
  1315.  
  1316.  
  1317. ;***************************************************************************
  1318. ;   Function
  1319. ;      checksum
  1320. ;
  1321. ;   Description
  1322. ;       checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
  1323. ;       Dont break anything; Most registers are used by the caller
  1324. ;       This code is derived from the 'C' source, cksum.c, in the book
  1325. ;       Internetworking with TCP/IP Volume II by D.E. Comer
  1326. ;
  1327. ;***************************************************************************
  1328.  
  1329.  
  1330. checksum:
  1331.     pusha
  1332. ;    mov     eax, [checkAdd1]
  1333.     xor     edx, edx                  ; edx is the accumulative checksum
  1334.     xor     ebx, ebx
  1335. ;    mov     cx, [checkSize1]
  1336.     shr     cx, 1
  1337.     jz      cs1_1
  1338.  
  1339. cs1:
  1340.     mov     bh, [eax]
  1341.     mov     bl, [eax + 1]
  1342.  
  1343.     add     eax, 2
  1344.     add     edx, ebx
  1345.  
  1346.     loopw   cs1
  1347.  
  1348. cs1_1:
  1349. ;    and     word [checkSize1], 0x01
  1350.     jz      cs_test2
  1351.  
  1352.     mov     bh, [eax]
  1353.     xor     bl, bl
  1354.  
  1355.     add     edx, ebx
  1356.  
  1357. cs_test2:
  1358. ;    mov     cx, [checkSize2]
  1359.     cmp     cx, 0
  1360.     jz      cs_exit                     ; Finished if no 2nd buffer
  1361.  
  1362. ;    mov     eax, [checkAdd2]
  1363.  
  1364.     shr     cx, 1
  1365.     jz      cs2_1
  1366.  
  1367. cs2:
  1368.     mov     bh, [eax]
  1369.     mov     bl, [eax + 1]
  1370.  
  1371.     add     eax, 2
  1372.     add     edx, ebx
  1373.  
  1374.     loopw   cs2
  1375.  
  1376. cs2_1:
  1377. ;    and     word [checkSize2], 0x01
  1378.     jz      cs_exit
  1379.  
  1380.     mov     bh, [eax]
  1381.     xor     bl, bl
  1382.  
  1383.     add     edx, ebx
  1384.  
  1385. cs_exit:
  1386.     mov     ebx, edx
  1387.  
  1388.     shr     ebx, 16
  1389.     and     edx, 0xffff
  1390.     add     edx, ebx
  1391.     mov     eax, edx
  1392.     shr     eax, 16
  1393.     add     edx, eax
  1394.     not     dx
  1395.  
  1396. ;    mov     [checkResult], dx
  1397.     popa
  1398.     ret
  1399.  
  1400.