Subversion Repositories Kolibri OS

Rev

Rev 1543 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. 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. ;;    Based on the code of 4.4BSD                                  ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. $Revision: 1716 $
  20.  
  21. ; Socket states
  22. TCB_CLOSED              equ 0
  23. TCB_LISTEN              equ 1
  24. TCB_SYN_SENT            equ 2
  25. TCB_SYN_RECEIVED        equ 3
  26. TCB_ESTABLISHED         equ 4
  27. TCB_CLOSE_WAIT          equ 5
  28. TCB_FIN_WAIT_1          equ 6
  29. TCB_CLOSING             equ 7
  30. TCB_LAST_ACK            equ 8
  31. TCB_FIN_WAIT_2          equ 9
  32. TCB_TIMED_WAIT          equ 10
  33.  
  34. ; Socket Flags
  35. TF_ACKNOW               equ 1 shl 0     ; ack peer immediately
  36. TF_DELACK               equ 1 shl 1     ; ack, but try to delay it
  37. TF_NODELAY              equ 1 shl 2     ; don't delay packets to coalesce
  38. TF_NOOPT                equ 1 shl 3     ; don't use tcp options
  39. TF_SENTFIN              equ 1 shl 4     ; have sent FIN
  40. TF_REQ_SCALE            equ 1 shl 5     ; have/will request window scaling
  41. TF_RCVD_SCALE           equ 1 shl 6     ; other side has requested scaling
  42. TF_REQ_TSTMP            equ 1 shl 7     ; have/will request timestamps
  43. TF_RCVD_TSTMP           equ 1 shl 8     ; a timestamp was received in SYN
  44. TF_SACK_PERMIT          equ 1 shl 9     ; other side said I could SACK
  45.  
  46. ; Segment flags
  47. TH_FIN                  equ 1 shl 0
  48. TH_SYN                  equ 1 shl 1
  49. TH_RST                  equ 1 shl 2
  50. TH_PUSH                 equ 1 shl 3
  51. TH_ACK                  equ 1 shl 4
  52. TH_URG                  equ 1 shl 5
  53.  
  54. ; Segment header options
  55. TCP_OPT_EOL             equ 0           ; End of option list.
  56. TCP_OPT_NOP             equ 1           ; No-Operation.
  57. TCP_OPT_MAXSEG          equ 2           ; Maximum Segment Size.
  58. TCP_OPT_WINDOW          equ 3           ; window scale
  59. TCP_OPT_TIMESTAMP       equ 8
  60.  
  61. ; Fundamental timer values
  62. TCP_time_MSL            equ 47          ; max segment lifetime (30s)
  63. TCP_time_re_min         equ 2           ; min retransmission (1,28s)
  64. TCP_time_re_max         equ 100         ; max retransmission (64s)
  65. TCP_time_pers_min       equ 8           ; min persist (5,12s)
  66. TCP_time_pers_max       equ 94          ; max persist (60,16s)
  67. TCP_time_keep_init      equ 118         ; connectione stablishment (75,52s)
  68. TCP_time_keep_idle      equ 4608        ; idle time before 1st probe (2h)
  69. TCP_time_keep_interval  equ 118         ; between probes when no response (75,52s)
  70. TCP_time_rtt_default    equ 5           ; default Round Trip Time (3,2s)
  71.  
  72. ; timer constants
  73. TCP_max_rxtshift        equ 12          ; max retransmissions waiting for ACK
  74. TCP_max_keepcnt         equ 8           ; max keepalive probes
  75.  
  76. ;
  77. TCP_max_winshift        equ 14
  78. TCP_max_win             equ 65535
  79.  
  80. struct  TCP_segment
  81.         .SourcePort             dw ?
  82.         .DestinationPort        dw ?
  83.         .SequenceNumber         dd ?
  84.         .AckNumber              dd ?
  85.         .DataOffset             db ?    ; DataOffset[0-3 bits] and Reserved[4-7]
  86.         .Flags                  db ?    ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
  87.         .Window                 dw ?
  88.         .Checksum               dw ?
  89.         .UrgentPointer          dw ?
  90.         .Data:                          ; ..or options
  91. ends
  92.  
  93. align 4
  94. uglobal
  95.         TCP_segments_tx         rd IP_MAX_INTERFACES
  96.         TCP_segments_rx         rd IP_MAX_INTERFACES
  97.         TCP_bytes_rx            rq IP_MAX_INTERFACES
  98.         TCP_bytes_tx            rq IP_MAX_INTERFACES
  99.         TCP_sequence_num        dd ?
  100. endg
  101.  
  102.  
  103. ;-----------------------------------------------------------------
  104. ;
  105. ; TCP_init
  106. ;
  107. ;  This function resets all TCP variables
  108. ;
  109. ;-----------------------------------------------------------------
  110. macro   TCP_init {
  111.  
  112.         xor     eax, eax
  113.         mov     edi, TCP_segments_tx
  114.         mov     ecx, (6*IP_MAX_INTERFACES)
  115.         rep     stosd
  116.  
  117.         pseudo_random   eax
  118.         mov     [TCP_sequence_num], eax
  119.  
  120. }
  121.  
  122.  
  123. ;----------------------
  124. ;
  125. ;
  126. ;----------------------
  127. macro   TCP_timer_160ms {
  128.  
  129. local   .loop
  130. local   .exit
  131.  
  132.         mov     eax, net_sockets
  133.   .loop:
  134.         mov     eax, [eax + SOCKET.NextPtr]
  135.         or      eax, eax
  136.         jz      .exit
  137.  
  138.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP           ;;; We should also check if family is AF_INET
  139.         jne     .loop
  140.  
  141.         dec     [eax + TCP_SOCKET.timer_ack]
  142.         jnz     .loop
  143.  
  144.         DEBUGF  1,"TCP ack for socket %x expired, time to piggyback!\n", eax
  145.  
  146.         push    eax
  147.         call    TCP_respond_socket
  148.         pop     eax
  149.  
  150.         jmp     .loop
  151.  
  152.   .exit:
  153.  
  154. }
  155.  
  156.  
  157. ;-----------------------------------------------------------------
  158. ;
  159. ;
  160. ;-----------------------------------------------------------------
  161. macro   TCP_timer_640ms {
  162.  
  163. local   .loop
  164. local   .exit
  165.  
  166. ; Update TCP sequence number
  167.  
  168.         add     [TCP_sequence_num], 64000
  169.  
  170. ; scan through all the active TCP sockets, decrementing ALL timers
  171. ; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
  172.  
  173.         mov     eax, net_sockets
  174.   .loop:
  175.         mov     eax, [eax + SOCKET.NextPtr]
  176.   .check_only:
  177.         or      eax, eax
  178.         jz      .exit
  179.  
  180.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP     ;;; We should also check if family is AF_INET
  181.         jne     .loop
  182.  
  183.         inc     [eax + TCP_SOCKET.t_idle]
  184.         dec     [eax + TCP_SOCKET.timer_retransmission]
  185.         jnz     .check_more2
  186.  
  187.         DEBUGF  1,"socket %x: Retransmission timer expired\n", eax
  188.  
  189.         push    eax
  190.         call    TCP_output
  191.         pop     eax
  192.  
  193.   .check_more2:
  194.         dec     [eax + TCP_SOCKET.timer_keepalive]
  195.         jnz     .check_more3
  196.  
  197.         DEBUGF  1,"socket %x: Keepalive expired\n", eax
  198.  
  199.         ;;; TODO: check socket state and handle accordingly
  200.  
  201.   .check_more3:
  202.         dec     [eax + TCP_SOCKET.timer_timed_wait]
  203.         jnz     .check_more5
  204.  
  205.         DEBUGF  1,"socket %x: 2MSL timer expired\n", eax
  206.  
  207.   .check_more5:
  208.         dec     [eax + TCP_SOCKET.timer_persist]
  209.         jnz     .loop
  210.  
  211.         DEBUGF  1,"socket %x: persist timer expired\n", eax
  212.  
  213.         jmp     .loop
  214.   .exit:
  215. }
  216.  
  217.  
  218.  
  219.  
  220. macro   TCP_checksum IP1, IP2 {
  221.  
  222. ;-------------
  223. ; Pseudoheader
  224.  
  225.         ; protocol type
  226.         mov     edx, IP_PROTO_TCP
  227.  
  228.         ; source address
  229.         add     dl, byte [IP1+1]
  230.         adc     dh, byte [IP1+0]
  231.         adc     dl, byte [IP1+3]
  232.         adc     dh, byte [IP1+2]
  233.  
  234.         ; destination address
  235.         adc     dl, byte [IP2+1]
  236.         adc     dh, byte [IP2+0]
  237.         adc     dl, byte [IP2+3]
  238.         adc     dh, byte [IP2+2]
  239.  
  240.         ; size
  241.         adc     dl, cl
  242.         adc     dh, ch
  243.  
  244. ;---------------------
  245. ; Real header and data
  246.  
  247.         push    esi
  248.         call    checksum_1
  249.         call    checksum_2
  250.         pop     esi
  251.  
  252. }       ; returns in dx only
  253.  
  254.  
  255. macro   TCP_sendseqinit ptr {
  256.  
  257.         push    edi                     ;;;; i dont like this static use of edi
  258.         mov     edi, [ptr + TCP_SOCKET.ISS]
  259.         mov     [ptr + TCP_SOCKET.SND_UP], edi
  260.         mov     [ptr + TCP_SOCKET.SND_MAX], edi
  261.         mov     [ptr + TCP_SOCKET.SND_NXT], edi
  262.         mov     [ptr + TCP_SOCKET.SND_UNA], edi
  263.         pop     edi
  264.  
  265. }
  266.  
  267. macro   TCP_rcvseqinit ptr {
  268.  
  269.         push    edi
  270.         mov     edi, [ptr + TCP_SOCKET.IRS]
  271.         inc     edi
  272.         mov     [ptr + TCP_SOCKET.RCV_NXT], edi
  273.         mov     [ptr + TCP_SOCKET.RCV_ADV], edi
  274.         pop     edi
  275.  
  276. }
  277.  
  278.  
  279.  
  280. ;-----------------------------------------------------------------
  281. ;
  282. ; TCP_input:
  283. ;
  284. ;  IN:  [esp] = ptr to buffer
  285. ;       [esp+4] = buffer size
  286. ;       ebx = ptr to device struct
  287. ;       ecx = segment size
  288. ;       edx = ptr to TCP segment
  289. ;
  290. ;       esi = ipv4 source address
  291. ;       edi = ipv4 dest   address
  292. ;
  293. ;  OUT: /
  294. ;
  295. ;-----------------------------------------------------------------
  296. align 4
  297. TCP_input:
  298.  
  299.        DEBUGF  1,"TCP_input size=%u\n", ecx
  300. ; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length.
  301.  
  302.         movzx   eax, [edx + TCP_segment.DataOffset]
  303.         and     eax, 0xf0
  304.         shr     al, 2
  305.  
  306.         DEBUGF  1,"headersize=%u\n", eax
  307.  
  308.         cmp     eax, 20
  309.         jl      .drop
  310.  
  311. ;-------------------------------
  312. ; Now, re-calculate the checksum
  313.  
  314.         push    eax ecx edx
  315.         pushw   [edx + TCP_segment.Checksum]
  316.         mov     [edx + TCP_segment.Checksum], 0
  317.         push    esi edi
  318.         mov     esi, edx
  319.         TCP_checksum (esp), (esp+4)
  320.         pop     esi edi ; yes, swap them (we dont need dest addr)
  321.         pop     cx      ; previous checksum
  322.         cmp     cx, dx
  323.         pop     edx ecx esi
  324.         jnz     .drop
  325.  
  326.         DEBUGF  1,"Checksum is correct\n"
  327.  
  328.         sub     ecx, esi        ; update packet size
  329.         jl      .drop
  330.         DEBUGF  1,"we got %u bytes of data\n", ecx
  331.  
  332. ;-----------------------------------------------------------------------------------------
  333. ; Check if this packet has a timestamp option (We do it here so we can process it quickly)
  334.  
  335.         cmp     esi, 20 + 12                                    ; Timestamp option is 12 bytes
  336.         jl      .no_timestamp
  337.         je      .is_ok
  338.  
  339.         cmp     byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list
  340.         jne     .no_timestamp
  341.  
  342.   .is_ok:
  343.         test    [edx + TCP_segment.Flags], TH_SYN               ; SYN flag must not be set
  344.         jnz     .no_timestamp
  345.  
  346.         cmp     dword [edx + TCP_segment.Data], 0x0101080a      ; Timestamp header
  347.         jne     .no_timestamp
  348.  
  349.         DEBUGF  1,"timestamp ok\n"
  350.  
  351.         ; TODO: Parse the option
  352.         ; TODO: Set a Bit in the TCP to tell all options are parsed
  353.  
  354.   .no_timestamp:
  355.  
  356. ;-------------------------------------------
  357. ; Convert Big-endian values to little endian
  358.  
  359.         ntohd   [edx + TCP_segment.SequenceNumber]
  360.         ntohd   [edx + TCP_segment.AckNumber]
  361.  
  362.         ntohw   [edx + TCP_segment.Window]
  363.         ntohw   [edx + TCP_segment.UrgentPointer]
  364.         ntohw   [edx + TCP_segment.SourcePort]
  365.         ntohw   [edx + TCP_segment.DestinationPort]
  366.  
  367. ;------------------------------------------------------------
  368. ; Next thing to do is find the TCB (thus, the socket pointer)
  369.  
  370. ; IP Packet TCP Destination Port = local Port
  371. ; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
  372. ; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
  373.  
  374.         mov     ebx, net_sockets
  375.  
  376.   .socket_loop:
  377.         mov     ebx, [ebx + SOCKET.NextPtr]
  378.         or      ebx, ebx
  379.         jz      .drop_with_reset
  380.  
  381.         cmp     [ebx + SOCKET.Domain], AF_INET4
  382.         jne     .socket_loop
  383.  
  384.         cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
  385.         jne     .socket_loop
  386.  
  387.         mov     ax, [edx + TCP_segment.DestinationPort]
  388.         cmp     [ebx + TCP_SOCKET.LocalPort], ax
  389.         jne     .socket_loop
  390.  
  391.         mov     eax, [ebx + IP_SOCKET.RemoteIP]
  392.         cmp     eax, edi                        ; edi is source ip from packet
  393.         je      @f
  394.         test    eax, eax
  395.         jnz     .socket_loop
  396.        @@:
  397.  
  398.         mov     ax, [ebx + TCP_SOCKET.RemotePort]
  399.         cmp     [edx + TCP_segment.SourcePort] , ax
  400.         je      .found_socket
  401.         test    ax, ax
  402.         jnz     .socket_loop
  403.   .found_socket:
  404.         DEBUGF  1,"Socket ptr: %x\n", ebx
  405.  
  406. ; ebx now contains the pointer to the socket
  407.  
  408. ;----------------------------
  409. ; Check if socket isnt closed
  410.  
  411.         cmp     [ebx + TCP_SOCKET.t_state], TCB_CLOSED
  412.         je      .drop
  413.  
  414. ;----------------
  415. ; Lock the socket
  416.  
  417. ;;        add     ebx, SOCKET.lock ; TODO: figure out if we should lock now already
  418. ;;        call    wait_mutex
  419. ;;        sub     ebx, SOCKET.lock
  420.  
  421.         DEBUGF  1,"Socket locked\n"
  422.  
  423. ;---------------------------------------
  424. ; unscale the window into a 32 bit value
  425.  
  426.         movzx   eax, [edx + TCP_segment.Window]
  427.         push    ecx
  428.         mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
  429.         shl     eax, cl
  430.         mov     dword [edx + TCP_segment.Window], eax   ; word after window is checksum, we dont need checksum anymore
  431.         pop     ecx
  432.  
  433. ;-----------------------------------
  434. ; Is this socket a listening socket?
  435.  
  436.         test    [ebx + SOCKET.options], SO_ACCEPTCON
  437.         jz      .no_listening_socket
  438.  
  439.         call    SOCKET_fork
  440.         jz      .drop
  441.  
  442.         push    [edx + TCP_segment.DestinationPort]
  443.         pop     [eax + TCP_SOCKET.LocalPort]
  444.  
  445.         push    [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress]     ;;; FIXME
  446.         pop     [eax + IP_SOCKET.LocalIP]
  447.  
  448.         push    [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress]     ;;; FIXME
  449.         pop     [eax + IP_SOCKET.RemoteIP]
  450.  
  451.         mov     [eax + TCP_SOCKET.t_state], TCB_LISTEN
  452.  
  453.         jmp     .not_uni_xfer
  454.  
  455.   .no_listening_socket:
  456.  
  457. ;-------------------------------------
  458. ; Reset idle timer and keepalive timer
  459.  
  460.         mov     [ebx + TCP_SOCKET.t_idle], 0
  461.         mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
  462.  
  463. ;--------------------
  464. ; Process TCP options
  465.  
  466.         cmp     esi, 20                         ; esi is headersize
  467.         je      .no_options
  468.  
  469.         DEBUGF  1,"Segment has options\n"
  470.  
  471.         cmp     [ebx + TCP_SOCKET.t_state], TCB_LISTEN          ; no options when in listen state
  472.         jz      .not_uni_xfer                                   ; also no header prediction
  473.  
  474.         lea     edi, [edx + TCP_segment.Data]
  475.         lea     eax, [edx + esi]
  476.  
  477.   .opt_loop:
  478.         cmp     edi, eax
  479.         jge     .no_options
  480.  
  481.         cmp     byte [edi], TCP_OPT_EOL         ; end of option list?
  482.         jz      .no_options
  483.  
  484.         cmp     byte [edi], TCP_OPT_NOP         ; nop ?
  485.         jz      .opt_nop
  486.  
  487.         cmp     byte [edi], TCP_OPT_MAXSEG
  488.         je      .opt_maxseg
  489.  
  490.         cmp     byte [edi], TCP_OPT_WINDOW
  491.         je      .opt_window
  492.  
  493.         cmp     byte [edi], TCP_OPT_TIMESTAMP
  494.         je      .opt_timestamp
  495.  
  496.         jmp     .no_options     ; If we reach here, some unknown options were received, skip them all!
  497.  
  498.   .opt_nop:
  499.         inc     edi
  500.         jmp     .opt_loop
  501.  
  502.   .opt_maxseg:
  503.         cmp     byte [edi+1], 4
  504.         jne     .no_options             ; error occured, ignore all options!
  505.  
  506.         test    [edx + TCP_segment.Flags], TH_SYN
  507.         jz      @f
  508.  
  509.         movzx   eax, word[edi+2]
  510.         rol     ax, 8
  511.         DEBUGF  1,"Maxseg: %u\n", ax
  512.  
  513.         mov     [ebx + TCP_SOCKET.t_maxseg], eax
  514.  
  515.        @@:
  516.         add     edi, 4
  517.         jmp     .opt_loop
  518.  
  519.  
  520.   .opt_window:
  521.         cmp     byte [edi+1], 3
  522.         jne     .no_options
  523.  
  524.         test    [edx + TCP_segment.Flags], TH_SYN
  525.         jz      @f
  526.  
  527.         DEBUGF  1,"Got window option\n"
  528.  
  529.         ;;;;;
  530.        @@:
  531.         add     edi, 3
  532.         jmp     .opt_loop
  533.  
  534.  
  535.   .opt_timestamp:
  536.         cmp     byte [edi+1], 10
  537.         jne     .no_options
  538.  
  539.         DEBUGF  1,"Got timestamp option\n"
  540.  
  541.         ;;;;;
  542.  
  543.         add     edi, 10
  544.         jmp     .opt_loop
  545.  
  546.   .no_options:
  547.  
  548. ;-----------------------------------------------------------------------
  549. ; Time to do some header prediction (Original Principle by Van Jacobson)
  550.  
  551. ; There are two common cases for an uni-directional data transfer.
  552. ;
  553. ; General rule: the packets has no control flags, is in-sequence,
  554. ;   window width didnt change and we're not retransmitting.
  555. ;
  556. ; Second rules:
  557. ;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
  558. ;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
  559. ;
  560. ;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
  561. ;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
  562.  
  563.         cmp     [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
  564.         jnz     .not_uni_xfer
  565.  
  566.         test    [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
  567.         jnz     .not_uni_xfer
  568.  
  569.         test    [edx + TCP_segment.Flags], TH_ACK
  570.         jz      .not_uni_xfer
  571.  
  572.         mov     eax, [edx + TCP_segment.SequenceNumber]
  573.         cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
  574.         jne     .not_uni_xfer
  575.  
  576.         mov     eax, dword [edx + TCP_segment.Window]
  577.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  578.         jne     .not_uni_xfer
  579.  
  580.         mov     eax, [ebx + TCP_SOCKET.SND_NXT]
  581.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  582.         jne     .not_uni_xfer
  583.  
  584. ;---------------------------------------
  585. ; check if we are sender in the uni-xfer
  586.  
  587. ; If the following 4 conditions are all true, this segment is a pure ACK.
  588. ;
  589. ; - The segment contains no data.
  590.         test    ecx, ecx
  591.         jnz     .not_sender
  592.  
  593. ; - The congestion window is greater than or equal to the current send window.
  594. ;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
  595.         mov     eax, [ebx + TCP_SOCKET.SND_CWND]
  596.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  597.         jl      .not_uni_xfer
  598.  
  599. ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
  600.         mov     eax, [edx + TCP_segment.AckNumber]
  601.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  602.         jg      .not_uni_xfer
  603.  
  604. ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
  605.         sub     eax, [ebx + TCP_SOCKET.SND_UNA]
  606.         jle     .not_uni_xfer
  607.  
  608.         DEBUGF  1,"Header prediction: we are sender\n"
  609.  
  610. ;---------------------------------
  611. ; Packet is a pure ACK, process it
  612.  
  613. ; Update RTT estimators
  614.  
  615. ; Delete acknowledged bytes from send buffer
  616.         mov     ecx, eax
  617.         lea     eax, [ebx + STREAM_SOCKET.snd]
  618.         call    SOCKET_ring_free
  619.  
  620. ; update window pointers
  621.         mov     eax, [edx + TCP_segment.AckNumber]
  622.         dec     eax
  623.         mov     [ebx + TCP_SOCKET.SND_WL1], eax
  624.  
  625. ; Stop retransmit timer
  626.         mov     [ebx + TCP_SOCKET.timer_ack], 0
  627.  
  628. ; Awaken waiting processes
  629.         mov     eax, ebx
  630.         call    SOCKET_notify_owner
  631.  
  632. ;; Generate more output
  633. ;;        mov     eax, ebx
  634. ;;        call    TCP_output
  635. ;;
  636. ;;        jmp     .drop
  637.         jmp     .step6
  638.  
  639. ;-------------------------------------------------
  640. ; maybe we are the receiver in the uni-xfer then..
  641.  
  642.   .not_sender:
  643. ; - The amount of data in the segment is greater than 0 (data count is in ecx)
  644.  
  645. ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
  646.         mov     eax, [edx + TCP_segment.AckNumber]
  647.         cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
  648.         jne     .not_uni_xfer
  649.  
  650. ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). ;;;;;;;
  651.  
  652.         jnz     .not_uni_xfer
  653.  
  654. ;-------------------------------------
  655. ; Complete processing of received data
  656.  
  657.         DEBUGF  1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
  658.  
  659.         add     esi, edx
  660.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  661.         call    SOCKET_ring_write                       ; Add the data to the socket buffer
  662.  
  663.         mov     eax, ebx
  664.         call    SOCKET_notify_owner
  665.  
  666.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
  667.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
  668.  
  669.         jmp     .drop
  670.  
  671. ;----------------------------------------------------
  672. ; Header prediction failed, doing it the slow way..     ;;;;; current implementation of header prediction destroys some regs (ecx) !!
  673.  
  674.   .not_uni_xfer:
  675.  
  676.         DEBUGF  1,"Header prediction failed\n"          ; time to do it the "slow" way :)
  677.  
  678. ;------------------------------
  679. ; Calculate receive window size
  680.  
  681.         ;;;;
  682.  
  683.         cmp     [ebx + TCP_SOCKET.t_state], TCB_LISTEN
  684.         je      .LISTEN
  685.  
  686.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
  687.         je      .SYN_SENT
  688.  
  689. ;--------------------------------------------
  690. ; Protection Against Wrapped Sequence Numbers
  691.  
  692. ; First, check if timestamp is present
  693.  
  694. ;;;; TODO
  695.  
  696. ; Then, check if at least some bytes of data are within window
  697.  
  698. ;;;; TODO
  699.  
  700.         jmp     .trim_then_step6
  701.  
  702. ;-------------
  703. ; Passive Open
  704.  
  705. align 4
  706. .LISTEN:
  707.  
  708.         DEBUGF  1,"TCP state: listen\n"
  709.  
  710.         test    [edx + TCP_segment.Flags], TH_RST       ;;; TODO: kill new socket on error
  711.         jnz     .drop
  712.  
  713.         test    [edx + TCP_segment.Flags], TH_ACK
  714.         jnz     .drop_with_reset
  715.  
  716.         test    [edx + TCP_segment.Flags], TH_SYN
  717.         jz      .drop
  718.  
  719.  
  720.         ; TODO: check if it's a broadcast or multicast, and drop if so
  721.  
  722. ;-----------------------
  723. ; Fill in some variables
  724.  
  725.         add     [TCP_sequence_num], 64000
  726.  
  727.         push    [edx + TCP_segment.SourcePort]
  728.         pop     [eax + TCP_SOCKET.RemotePort]
  729.  
  730.         push    [edx + TCP_segment.SequenceNumber]
  731.         pop     [eax + TCP_SOCKET.IRS]
  732.  
  733.         push    [eax + TCP_SOCKET.ISS]
  734.         pop     [eax + TCP_SOCKET.SND_NXT]
  735.  
  736.         TCP_sendseqinit eax
  737.         TCP_rcvseqinit eax
  738.  
  739.         mov     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  740.         mov     [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  741.         mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
  742.  
  743.         add     eax, STREAM_SOCKET.snd
  744.         call    SOCKET_ring_create
  745.  
  746.         add     eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd
  747.         call    SOCKET_ring_create
  748.  
  749.         sub     eax, STREAM_SOCKET.rcv
  750.  
  751.         mov     [eax + SOCKET.lock], 0
  752.         mov     ebx, eax        ; if there is data, it must arrive in this new socket!
  753.         jmp     .trim_then_step6
  754.  
  755.  
  756. ;------------
  757. ; Active Open
  758.  
  759. align 4
  760. .SYN_SENT:
  761.  
  762.         DEBUGF  1,"TCP state: syn_sent\n"
  763.  
  764.         test    [edx + TCP_segment.Flags], TH_ACK
  765.         jz      @f
  766.  
  767.         mov     eax, [edx + TCP_segment.AckNumber]
  768.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  769.         jle     .drop_with_reset
  770.  
  771. ;        mov     eax, [edx + TCP_segment.AckNumber]
  772.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  773.         jg      .drop_with_reset
  774.        @@:
  775.  
  776.         test    [edx + TCP_segment.Flags], TH_RST
  777.         jz      @f
  778.  
  779.         test    [edx + TCP_segment.Flags], TH_ACK
  780.         jz      .drop
  781.  
  782.         mov     ebx, ECONNREFUSED
  783.         call    TCP_drop
  784.  
  785.         jmp     .drop
  786.        @@:
  787.  
  788.         test    [edx + TCP_segment.Flags], TH_SYN
  789.         jz      .drop
  790.  
  791. ; at this point, segment seems to be valid
  792.  
  793.         test    [edx + TCP_segment.Flags], TH_ACK
  794.         jz      .no_syn_ack
  795.  
  796. ; now, process received SYN in response to an active open
  797.  
  798.         mov     eax, [edx + TCP_segment.AckNumber]
  799.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  800.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  801.         jle     @f
  802.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  803.        @@:
  804.  
  805.   .no_syn_ack:
  806.  
  807.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
  808.  
  809.         push    [edx + TCP_segment.SequenceNumber]
  810.         pop     [ebx + TCP_SOCKET.IRS]
  811.  
  812.         TCP_rcvseqinit ebx
  813.  
  814.         mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  815.  
  816.         mov     eax, [ebx + TCP_SOCKET.SND_UNA]
  817.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  818.         jle     .simultaneous_open
  819.  
  820.         test    [edx + TCP_segment.Flags], TH_ACK
  821.         jz      .simultaneous_open
  822.  
  823.         DEBUGF  1,"TCP: active open\n"
  824.  
  825. ; TODO: update stats
  826. ; TODO: set general socket state to connected
  827.  
  828.         mov     [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
  829.  
  830. ; TODO: check if we should scale the connection (567-572)
  831. ; TODO: update RTT estimators
  832.  
  833.         jmp     .trimthenstep6
  834.  
  835.   .simultaneous_open:
  836.  
  837.         DEBUGF  1,"TCP: simultaneous open\n"
  838. ; We have received a syn but no ACK, so we are having a simultaneous open..
  839.         mov     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  840.  
  841. ;-------------------------------------
  842. ; Common processing for receipt of SYN
  843.  
  844.   .trimthenstep6:
  845.  
  846.         inc     [edx + TCP_segment.SequenceNumber]
  847.  
  848.         cmp     cx, [ebx + TCP_SOCKET.RCV_WND]
  849.         jle     @f
  850.  
  851.         movzx   eax, cx
  852.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  853.         ; TODO: 592
  854.         mov     cx, [ebx + TCP_SOCKET.RCV_WND]
  855.         ; TODO...
  856.        @@:
  857.         ;;;;;
  858.         jmp     .step6
  859.  
  860.  
  861.   .trim_then_step6:
  862.  
  863. ;----------------------------
  864. ; trim any data not in window
  865.  
  866.         DEBUGF  1,"Trimming window\n"
  867.  
  868.         mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
  869.         sub     eax, [edx + TCP_segment.SequenceNumber]
  870.  
  871.         test    eax, eax
  872.         jz      .no_duplicate
  873.  
  874.         test    [edx + TCP_segment.Flags], TH_SYN
  875.         jz      .no_drop
  876.  
  877.         and     [edx + TCP_segment.Flags], not (TH_SYN)
  878.         inc     [edx + TCP_segment.SequenceNumber]
  879.  
  880.         cmp     [edx + TCP_segment.UrgentPointer], 1
  881.         jl      @f
  882.  
  883.         dec     [edx + TCP_segment.UrgentPointer]
  884.  
  885.         jmp     .no_drop
  886.        @@:
  887.  
  888.         and     [edx + TCP_segment.Flags], not (TH_URG)
  889.         dec     eax
  890.         jz      .no_duplicate
  891.   .no_drop:
  892.  
  893.         DEBUGF  1,"Going to drop %u out of %u bytes\n", eax, ecx
  894.  
  895. ; eax holds number of bytes to drop
  896.  
  897. ;----------------------------------
  898. ; Check for entire duplicate packet
  899.  
  900.         cmp     eax, ecx
  901.         jge     .duplicate
  902.  
  903.         ;;; TODO: figure 28.30
  904.  
  905. ;------------------------
  906. ; Check for duplicate FIN
  907.  
  908.         test    [edx + TCP_segment.Flags], TH_FIN
  909.         jz      @f
  910.         inc     ecx
  911.         cmp     eax, ecx
  912.         dec     ecx
  913.         jne     @f
  914.  
  915.         mov     eax, ecx
  916.         and     [edx + TCP_segment.Flags], not TH_FIN
  917.         or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  918.         jmp     .no_duplicate
  919.        @@:
  920.  
  921.         ; Handle the case when a bound socket connects to itself
  922.         ; Allow packets with a SYN and an ACKto continue with the processing
  923.  
  924. ;-------------------------------------
  925. ; Generate duplicate ACK if nescessary
  926.  
  927. ; This code also handles simultaneous half-open or self-connects
  928.  
  929.         test    eax, eax
  930.         jnz     .drop_after_ack
  931.  
  932.         cmp     [edx + TCP_segment.Flags], TH_ACK
  933.         jz      .drop_after_ack
  934.  
  935.   .duplicate:
  936.  
  937.         DEBUGF  1,"Duplicate received\n"
  938.  
  939. ;----------------------------------------
  940. ; Update statistics for duplicate packets
  941.  
  942.         ;;; TODO
  943.  
  944.         jmp     .drop          ;;; DROP the packet ??
  945.  
  946.   .no_duplicate:
  947.  
  948. ;-----------------------------------------------
  949. ; Remove duplicate data and update urgent offset
  950.  
  951.         add     [edx + TCP_segment.SequenceNumber], eax
  952.  
  953.         ;;; TODO
  954.  
  955.         sub     [edx + TCP_segment.UrgentPointer], ax
  956.         jg      @f
  957.  
  958.         and     [edx + TCP_segment.Flags], not (TH_URG)
  959.         mov     [edx + TCP_segment.UrgentPointer], 0
  960.        @@:
  961.  
  962. ;--------------------------------------------------
  963. ; Handle data that arrives after process terminates
  964.  
  965.         cmp     [ebx + SOCKET.PID], 0
  966.         jg      @f
  967.  
  968.         cmp     [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
  969.         jle     @f
  970.  
  971.         test    ecx, ecx
  972.         jz      @f
  973.  
  974.         ;;; Close the socket
  975.         ;;; update stats
  976.  
  977.         jmp     .drop_with_reset
  978.        @@:
  979.  
  980. ;----------------------------------------
  981. ; Remove data beyond right edge of window
  982.  
  983.         mov     eax, [edx + TCP_segment.SequenceNumber]
  984.         add     eax, ecx
  985.         sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
  986.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  987.  
  988.         ; eax now holds the number of bytes to drop
  989.  
  990.         jle     .no_excess_data
  991.  
  992.         ;;; TODO: update stats
  993.  
  994.         cmp     eax, ecx
  995.         jl      .dont_drop_all
  996.  
  997. ;;; TODO 700-736
  998.  
  999.   .dont_drop_all:
  1000.  
  1001.   .no_excess_data:
  1002.  
  1003. ;-----------------
  1004. ; Record timestamp
  1005.  
  1006.         ;;; TODO 737-746
  1007.  
  1008. ;------------------
  1009. ; Process RST flags
  1010.  
  1011.         test    [edx + TCP_segment.Flags], TH_RST
  1012.         jz      .rst_skip
  1013.  
  1014.         DEBUGF  1,"Got an RST flag"
  1015.  
  1016.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1017.         shl     eax, 2
  1018.         jmp     dword [eax + .rst_sw_list]
  1019.  
  1020.   .rst_sw_list:
  1021.         dd      .rst_skip       ;TCB_CLOSED
  1022.         dd      .rst_skip       ;TCB_LISTEN
  1023.         dd      .rst_skip       ;TCB_SYN_SENT
  1024.         dd      .econnrefused   ;TCB_SYN_RECEIVED
  1025.         dd      .econnreset     ;TCB_ESTABLISHED
  1026.         dd      .econnreset     ;TCB_CLOSE_WAIT
  1027.         dd      .econnreset     ;TCB_FIN_WAIT_1
  1028.         dd      .rst_close      ;TCB_CLOSING
  1029.         dd      .rst_close      ;TCB_LAST_ACK
  1030.         dd      .econnreset     ;TCB_FIN_WAIT_2
  1031.         dd      .rst_close      ;TCB_TIMED_WAIT
  1032.  
  1033.   .econnrefused:
  1034.  
  1035.         DEBUGF  1,"Connection refused"
  1036.  
  1037.         ;;; TODO: debug info
  1038.  
  1039.         jmp     .close
  1040.  
  1041.   .econnreset:
  1042.  
  1043.         DEBUGF  1,"Connection reset"
  1044.  
  1045.         ;;; TODO: debug info
  1046.   .close:
  1047.  
  1048.         DEBUGF  1,"Closing connection"
  1049.  
  1050.         ;;; update stats
  1051.  
  1052.   .rst_close:
  1053.  
  1054.         DEBUGF  1,"Closing with reset\n"
  1055.  
  1056.         ;;; Close the socket
  1057.         jmp     .drop
  1058.  
  1059.   .rst_skip:
  1060.  
  1061. ;--------------------------------------
  1062. ; handle SYN-full and ACK-less segments
  1063.  
  1064.         test    [edx + TCP_segment.Flags], TH_SYN
  1065.         jz      @f
  1066.  
  1067.         mov     ebx, ECONNRESET
  1068.         call    TCP_drop
  1069.  
  1070.         jmp     .drop_with_reset
  1071.  
  1072.         test    [edx + TCP_segment.Flags], TH_ACK
  1073.         jz      .drop
  1074.       @@:
  1075. ;----------------
  1076. ; Process the ACK
  1077.  
  1078.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  1079.         jg      .ack_dup
  1080.         jl      .ack_nodup
  1081.  
  1082.         DEBUGF  1,"TCP state = syn received\n"
  1083.  
  1084.         ;;;;;
  1085.  
  1086.   .ack_nodup:
  1087.  
  1088.         DEBUGF  1,"New ACK\n"
  1089.  
  1090.  
  1091.  
  1092.   .ack_dup:
  1093.  
  1094.         ;;;;
  1095.  
  1096. ;-------------------------------------------------
  1097. ; If the congestion window was inflated to account
  1098. ; for the other side's cached packets, retrace it
  1099.  
  1100.         ;;;; 888 -  902
  1101.  
  1102.  
  1103. ;------------------------------------------
  1104. ; RTT measurements and retransmission timer
  1105.  
  1106.         ;;;;; 903 - 926
  1107.  
  1108.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0
  1109.  
  1110.         mov     eax, [ebx + TCP_SOCKET.SND_MAX]
  1111.         cmp     eax, [edx + TCP_segment.AckNumber]
  1112.         je      .all_outstanding
  1113.         mov     [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
  1114.   .all_outstanding:
  1115.  
  1116. ;-------------------------------------------
  1117. ; Open congestion window in response to ACKs
  1118.  
  1119.         ;;;;
  1120.  
  1121.  
  1122. ;------------------------------------------
  1123. ; Remove acknowledged data from send buffer
  1124.  
  1125.         pusha
  1126. ; Delete acknowledged bytes from send buffer
  1127.         mov     ecx, [edx + TCP_segment.AckNumber]
  1128.         sub     ecx, [ebx + TCP_SOCKET.SND_UNA]
  1129.         lea     eax, [ebx + STREAM_SOCKET.snd]
  1130.         call    SOCKET_ring_free
  1131.         popa
  1132.  
  1133.  
  1134. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  code missing (943?)
  1135.  
  1136.  
  1137.  
  1138.         mov     eax, [edx + TCP_segment.AckNumber]
  1139.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  1140.  
  1141.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  1142.         jl      @f
  1143.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  1144.        @@:
  1145.  
  1146.  
  1147. ;---------------------------------------
  1148. ; Wake up process waiting on send buffer
  1149.  
  1150.         mov     eax, ebx
  1151.         call    SOCKET_notify_owner
  1152.  
  1153.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1154.         shl     eax, 2
  1155.         jmp     dword [eax + .ACK_sw_list]
  1156.  
  1157.   .ACK_sw_list:
  1158.         dd      .step6          ;TCB_CLOSED
  1159.         dd      .step6          ;TCB_LISTEN
  1160.         dd      .step6          ;TCB_SYN_SENT
  1161.         dd      .step6          ;TCB_SYN_RECEIVED
  1162.         dd      .step6          ;TCB_ESTABLISHED
  1163.         dd      .step6          ;TCB_CLOSE_WAIT
  1164.         dd      ._963           ;TCB_FIN_WAIT_1
  1165.         dd      ._958           ;TCB_CLOSING
  1166.         dd      ._999           ;TCB_LAST_ACK
  1167.         dd      .step6          ;TCB_FIN_WAIT_2
  1168.         dd      ._1010          ;TCB_TIMED_WAIT
  1169.  
  1170.  
  1171.   ._963:
  1172.  
  1173.  
  1174.         jmp     .step6
  1175.  
  1176.  
  1177.   ._958:
  1178.  
  1179.         jmp     .step6
  1180.  
  1181.   ._999:
  1182.  
  1183.         jmp     .step6
  1184.  
  1185.  
  1186.   ._1010:
  1187.  
  1188.         jmp     .step6
  1189.  
  1190.  
  1191.   .step6:
  1192.  
  1193.         DEBUGF  1,"step 6\n"
  1194.  
  1195. ;----------------------------------------------
  1196. ; check if we need to update window information
  1197.  
  1198.         test    [edx + TCP_segment.Flags], TH_ACK
  1199.         jz      .no_window_update
  1200.  
  1201.         mov     eax, [ebx + TCP_SOCKET.SND_WL1]
  1202.         cmp     eax, [edx + TCP_segment.SequenceNumber]
  1203.         jl      .update_window
  1204.         jg      @f
  1205.  
  1206.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1207.         cmp     eax, [edx + TCP_segment.AckNumber]
  1208.         jl      .update_window
  1209.         jg      .no_window_update
  1210.        @@:
  1211.  
  1212.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1213.         cmp     eax, [edx + TCP_segment.AckNumber]
  1214.         jne     .no_window_update
  1215.  
  1216.         movzx   eax, [edx + TCP_segment.Window]
  1217.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1218.         jle     .no_window_update
  1219.  
  1220.   .update_window:
  1221.  
  1222.         DEBUGF  1,"Updating window\n"
  1223.  
  1224. ;----------------------------------
  1225. ; Keep track of pure window updates
  1226.  
  1227. ;        test    ecx, ecx
  1228. ;        jz      @f
  1229. ;
  1230. ;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1231. ;        cmp     eax, [edx + TCP_segment.AckNumber]
  1232. ;        jne     @f
  1233. ;
  1234. ;        ;; mov eax, tiwin
  1235. ;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1236. ;        jle     @f
  1237. ;
  1238. ;        ;;; update stats
  1239. ;
  1240. ;       @@:
  1241.  
  1242.         mov     eax, dword [edx + TCP_segment.Window]
  1243.         cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
  1244.         jle     @f
  1245.         mov     [ebx + TCP_SOCKET.max_sndwnd], eax
  1246.        @@:
  1247.         mov     [ebx + TCP_SOCKET.SND_WND], eax
  1248.  
  1249.         push    [edx + TCP_segment.SequenceNumber]
  1250.         pop     [ebx + TCP_SOCKET.SND_WL1]
  1251.  
  1252.         push    [edx + TCP_segment.AckNumber]
  1253.         pop     [ebx + TCP_SOCKET.SND_WL2]
  1254.  
  1255.         ;;; needoutput = 1
  1256.  
  1257.   .no_window_update:
  1258.  
  1259. ;-----------------
  1260. ; process URG flag
  1261.  
  1262.         test    [edx + TCP_segment.Flags], TH_URG
  1263.         jz      .not_urgent
  1264.  
  1265.         cmp     [edx + TCP_segment.UrgentPointer], 0
  1266.         jz      .not_urgent
  1267.  
  1268.         cmp     [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
  1269.         je      .not_urgent
  1270.  
  1271. ; Ignore bogus urgent offsets
  1272.  
  1273.         ;;; 1040-1050
  1274.  
  1275.         movzx   eax, [edx + TCP_segment.UrgentPointer]
  1276.         add     eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1277.         cmp     eax, SOCKET_MAXDATA
  1278.         jle     .not_urgent
  1279.  
  1280.         mov     [edx + TCP_segment.UrgentPointer], 0
  1281.         and     [edx + TCP_segment.Flags], not (TH_URG)
  1282.         jmp     .do_data
  1283.  
  1284.   .not_urgent:
  1285.  
  1286. ;--------------------------------------
  1287. ; processing of received urgent pointer
  1288.  
  1289.         ;;; TODO (1051-1093)
  1290.  
  1291. ;--------------------------------
  1292. ; process the data in the segment
  1293.  
  1294.   .do_data:
  1295.  
  1296.         DEBUGF  1,"TCP: do data (%u)\n", ecx
  1297.  
  1298.         test    [edx + TCP_segment.Flags], TH_FIN
  1299.         jnz     .process_fin
  1300.  
  1301.         cmp     [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
  1302.         jge     .dont_do_data
  1303.  
  1304.         test    ecx, ecx
  1305.         jz      .final_processing
  1306.  
  1307.         DEBUGF  1,"Processing data in segment\n"
  1308.  
  1309. ;; TODO: check if data is in sequence !
  1310.  
  1311.         movzx   eax, [edx + TCP_segment.DataOffset]             ;;; todo: remember this in.. edi ?
  1312.         and     eax, 0xf0
  1313.         shr     al, 2
  1314.  
  1315.         lea     esi, [edx + eax]
  1316.  
  1317.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
  1318.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx
  1319.  
  1320.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  1321.         call    SOCKET_ring_write
  1322.  
  1323.         mov     eax, ebx
  1324.         call    SOCKET_notify_owner
  1325.  
  1326.         jmp     .final_processing
  1327.  
  1328.  
  1329.   .dont_do_data:
  1330.  
  1331. ;---------------
  1332. ; FIN processing
  1333.  
  1334.   .process_fin:
  1335.  
  1336.         DEBUGF  1,"Processing FIN\n"
  1337.  
  1338.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1339.         shl     eax, 2
  1340.         jmp     dword [eax + .FIN_sw_list]
  1341.  
  1342.   .FIN_sw_list:
  1343.         dd      .no_fin         ;TCB_CLOSED
  1344.         dd      .no_fin         ;TCB_LISTEN
  1345.         dd      .no_fin         ;TCB_SYN_SENT
  1346.         dd      .fin_syn_est    ;TCB_SYN_RECEIVED
  1347.         dd      .fin_syn_est    ;TCB_ESTABLISHED
  1348.         dd      .no_fin         ;TCB_CLOSE_WAIT
  1349.         dd      .fin_wait1      ;TCB_FIN_WAIT_1
  1350.         dd      .no_fin         ;TCB_CLOSING
  1351.         dd      .no_fin         ;TCB_LAST_ACK
  1352.         dd      .fin_wait2      ;TCB_FIN_WAIT_2
  1353.         dd      .fin_timed      ;TCB_TIMED_WAIT
  1354.  
  1355.  
  1356.  
  1357.   .fin_syn_est:
  1358.  
  1359.         jmp     .final_processing
  1360.  
  1361.   .fin_wait1:
  1362.  
  1363.         jmp     .final_processing
  1364.  
  1365.   .fin_wait2:
  1366.  
  1367.         jmp     .final_processing
  1368.  
  1369.   .fin_timed:
  1370.  
  1371.         jmp     .final_processing
  1372.  
  1373.   .no_fin:
  1374.  
  1375. ;-----------------
  1376. ; Final processing
  1377.  
  1378.   .final_processing:
  1379.  
  1380.         DEBUGF  1,"Final processing\n"
  1381.  
  1382.         mov     [ebx + SOCKET.lock], 0
  1383.  
  1384.         ;;; if debug enabled, output packet
  1385.  
  1386.         ;test    ;;;needoutput = 1
  1387.         ;jnz     .outputnow
  1388.  
  1389.         test    [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1390.         jnz     .ack_now
  1391.  
  1392.         call    kernel_free
  1393.         add     esp, 4
  1394.         ret
  1395.  
  1396.   .ack_now:
  1397.  
  1398.         DEBUGF  1,"ACK now!\n"
  1399.  
  1400.         push    ebx
  1401.         mov     eax, ebx
  1402.         call    TCP_output
  1403.         pop     ebx
  1404.  
  1405.         call    kernel_free
  1406.         add     esp, 4
  1407.         ret
  1408.  
  1409. ;------------------------------------------
  1410. ; Generate an ACK, droping incoming segment
  1411.  
  1412. align 4
  1413. .drop_after_ack:
  1414.  
  1415.         DEBUGF  1,"Drop after ACK\n"
  1416.  
  1417.         test    [edx + TCP_segment.Flags], TH_RST
  1418.         jnz     .drop
  1419.  
  1420.         and     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1421.  
  1422.         push    ebx
  1423.         mov     eax, ebx
  1424.         call    TCP_output
  1425.         pop     ebx
  1426.  
  1427.         call    kernel_free
  1428.         add     esp, 4
  1429.         ret
  1430.  
  1431.  
  1432. ;-------------------------------------------
  1433. ; Generate an RST, dropping incoming segment
  1434.  
  1435. align 4
  1436. .drop_with_reset:
  1437.  
  1438.         DEBUGF  1,"Drop with reset\n"
  1439.  
  1440.         test    [edx + TCP_segment.Flags], TH_RST
  1441.         jnz     .drop
  1442.  
  1443.         ;;; if its a multicast/broadcast, also drop
  1444.  
  1445.         test    [edx + TCP_segment.Flags], TH_ACK
  1446.         jnz     .respond_ack
  1447.  
  1448.         test    [edx + TCP_segment.Flags], TH_SYN
  1449.         jnz     .respond_syn
  1450.  
  1451.         call    kernel_free
  1452.         add     esp, 4
  1453.         ret
  1454.  
  1455.   .respond_ack:
  1456.  
  1457.         mov     dl, TH_RST
  1458.  
  1459.         push    ebx
  1460.         call    TCP_respond_segment
  1461.         pop     ebx
  1462.  
  1463.         jmp     .destroy_new_socket
  1464.  
  1465.  
  1466.   .respond_syn:
  1467.  
  1468.         mov     dl, TH_RST + TH_ACK
  1469.  
  1470.         push    ebx
  1471.         call    TCP_respond_socket
  1472.         pop     ebx
  1473.  
  1474.         jmp     .destroy_new_socket
  1475.  
  1476. ;-----
  1477. ; Drop
  1478.  
  1479. align 4
  1480. .drop:
  1481.  
  1482.         DEBUGF  1,"Dropping packet\n"
  1483.  
  1484.         ;;;; If debugging options are enabled, output the packet somwhere
  1485.  
  1486.   .destroy_new_socket:
  1487.  
  1488.         ;;;; kill the newly created socket
  1489.  
  1490.         call    kernel_free
  1491.         add     esp, 4
  1492.         ret
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499. ;---------------------------
  1500. ;
  1501. ; TCP_pull_out_of_band
  1502. ;
  1503. ; IN:  eax =
  1504. ;      ebx = socket ptr
  1505. ;      edx = tcp packet ptr
  1506. ;
  1507. ; OUT: /
  1508. ;
  1509. ;---------------------------
  1510.  
  1511. align 4
  1512. TCP_pull_out_of_band:
  1513.  
  1514.         DEBUGF  1,"TCP_pull_out_of_band\n"
  1515.  
  1516.         ;;;; 1282-1305
  1517.  
  1518.         ret
  1519.  
  1520.  
  1521.  
  1522. ;-----------------------------------------------------------------
  1523. ;
  1524. ; TCP_output
  1525. ;
  1526. ; IN:  eax = socket pointer
  1527. ;
  1528. ; OUT: /
  1529. ;
  1530. ;-----------------------------------------------------------------
  1531. align 4
  1532. TCP_output:
  1533.  
  1534.         DEBUGF 1,"TCP_output, socket: %x\n", eax
  1535.  
  1536. ; We'll detect the length of the data to be transmitted, and flags to be used
  1537. ; If there is some data, or any critical controls to send (SYN / RST), then transmit
  1538. ; Otherwise, investigate further
  1539.  
  1540.         mov     ebx, [eax + TCP_SOCKET.SND_MAX]
  1541.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1542.         jne     .not_idle
  1543.  
  1544.         mov     ebx, [eax + TCP_SOCKET.t_idle]
  1545.         cmp     ebx, [eax + TCP_SOCKET.t_rxtcur]
  1546.         jle     .not_idle
  1547.  
  1548. ; We have been idle for a while and no ACKS are expected to clock out any data we send..
  1549. ; Slow start to get ack "clock" running again.
  1550.  
  1551.         mov     ebx, [eax + TCP_SOCKET.t_maxseg]
  1552.         mov     [eax + TCP_SOCKET.SND_CWND], ebx
  1553.  
  1554.   .not_idle:
  1555.   .again:
  1556.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]         ; calculate offset
  1557.         sub     ebx, [eax + TCP_SOCKET.SND_UNA]         ;
  1558.  
  1559.         mov     ecx, [eax + TCP_SOCKET.SND_WND]         ; determine window
  1560.         cmp     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1561.         jl      @f                                      ;
  1562.         mov     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1563.        @@:                                              ;
  1564.  
  1565.         call    TCP_outflags    ; in dl
  1566.  
  1567. ; If in persist timeout with window of 0, send 1 byte.
  1568. ; Otherwise, if window is small but nonzero, and timer expired,
  1569. ; we will send what we can and go to transmit state
  1570.  
  1571.         test    [eax + TCP_SOCKET.t_force], -1
  1572.         jz      .no_persist_timeout
  1573.  
  1574.         test    ecx, ecx
  1575.         jnz     .no_zero_window
  1576.  
  1577.         cmp     ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1578.         jge     @f
  1579.  
  1580.         and     dl, not (TH_FIN)          ; clear the FIN flag    ??? how can it be set before?
  1581.  
  1582.        @@:
  1583.         inc     ecx
  1584.         jmp     .no_persist_timeout
  1585.  
  1586.   .no_zero_window:
  1587.  
  1588.         mov     [eax + TCP_SOCKET.timer_persist], 0
  1589.         mov     [eax + TCP_SOCKET.t_rxtshift], 0
  1590.  
  1591.   .no_persist_timeout:
  1592.  
  1593. ;;;106
  1594.  
  1595.         mov     esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1596.         cmp     esi, ecx
  1597.         jl      @f
  1598.         mov     esi, ecx
  1599.        @@:
  1600.         sub     esi, ebx
  1601.  
  1602.         cmp     esi, -1
  1603.         jne     .not_minus_one
  1604.  
  1605. ; If FIN has been set, but not ACKed, and we havent been called to retransmit,
  1606. ; len (esi) will be -1
  1607. ; Otherwise, window shrank after we sent into it.
  1608. ; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
  1609. ; We will enter persist state below.
  1610. ; If window didn't close completely, just wait for an ACK
  1611.  
  1612.         xor     esi, esi
  1613.  
  1614.         test    ecx, ecx
  1615.         jnz     @f
  1616.  
  1617.         mov     [eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
  1618.  
  1619.         push    [eax + TCP_SOCKET.SND_UNA]
  1620.         pop     [eax + TCP_SOCKET.SND_NXT]
  1621.        @@:
  1622.  
  1623.   .not_minus_one:
  1624.  
  1625. ;;; 124
  1626.  
  1627.         cmp     esi, [eax + TCP_SOCKET.t_maxseg]
  1628.         jle     @f
  1629.  
  1630.         mov     esi, [eax + TCP_SOCKET.t_maxseg]
  1631.         ;sendalot = 1
  1632.  
  1633.        @@:
  1634.  
  1635. ;;; 128
  1636.  
  1637.         mov     edi, [eax + TCP_SOCKET.SND_NXT]
  1638.         add     edi, esi        ; len
  1639.         sub     edi, [eax + TCP_SOCKET.SND_UNA]
  1640.         add     edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1641.         cmp     edi, 0
  1642.         jle     @f
  1643.  
  1644.         and     dl, not (TH_FIN)          ; clear the FIN flag
  1645.  
  1646.        @@:
  1647.  
  1648.  
  1649. ; set ecx to space available in receive buffer
  1650. ; From now on, ecx will be the window we advertise to the other end
  1651.  
  1652.         mov     ecx, SOCKET_MAXDATA
  1653.         sub     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1654.  
  1655. ;------------------------------
  1656. ; Sender silly window avoidance
  1657.  
  1658.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]
  1659.         je      .send
  1660.  
  1661. ;;; TODO: 144-145
  1662.  
  1663.         test    [eax + TCP_SOCKET.t_force], -1
  1664.         jnz     .send
  1665.  
  1666.         mov     ebx, [eax + TCP_SOCKET.max_sndwnd]
  1667.         shr     ebx, 1
  1668.         cmp     ecx, ebx
  1669.         jge     .send
  1670.  
  1671.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1672.         cmp     ebx, [eax + TCP_SOCKET.SND_MAX]
  1673.         jl      .send
  1674.  
  1675. ;----------------------------------------
  1676. ; Check if a window update should be sent
  1677.  
  1678.         test    ecx, ecx        ; window
  1679.         jz      .no_window
  1680.  
  1681. ;;; TODO 154-172
  1682.  
  1683.   .no_window:
  1684.  
  1685. ;--------------------------
  1686. ; Should a segment be sent?
  1687.  
  1688.         test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  1689.         jnz     .send
  1690.  
  1691.         test    dl, TH_SYN + TH_RST
  1692.         jnz     .send
  1693.  
  1694.         mov     ebx, [eax + TCP_SOCKET.SND_UP]
  1695.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1696.         jg      .send
  1697.  
  1698.         test    dl, TH_FIN
  1699.         jz      .enter_persist
  1700.  
  1701.         test    [eax + TCP_SOCKET.t_flags], TF_SENTFIN
  1702.         jnz     .send
  1703.  
  1704.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1705.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1706.         je      .send
  1707.  
  1708. ;--------------------
  1709. ; Enter persist state
  1710.  
  1711.   .enter_persist:
  1712.  
  1713.         DEBUGF  1,"Entering persist state\n"
  1714.  
  1715. ;--------------------------------------
  1716. ; No reason to send a segment, just ret
  1717.  
  1718.         DEBUGF  1,"No reason to send a segment\n"
  1719.  
  1720.         ret
  1721.  
  1722.  
  1723. ;-----------------------------------------------
  1724. ;
  1725. ; Send a segment
  1726. ;
  1727. ; eax = socket pointer
  1728. ;  dl = flags
  1729. ;
  1730. ;-----------------------------------------------
  1731.  
  1732.   .send:
  1733.  
  1734.         DEBUGF  1,"Preparing to send a segment\n"
  1735.  
  1736.         mov     edi, TCP_segment.Data   ; edi will contain headersize
  1737.  
  1738.         sub     esp, 8                  ; create some space on stack
  1739.         push    eax                     ; save this too..
  1740.  
  1741. ;------------------------------------
  1742. ; Send options with first SYN segment
  1743.  
  1744.         test    dl, TH_SYN
  1745.         jz      .no_options
  1746.  
  1747.         push    [eax + TCP_SOCKET.ISS]
  1748.         pop     [eax + TCP_SOCKET.SND_NXT]
  1749.  
  1750.         test    [eax + TCP_SOCKET.t_flags], TF_NOOPT
  1751.         jnz     .no_options
  1752.  
  1753.         mov     ecx, 1460
  1754.         or      ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
  1755.         bswap   ecx
  1756.         push    ecx
  1757.         add     di, 4
  1758.  
  1759.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
  1760.         jz      .no_syn
  1761.  
  1762.         test    dl, TH_ACK
  1763.         jnz     .scale_opt
  1764.  
  1765.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
  1766.         jz      .no_syn
  1767.  
  1768.   .scale_opt:
  1769.         movzx   ecx, byte [eax + TCP_SOCKET.request_r_scale]
  1770.         or      ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
  1771.         bswap   ecx
  1772.         pushd   ecx
  1773.         add     di, 4
  1774.  
  1775.   .no_syn:
  1776.  
  1777. ;------------------------------------
  1778. ; Make the timestamp option if needed
  1779.  
  1780.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
  1781.         jz      .no_timestamp
  1782.  
  1783.         test    dl, TH_RST
  1784.         jnz     .no_timestamp
  1785.  
  1786.         test    dl, TH_ACK
  1787.         jz      .timestamp
  1788.  
  1789.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
  1790.         jz      .no_timestamp
  1791.  
  1792.   .timestamp:
  1793.         mov     esi, [timer_ticks]
  1794.         bswap   esi
  1795.         push    esi
  1796.         pushw   0
  1797.         pushd   TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
  1798.         add     di, 10
  1799.  
  1800.   .no_timestamp:
  1801.         ;; TODO: check if we dont exceed the max segment size
  1802.  
  1803.   .no_options:
  1804.         ; eax = socket ptr
  1805.         ; edx = flags
  1806.         ; ecx = data size
  1807.         ; edi = header size
  1808.         ; esi = snd ring buff ptr
  1809.  
  1810.         mov     ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1811.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]                        ;;; right?
  1812.         jle     @f
  1813.         mov     ecx, [eax + TCP_SOCKET.t_maxseg]
  1814.        @@:
  1815.         add     ecx, edi        ; total TCP segment size
  1816.  
  1817. ; Start by pushing all TCP header values in reverse order on stack
  1818. ; (essentially, creating the tcp header!)
  1819.  
  1820.         pushw   0       ;        .UrgentPointer          dw ?
  1821.         pushw   0       ;        .Checksum               dw ?
  1822.         pushw   0x00a0  ;        .Window                 dw ?    ;;;;;;;
  1823.         shl     edi, 2  ;        .DataOffset             db ?  only 4 left-most bits
  1824.         shl     dx, 8
  1825.         or      dx, di  ;        .Flags                  db ?
  1826.         pushw   dx
  1827.         shr     edi, 2  ;        .DataOffset             db ? ;;;;
  1828.  
  1829.         push    [eax + TCP_SOCKET.RCV_NXT]      ;        .AckNumber              dd ?
  1830.         ntohd   [esp]
  1831.  
  1832.         push    [eax + TCP_SOCKET.SND_NXT]      ;        .SequenceNumber         dd ?
  1833.         ntohd   [esp]
  1834.  
  1835.         push    [eax + TCP_SOCKET.RemotePort]   ;        .DestinationPort        dw ?
  1836.         ntohw   [esp]
  1837.  
  1838.         push    [eax + TCP_SOCKET.LocalPort]    ;        .SourcePort             dw ?
  1839.         ntohw   [esp]
  1840.  
  1841.         push    edi             ; header size
  1842.  
  1843. ; Create the IP packet
  1844.         mov     ebx, [eax + IP_SOCKET.LocalIP]  ; source ip
  1845.         mov     eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
  1846.         mov     di, IP_PROTO_TCP shl 8 + 128
  1847.         call    IPv4_output
  1848.         jz      .fail
  1849.  
  1850. ;-----------------------------------------
  1851. ; Move TCP header from stack to TCP packet
  1852.  
  1853.         push    ecx
  1854.         mov     ecx, [esp+4]
  1855.         lea     esi, [esp+4+4]
  1856.         shr     ecx, 2
  1857.         rep     movsd
  1858.         pop     ecx             ; full TCP packet size
  1859.  
  1860.         pop     esi             ; headersize
  1861.         add     esp, esi
  1862.  
  1863.         mov     [esp + 4], eax          ; packet ptr
  1864.         mov     [esp + 4+4], edx        ; packet size
  1865.  
  1866.         mov     edx, edi                ; begin of data
  1867.         sub     edx, esi                ; begin of packet (edi = begin of data)
  1868.         push    ecx
  1869.         sub     ecx, esi                ; data size
  1870.  
  1871. ;--------------
  1872. ; Copy the data
  1873.  
  1874. ; eax = ptr to ring struct
  1875. ; ecx = buffer size
  1876. ; edi = ptr to buffer
  1877.  
  1878. ;        test    ecx, ecx
  1879.         mov     eax, [esp+4]              ; socket ptr
  1880.         add     [eax + TCP_SOCKET.SND_NXT], ecx
  1881.         add     eax, STREAM_SOCKET.snd
  1882.         push    edx
  1883.         call    SOCKET_ring_read
  1884.         pop     esi
  1885.         pop     ecx
  1886.         pop     eax
  1887.  
  1888.         test    [esi + TCP_segment.Flags], TH_SYN + TH_FIN
  1889.         jz      @f
  1890.         inc     [eax + TCP_SOCKET.SND_NXT]
  1891.         ;;; TODO: update sentfin flag
  1892.        @@:
  1893.  
  1894.         mov     edx, [eax + TCP_SOCKET.SND_NXT]
  1895.         cmp     edx, [eax + TCP_SOCKET.SND_MAX]
  1896.         jle     @f
  1897.         mov     [eax + TCP_SOCKET.SND_MAX], edx
  1898.  
  1899.         ;;;; TODO: time transmission (420)
  1900.        @@:
  1901.  
  1902.         ;;; TODO: set retransmission timer
  1903.  
  1904. ;--------------------
  1905. ; Create the checksum
  1906.  
  1907.         DEBUGF  1,"checksum: ptr=%x size=%u\n", esi, ecx
  1908.  
  1909.         TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
  1910.         mov     [esi+TCP_segment.Checksum], dx
  1911.  
  1912. ;----------------
  1913. ; Send the packet
  1914.  
  1915.         DEBUGF  1,"Sending TCP Packet to device %x\n", ebx
  1916.         call    [ebx + NET_DEVICE.transmit]
  1917.         ret
  1918.  
  1919.  
  1920.   .fail:
  1921.         pop     ecx
  1922.         add     esp, ecx
  1923.         add     esp, 4+8
  1924.         DEBUGF 1,"TCP_output: failed\n"
  1925.         ret
  1926.  
  1927.  
  1928.  
  1929. ;-------------------------
  1930. ;
  1931. ; TCP_outflags
  1932. ;
  1933. ;  IN:  eax = socket ptr
  1934. ;
  1935. ;  OUT: edx = flags
  1936. ;
  1937. ;-------------------------
  1938. align 4
  1939. TCP_outflags:
  1940.  
  1941.         mov     edx, [eax + TCP_SOCKET.t_state]
  1942.         movzx   edx, byte [edx + .flaglist]
  1943.  
  1944.         DEBUGF  1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
  1945.  
  1946.         ret
  1947.  
  1948.   .flaglist:
  1949.  
  1950.         db      TH_RST + TH_ACK         ; TCB_CLOSED
  1951.         db      0                       ; TCB_LISTEN
  1952.         db      TH_SYN                  ; TCB_SYN_SENT
  1953.         db      TH_SYN + TH_ACK         ; TCB_SYN_RECEIVED
  1954.         db               TH_ACK         ; TCB_ESTABLISHED
  1955.         db               TH_ACK         ; TCB_CLOSE_WAIT
  1956.         db      TH_SYN + TH_ACK         ; TCB_FIN_WAIT_1
  1957.         db      TH_SYN + TH_ACK         ; TCB_CLOSING
  1958.         db      TH_SYN + TH_ACK         ; TCB_LAST_ACK
  1959.         db               TH_ACK         ; TCB_FIN_WAIT_2
  1960.         db               TH_ACK         ; TCB_TIMED_WAIT
  1961.  
  1962.  
  1963.  
  1964.  
  1965. ;-------------------------
  1966. ;
  1967. ; TCP_drop
  1968. ;
  1969. ;  IN:  eax = socket ptr
  1970. ;       ebx = error number
  1971. ;
  1972. ;  OUT: eax = socket ptr
  1973. ;
  1974. ;-------------------------
  1975. align 4
  1976. TCP_drop:
  1977.  
  1978.         DEBUGF  1,"TCP_drop\n"
  1979.  
  1980.         cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  1981.         jl      .no_syn_received
  1982.  
  1983.         mov     [eax + TCP_SOCKET.t_state], TCB_CLOSED
  1984.  
  1985.         call    TCP_output
  1986.  
  1987. ;;; TODO: update stats
  1988.  
  1989.         jmp     TCP_close
  1990.  
  1991.   .no_syn_received:
  1992.  
  1993. ;;; TODO: update stats
  1994.  
  1995. ;;; TODO: check if error code is "Connection timed out' and handle accordingly
  1996.  
  1997.         mov     [eax + SOCKET.errorcode], ebx
  1998.  
  1999.         jmp     TCP_close
  2000.  
  2001.  
  2002. ;-------------------------
  2003. ;
  2004. ; TCP_close
  2005. ;
  2006. ;  IN:  eax = socket ptr
  2007. ;  OUT: eax = socket ptr
  2008. ;
  2009. ;-------------------------
  2010. align 4
  2011. TCP_close:
  2012.  
  2013. ;;; TODO: update RTT and mean deviation
  2014. ;;; TODO: update slow start threshold
  2015. ;;; TODO: release connection resources
  2016.  
  2017.         ret
  2018.  
  2019.  
  2020.  
  2021.  
  2022. ;---------------------------------------
  2023. ;
  2024. ; The easy way to send an ACK/RST/keepalive segment
  2025. ;
  2026. ; TCP_respond_socket:
  2027. ;
  2028. ;  IN:  ebx = socket ptr
  2029. ;        cl = flags
  2030. ;
  2031. ;--------------------------------------
  2032. align 4
  2033. TCP_respond_socket:
  2034.  
  2035.         DEBUGF  1,"TCP_respond_socket\n"
  2036.  
  2037. ;---------------------
  2038. ; Create the IP packet
  2039.  
  2040.         push    cx ebx
  2041.         mov     eax, [ebx + IP_SOCKET.RemoteIP]
  2042.         mov     ebx, [ebx + IP_SOCKET.LocalIP]
  2043.         mov     ecx, TCP_segment.Data
  2044.         mov     di , IP_PROTO_TCP shl 8 + 128
  2045.         call    IPv4_output
  2046.         test    edi, edi
  2047.         jz      .error
  2048.         pop     esi cx
  2049.         push    edx eax
  2050.  
  2051. ;-----------------------------------------------
  2052. ; Fill in the TCP header by using the socket ptr
  2053.  
  2054.         mov     ax, [esi + TCP_SOCKET.LocalPort]
  2055.         rol     ax, 8
  2056.         stosw
  2057.         mov     ax, [esi + TCP_SOCKET.RemotePort]
  2058.         rol     ax, 8
  2059.         stosw
  2060.         mov     eax, [esi + TCP_SOCKET.SND_NXT]
  2061.         bswap   eax
  2062.         stosd
  2063.         mov     eax, [esi + TCP_SOCKET.RCV_NXT]
  2064.         bswap   eax
  2065.         stosd
  2066.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2067.         stosb
  2068.         mov     al, cl
  2069.         stosb
  2070.         mov     ax, [esi + TCP_SOCKET.RCV_WND]
  2071.         rol     ax, 8
  2072.         stosw                   ; window
  2073.         xor     eax, eax
  2074.         stosd                   ; checksum + urgentpointer
  2075.  
  2076. ;---------------------
  2077. ; Fill in the checksum
  2078.  
  2079.   .checksum:
  2080.         sub     edi, TCP_segment.Data
  2081.         mov     ecx, TCP_segment.Data
  2082.         xchg    esi, edi
  2083.         TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
  2084.         mov     [esi+TCP_segment.Checksum], dx
  2085.  
  2086. ;--------------------
  2087. ; And send the segment
  2088.  
  2089.         call    [ebx + NET_DEVICE.transmit]
  2090.         ret
  2091.  
  2092.   .error:
  2093.         DEBUGF  1,"TCP_respond failed\n"
  2094.         add     esp, 2+4
  2095.  
  2096.         ret
  2097.  
  2098.  
  2099.  
  2100. ;-------------------------
  2101. ; TCP_respond.segment:
  2102. ;
  2103. ;  IN:  edx = segment ptr (a previously received segment)
  2104. ;        cl = flags
  2105.  
  2106. align 4
  2107. TCP_respond_segment:
  2108.  
  2109.         DEBUGF  1,"TCP_respond_segment\n"
  2110.  
  2111. ;---------------------
  2112. ; Create the IP packet
  2113.  
  2114.         push    cx edx
  2115.         mov     ebx, [edx - 20 + IPv4_Packet.SourceAddress]      ;;;; and what if ip packet had options?!
  2116.         mov     eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
  2117.         mov     ecx, TCP_segment.Data
  2118.         mov     di , IP_PROTO_TCP shl 8 + 128
  2119.         call    IPv4_output
  2120.         jz      .error
  2121.         pop     esi cx
  2122.  
  2123.         push    edx eax
  2124.  
  2125. ;---------------------------------------------------
  2126. ; Fill in the TCP header by using a received segment
  2127.  
  2128.         mov     ax, [esi + TCP_segment.DestinationPort]
  2129.         rol     ax, 8
  2130.         stosw
  2131.         mov     ax, [esi + TCP_segment.SourcePort]
  2132.         rol     ax, 8
  2133.         stosw
  2134.         mov     eax, [esi + TCP_segment.AckNumber]
  2135.         bswap   eax
  2136.         stosd
  2137.         xor     eax, eax
  2138.         stosd
  2139.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2140.         stosb
  2141.         mov     al, cl
  2142.         stosb
  2143.         mov     ax, 1280
  2144.         rol     ax, 8
  2145.         stosw                   ; window
  2146.         xor     eax, eax
  2147.         stosd                   ; checksum + urgentpointer
  2148.  
  2149. ;---------------------
  2150. ; Fill in the checksum
  2151.  
  2152.   .checksum:
  2153.         lea     esi, [edi - TCP_segment.Data]
  2154.         mov     ecx, TCP_segment.Data
  2155.         TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
  2156.         mov     [esi+TCP_segment.Checksum], dx
  2157.  
  2158. ;--------------------
  2159. ; And send the segment
  2160.  
  2161.         call    [ebx + NET_DEVICE.transmit]
  2162.         ret
  2163.  
  2164.   .error:
  2165.         DEBUGF  1,"TCP_respond failed\n"
  2166.         add     esp, 2+4
  2167.  
  2168.         ret
  2169.  
  2170.  
  2171.  
  2172.  
  2173. ;---------------------------------------------------------------------------
  2174. ;
  2175. ; TCP_API
  2176. ;
  2177. ; This function is called by system function 75
  2178. ;
  2179. ; IN:  subfunction number in bl
  2180. ;      device number in bh
  2181. ;      ecx, edx, .. depends on subfunction
  2182. ;
  2183. ; OUT:
  2184. ;
  2185. ;---------------------------------------------------------------------------
  2186. align 4
  2187. TCP_API:
  2188.  
  2189.         movzx   eax, bh
  2190.         shl     eax, 2
  2191.  
  2192.         test    bl, bl
  2193.         jz      .packets_tx     ; 0
  2194.         dec     bl
  2195.         jz      .packets_rx     ; 1
  2196.  
  2197. .error:
  2198.         mov     eax, -1
  2199.         ret
  2200.  
  2201. .packets_tx:
  2202.         add     eax, TCP_segments_tx
  2203.         mov     eax, [eax]
  2204.         ret
  2205.  
  2206. .packets_rx:
  2207.         add     eax, TCP_segments_rx
  2208.         mov     eax, [eax]
  2209.         ret
  2210.