Subversion Repositories Kolibri OS

Rev

Rev 1716 | Go to most recent revision | 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: 1719 $
  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.         DEBUGF  1,"TCP_segment.window=%u\n", [edx + TCP_segment.Window]:4
  576.         DEBUGF  1,"TCP_SOCKET.SND_WND=%u\n", [ebx + TCP_SOCKET.SND_WND]:4
  577.         mov     eax, dword [edx + TCP_segment.Window]
  578.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  579.         jne     .not_uni_xfer
  580.  
  581.         mov     eax, [ebx + TCP_SOCKET.SND_NXT]
  582.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  583.         jne     .not_uni_xfer
  584.  
  585. ;---------------------------------------
  586. ; check if we are sender in the uni-xfer
  587.  
  588. ; If the following 4 conditions are all true, this segment is a pure ACK.
  589. ;
  590. ; - The segment contains no data.
  591.         test    ecx, ecx
  592.         jnz     .not_sender
  593.  
  594. ; - The congestion window is greater than or equal to the current send window.
  595. ;     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.
  596.         mov     eax, [ebx + TCP_SOCKET.SND_CWND]
  597.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  598.         jl      .not_uni_xfer
  599.  
  600. ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
  601.         mov     eax, [edx + TCP_segment.AckNumber]
  602.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  603.         jg      .not_uni_xfer
  604.  
  605. ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
  606.         sub     eax, [ebx + TCP_SOCKET.SND_UNA]
  607.         jle     .not_uni_xfer
  608.  
  609.         DEBUGF  1,"Header prediction: we are sender\n"
  610.  
  611. ;---------------------------------
  612. ; Packet is a pure ACK, process it
  613.  
  614. ; Update RTT estimators
  615.  
  616. ; Delete acknowledged bytes from send buffer
  617.         pusha
  618.         mov     ecx, eax
  619.         lea     eax, [ebx + STREAM_SOCKET.snd]
  620.         call    SOCKET_ring_free
  621.         popa
  622.  
  623. ; update window pointers
  624.         mov     eax, [edx + TCP_segment.AckNumber]
  625.         dec     eax
  626.         mov     [ebx + TCP_SOCKET.SND_WL1], eax
  627.  
  628. ; Stop retransmit timer
  629.         mov     [ebx + TCP_SOCKET.timer_ack], 0
  630.  
  631. ; Awaken waiting processes
  632.         mov     eax, ebx
  633.         call    SOCKET_notify_owner
  634.  
  635. ;; Generate more output                  FIXME
  636. ;;        mov     eax, ebx
  637. ;;        call    TCP_output
  638. ;;
  639. ;;        jmp     .drop
  640.         jmp     .ack_processed
  641.  
  642. ;-------------------------------------------------
  643. ; maybe we are the receiver in the uni-xfer then..
  644.  
  645.   .not_sender:
  646. ; - The amount of data in the segment is greater than 0 (data count is in ecx)
  647.  
  648. ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
  649.         mov     eax, [edx + TCP_segment.AckNumber]
  650.         cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
  651.         jne     .not_uni_xfer
  652.  
  653. ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
  654.  
  655. ;;;;;;;     TODO
  656.  
  657.         jnz     .not_uni_xfer
  658.  
  659. ;-------------------------------------
  660. ; Complete processing of received data
  661.  
  662.         DEBUGF  1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
  663.  
  664.         pusha
  665.         add     esi, edx
  666.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  667.         call    SOCKET_ring_write                       ; Add the data to the socket buffer
  668.  
  669.         mov     eax, ebx
  670.         call    SOCKET_notify_owner
  671.         popa
  672.  
  673.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
  674.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
  675.  
  676.         jmp     .drop
  677.  
  678. ;----------------------------------------------------
  679. ; Header prediction failed, doing it the slow way..     ;;;;; current implementation of header prediction destroys some regs (ecx) !!
  680.  
  681.   .not_uni_xfer:
  682.  
  683.         DEBUGF  1,"Header prediction failed\n"          ; time to do it the "slow" way :)
  684.  
  685. ;------------------------------
  686. ; Calculate receive window size
  687.  
  688.         ;;;;
  689.  
  690.         cmp     [ebx + TCP_SOCKET.t_state], TCB_LISTEN
  691.         je      .LISTEN
  692.  
  693.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
  694.         je      .SYN_SENT
  695.  
  696. ;--------------------------------------------
  697. ; Protection Against Wrapped Sequence Numbers
  698.  
  699. ; First, check if timestamp is present
  700.  
  701. ;;;; TODO
  702.  
  703. ; Then, check if at least some bytes of data are within window
  704.  
  705. ;;;; TODO
  706.  
  707.         jmp     .trim_then_step6
  708.  
  709. ;-------------
  710. ; Passive Open
  711.  
  712. align 4
  713. .LISTEN:
  714.  
  715.         DEBUGF  1,"TCP state: listen\n"
  716.  
  717.         test    [edx + TCP_segment.Flags], TH_RST       ;;; TODO: kill new socket on error
  718.         jnz     .drop
  719.  
  720.         test    [edx + TCP_segment.Flags], TH_ACK
  721.         jnz     .drop_with_reset
  722.  
  723.         test    [edx + TCP_segment.Flags], TH_SYN
  724.         jz      .drop
  725.  
  726.  
  727.         ; TODO: check if it's a broadcast or multicast, and drop if so
  728.  
  729. ;-----------------------
  730. ; Fill in some variables
  731.  
  732.         add     [TCP_sequence_num], 64000
  733.  
  734.         push    [edx + TCP_segment.SourcePort]
  735.         pop     [eax + TCP_SOCKET.RemotePort]
  736.  
  737.         push    [edx + TCP_segment.SequenceNumber]
  738.         pop     [eax + TCP_SOCKET.IRS]
  739.  
  740.         push    [eax + TCP_SOCKET.ISS]
  741.         pop     [eax + TCP_SOCKET.SND_NXT]
  742.  
  743.         TCP_sendseqinit eax
  744.         TCP_rcvseqinit eax
  745.  
  746.         mov     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  747.         mov     [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  748.         mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
  749.  
  750.         add     eax, STREAM_SOCKET.snd
  751.         call    SOCKET_ring_create
  752.  
  753.         add     eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd
  754.         call    SOCKET_ring_create
  755.  
  756.         sub     eax, STREAM_SOCKET.rcv
  757.  
  758.         mov     [eax + SOCKET.lock], 0
  759.         mov     ebx, eax        ; if there is data, it must arrive in this new socket!
  760.         jmp     .trim_then_step6
  761.  
  762.  
  763. ;------------
  764. ; Active Open
  765.  
  766. align 4
  767. .SYN_SENT:
  768.  
  769.         DEBUGF  1,"TCP state: syn_sent\n"
  770.  
  771.         test    [edx + TCP_segment.Flags], TH_ACK
  772.         jz      @f
  773.  
  774.         mov     eax, [edx + TCP_segment.AckNumber]
  775.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  776.         jle     .drop_with_reset
  777.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  778.         jg      .drop_with_reset
  779.        @@:
  780.  
  781.         test    [edx + TCP_segment.Flags], TH_RST
  782.         jz      @f
  783.  
  784.         test    [edx + TCP_segment.Flags], TH_ACK
  785.         jz      .drop
  786.  
  787.         mov     eax, ebx
  788.         mov     ebx, ECONNREFUSED
  789.         call    TCP_drop
  790.  
  791.         jmp     .drop
  792.        @@:
  793.  
  794.         test    [edx + TCP_segment.Flags], TH_SYN
  795.         jz      .drop
  796.  
  797. ; at this point, segment seems to be valid
  798.  
  799.         test    [edx + TCP_segment.Flags], TH_ACK
  800.         jz      .no_syn_ack
  801.  
  802. ; now, process received SYN in response to an active open
  803.  
  804.         mov     eax, [edx + TCP_segment.AckNumber]
  805.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  806.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  807.         jle     @f
  808.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  809.        @@:
  810.  
  811.   .no_syn_ack:
  812.  
  813.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
  814.  
  815.         push    [edx + TCP_segment.SequenceNumber]
  816.         pop     [ebx + TCP_SOCKET.IRS]
  817.  
  818.         TCP_rcvseqinit ebx
  819.  
  820.         mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  821.  
  822.         mov     eax, [ebx + TCP_SOCKET.SND_UNA]
  823.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  824.         jle     .simultaneous_open
  825.  
  826.         test    [edx + TCP_segment.Flags], TH_ACK
  827.         jz      .simultaneous_open
  828.  
  829.         DEBUGF  1,"TCP: active open\n"
  830.  
  831. ; TODO: update stats
  832. ; TODO: set general socket state to connected
  833.  
  834.         mov     [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
  835.  
  836. ; TODO: check if we should scale the connection (567-572)
  837. ; TODO: update RTT estimators
  838.  
  839.         jmp     .trimthenstep6
  840.  
  841.   .simultaneous_open:
  842.  
  843.         DEBUGF  1,"TCP: simultaneous open\n"
  844. ; We have received a syn but no ACK, so we are having a simultaneous open..
  845.         mov     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  846.  
  847. ;-------------------------------------
  848. ; Common processing for receipt of SYN
  849.  
  850.   .trimthenstep6:
  851.  
  852.         inc     [edx + TCP_segment.SequenceNumber]
  853.  
  854.         cmp     cx, [ebx + TCP_SOCKET.RCV_WND]
  855.         jle     @f
  856.  
  857.         movzx   eax, cx
  858.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  859.         ; TODO: 592
  860.         mov     cx, [ebx + TCP_SOCKET.RCV_WND]
  861.         ; TODO...
  862.        @@:
  863.         ;;;;;
  864.         jmp     .ack_processed
  865.  
  866.  
  867.   .trim_then_step6:
  868.  
  869. ;----------------------------
  870. ; trim any data not in window
  871.  
  872.         DEBUGF  1,"Trimming window\n"
  873.  
  874.         mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
  875.         sub     eax, [edx + TCP_segment.SequenceNumber]
  876.         jz      .no_duplicate
  877.  
  878.         test    [edx + TCP_segment.Flags], TH_SYN
  879.         jz      .no_drop
  880.  
  881.         and     [edx + TCP_segment.Flags], not (TH_SYN)
  882.         inc     [edx + TCP_segment.SequenceNumber]
  883.  
  884.         cmp     [edx + TCP_segment.UrgentPointer], 1
  885.         jl      @f
  886.  
  887.         dec     [edx + TCP_segment.UrgentPointer]
  888.  
  889.         jmp     .no_drop
  890.        @@:
  891.  
  892.         and     [edx + TCP_segment.Flags], not (TH_URG)
  893.         dec     eax
  894.         jz      .no_duplicate
  895.   .no_drop:
  896.  
  897.         DEBUGF  1,"Going to drop %u out of %u bytes\n", eax, ecx
  898.  
  899. ; eax holds number of bytes to drop
  900.  
  901. ;----------------------------------
  902. ; Check for entire duplicate packet
  903.  
  904.         cmp     eax, ecx
  905.         jge     .duplicate
  906.  
  907.         ;;; TODO: figure 28.30
  908.  
  909. ;------------------------
  910. ; Check for duplicate FIN
  911.  
  912.         test    [edx + TCP_segment.Flags], TH_FIN
  913.         jz      @f
  914.         inc     ecx
  915.         cmp     eax, ecx
  916.         dec     ecx
  917.         jne     @f
  918.  
  919.         mov     eax, ecx
  920.         and     [edx + TCP_segment.Flags], not TH_FIN
  921.         or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  922.         jmp     .no_duplicate
  923.        @@:
  924.  
  925.         ; Handle the case when a bound socket connects to itself
  926.         ; Allow packets with a SYN and an ACKto continue with the processing
  927.  
  928. ;-------------------------------------
  929. ; Generate duplicate ACK if nescessary
  930.  
  931. ; This code also handles simultaneous half-open or self-connects
  932.  
  933.         test    eax, eax
  934.         jnz     .drop_after_ack
  935.  
  936.         cmp     [edx + TCP_segment.Flags], TH_ACK
  937.         jz      .drop_after_ack
  938.  
  939.   .duplicate:
  940.  
  941.         DEBUGF  1,"Duplicate received\n"
  942.  
  943. ;----------------------------------------
  944. ; Update statistics for duplicate packets
  945.  
  946.         ;;; TODO
  947.  
  948.         jmp     .drop          ;;; DROP the packet ??
  949.  
  950.   .no_duplicate:
  951.  
  952. ;-----------------------------------------------
  953. ; Remove duplicate data and update urgent offset
  954.  
  955.         add     [edx + TCP_segment.SequenceNumber], eax
  956.  
  957.         ;;; TODO
  958.  
  959.         sub     [edx + TCP_segment.UrgentPointer], ax
  960.         jg      @f
  961.  
  962.         and     [edx + TCP_segment.Flags], not (TH_URG)
  963.         mov     [edx + TCP_segment.UrgentPointer], 0
  964.        @@:
  965.  
  966. ;--------------------------------------------------
  967. ; Handle data that arrives after process terminates
  968.  
  969.         cmp     [ebx + SOCKET.PID], 0
  970.         jg      @f
  971.  
  972.         cmp     [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
  973.         jle     @f
  974.  
  975.         test    ecx, ecx
  976.         jz      @f
  977.  
  978.         ;;; Close the socket
  979.         ;;; update stats
  980.  
  981.         jmp     .drop_with_reset
  982.        @@:
  983.  
  984. ;----------------------------------------
  985. ; Remove data beyond right edge of window
  986.  
  987.         mov     eax, [edx + TCP_segment.SequenceNumber]
  988.         add     eax, ecx
  989.         sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
  990.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  991.  
  992.         ; eax now holds the number of bytes to drop
  993.  
  994.         jle     .no_excess_data
  995.  
  996.         ;;; TODO: update stats
  997.  
  998.         cmp     eax, ecx
  999.         jl      .dont_drop_all
  1000.  
  1001. ;;; TODO 700-736
  1002.  
  1003.   .dont_drop_all:
  1004.  
  1005.   .no_excess_data:
  1006.  
  1007. ;-----------------
  1008. ; Record timestamp
  1009.  
  1010.         ;;; TODO 737-746
  1011.  
  1012. ;------------------
  1013. ; Process RST flags
  1014.  
  1015.         test    [edx + TCP_segment.Flags], TH_RST
  1016.         jz      .rst_skip
  1017.  
  1018.         DEBUGF  1,"Got an RST flag"
  1019.  
  1020.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1021.         shl     eax, 2
  1022.         jmp     dword [eax + .rst_sw_list]
  1023.  
  1024.   .rst_sw_list:
  1025.         dd      .rst_skip       ;TCB_CLOSED
  1026.         dd      .rst_skip       ;TCB_LISTEN
  1027.         dd      .rst_skip       ;TCB_SYN_SENT
  1028.         dd      .econnrefused   ;TCB_SYN_RECEIVED
  1029.         dd      .econnreset     ;TCB_ESTABLISHED
  1030.         dd      .econnreset     ;TCB_CLOSE_WAIT
  1031.         dd      .econnreset     ;TCB_FIN_WAIT_1
  1032.         dd      .rst_close      ;TCB_CLOSING
  1033.         dd      .rst_close      ;TCB_LAST_ACK
  1034.         dd      .econnreset     ;TCB_FIN_WAIT_2
  1035.         dd      .rst_close      ;TCB_TIMED_WAIT
  1036.  
  1037.   .econnrefused:
  1038.  
  1039.         DEBUGF  1,"Connection refused"
  1040.  
  1041.         ;;; TODO: debug info
  1042.  
  1043.         jmp     .close
  1044.  
  1045.   .econnreset:
  1046.  
  1047.         DEBUGF  1,"Connection reset"
  1048.  
  1049.         ;;; TODO: debug info
  1050.   .close:
  1051.  
  1052.         DEBUGF  1,"Closing connection"
  1053.  
  1054.         ;;; update stats
  1055.  
  1056.   .rst_close:
  1057.  
  1058.         DEBUGF  1,"Closing with reset\n"
  1059.  
  1060.         ;;; Close the socket
  1061.         jmp     .drop
  1062.  
  1063.   .rst_skip:
  1064.  
  1065. ;--------------------------------------
  1066. ; handle SYN-full and ACK-less segments
  1067.  
  1068.         test    [edx + TCP_segment.Flags], TH_SYN
  1069.         jz      @f
  1070.  
  1071.         mov     eax, ebx
  1072.         mov     ebx, ECONNRESET
  1073.         call    TCP_drop
  1074.  
  1075.         jmp     .drop_with_reset
  1076.  
  1077.         test    [edx + TCP_segment.Flags], TH_ACK
  1078.         jz      .drop
  1079.       @@:
  1080.  
  1081. ;---------------
  1082. ; ACK processing
  1083.  
  1084.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  1085.         jnz     .no_syn_rcv
  1086.  
  1087.         DEBUGF  1,"TCP state = syn received\n"
  1088.  
  1089.         ;;;;;  801-815
  1090.  
  1091.   .no_syn_rcv:
  1092.  
  1093. ; check for duplicate ACK
  1094.  
  1095.         mov     eax, [edx + TCP_segment.AckNumber]
  1096.         cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
  1097.         jg      .not_dup_ack
  1098.  
  1099.         DEBUGF  1,"Duplicate ACK\n"
  1100.  
  1101.         test    ecx, ecx
  1102.         jnz     .ack_processed
  1103.  
  1104.         mov     eax, dword [edx + TCP_segment.Window]
  1105.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1106.         jne     .ack_processed
  1107.  
  1108. ; Process the duplicate ACK
  1109.  
  1110.         ;;;;; 833 - 878
  1111.  
  1112. ;;;        call    TCP_output
  1113.         jmp     .drop
  1114.  
  1115.   .not_dup_ack:
  1116.  
  1117.         DEBUGF  1,"new ACK\n"
  1118.  
  1119.  
  1120. ;-------------------------------------------------
  1121. ; If the congestion window was inflated to account
  1122. ; for the other side's cached packets, retract it
  1123.  
  1124.         ;;;; 888 -  902
  1125.  
  1126.  
  1127. ;------------------------------------------
  1128. ; RTT measurements and retransmission timer
  1129.  
  1130.         ;;;;; 903 - 926
  1131.  
  1132.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0
  1133.  
  1134.         mov     eax, [ebx + TCP_SOCKET.SND_MAX]
  1135.         cmp     eax, [edx + TCP_segment.AckNumber]
  1136.         je      .all_outstanding
  1137.         mov     [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
  1138.   .all_outstanding:
  1139.  
  1140. ;-------------------------------------------
  1141. ; Open congestion window in response to ACKs
  1142.  
  1143.         ;;;;
  1144.  
  1145.  
  1146. ;------------------------------------------
  1147. ; Remove acknowledged data from send buffer
  1148.  
  1149.         pusha
  1150.         mov     ecx, [edx + TCP_segment.AckNumber]
  1151.         sub     ecx, [ebx + TCP_SOCKET.SND_UNA]         ; ecx now holds number of bytes acked
  1152.  
  1153.         lea     eax, [ebx + STREAM_SOCKET.snd]
  1154.         call    SOCKET_ring_free
  1155.         popa
  1156.  
  1157. ;---------------------------------------
  1158. ; Wake up process waiting on send buffer
  1159.  
  1160.         mov     eax, ebx
  1161.         call    SOCKET_notify_owner
  1162.  
  1163. ; Update TCB
  1164.  
  1165.         mov     eax, [edx + TCP_segment.AckNumber]
  1166.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  1167.  
  1168.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  1169.         jl      @f
  1170.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  1171.        @@:
  1172.  
  1173. ; General ACK handling complete
  1174. ; Now do the state-specific ones
  1175.  
  1176.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1177.         jmp     dword [eax*4 + .ACK_sw_list]
  1178.  
  1179.   .ACK_sw_list:
  1180.         dd      .ack_processed  ;TCB_CLOSED
  1181.         dd      .ack_processed  ;TCB_LISTEN
  1182.         dd      .ack_processed  ;TCB_SYN_SENT
  1183.         dd      .ack_processed  ;TCB_SYN_RECEIVED
  1184.         dd      .ack_processed  ;TCB_ESTABLISHED
  1185.         dd      .ack_processed  ;TCB_CLOSE_WAIT
  1186.         dd      .ack_fw1        ;TCB_FIN_WAIT_1
  1187.         dd      .ack_c          ;TCB_CLOSING
  1188.         dd      .ack_la         ;TCB_LAST_ACK
  1189.         dd      .ack_processed  ;TCB_FIN_WAIT_2
  1190.         dd      .ack_tw         ;TCB_TIMED_WAIT
  1191.  
  1192.  
  1193.   .ack_fw1:
  1194.  
  1195. ;;; TODO: 963
  1196.  
  1197.         jmp     .ack_processed
  1198.  
  1199.   .ack_c:
  1200.  
  1201. ;;; TODO: 958
  1202.  
  1203.         jmp     .ack_processed
  1204.  
  1205.   .ack_la:
  1206.  
  1207. ;;; TODO: 999
  1208.  
  1209.         jmp     .ack_processed
  1210.  
  1211.  
  1212.   .ack_tw:
  1213.  
  1214. ;;; TODO: 1010
  1215.  
  1216.         jmp     .ack_processed
  1217.  
  1218.  
  1219.   .ack_processed:
  1220.  
  1221.         DEBUGF  1,"ack processed\n"
  1222.  
  1223. ;----------------------------------------------
  1224. ; check if we need to update window information
  1225.  
  1226.         test    [edx + TCP_segment.Flags], TH_ACK
  1227.         jz      .no_window_update
  1228.  
  1229.         mov     eax, [ebx + TCP_SOCKET.SND_WL1]
  1230.         cmp     eax, [edx + TCP_segment.SequenceNumber]
  1231.         jl      .update_window
  1232.         jg      @f
  1233.  
  1234.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1235.         cmp     eax, [edx + TCP_segment.AckNumber]
  1236.         jl      .update_window
  1237.         jg      .no_window_update
  1238.        @@:
  1239.  
  1240.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1241.         cmp     eax, [edx + TCP_segment.AckNumber]
  1242.         jne     .no_window_update
  1243.  
  1244.         movzx   eax, [edx + TCP_segment.Window]
  1245.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1246.         jle     .no_window_update
  1247.  
  1248.   .update_window:
  1249.  
  1250.         DEBUGF  1,"Updating window\n"
  1251.  
  1252. ;----------------------------------
  1253. ; Keep track of pure window updates
  1254.  
  1255. ;        test    ecx, ecx
  1256. ;        jz      @f
  1257. ;
  1258. ;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1259. ;        cmp     eax, [edx + TCP_segment.AckNumber]
  1260. ;        jne     @f
  1261. ;
  1262. ;        ;; mov eax, tiwin
  1263. ;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1264. ;        jle     @f
  1265. ;
  1266. ;        ;;; update stats
  1267. ;
  1268. ;       @@:
  1269.  
  1270.         mov     eax, dword [edx + TCP_segment.Window]
  1271.         cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
  1272.         jle     @f
  1273.         mov     [ebx + TCP_SOCKET.max_sndwnd], eax
  1274.        @@:
  1275.         mov     [ebx + TCP_SOCKET.SND_WND], eax
  1276.  
  1277.         push    [edx + TCP_segment.SequenceNumber]
  1278.         pop     [ebx + TCP_SOCKET.SND_WL1]
  1279.  
  1280.         push    [edx + TCP_segment.AckNumber]
  1281.         pop     [ebx + TCP_SOCKET.SND_WL2]
  1282.  
  1283.         ;;; needoutput = 1
  1284.  
  1285.   .no_window_update:
  1286.  
  1287. ;-----------------
  1288. ; process URG flag
  1289.  
  1290.         test    [edx + TCP_segment.Flags], TH_URG
  1291.         jz      .not_urgent
  1292.  
  1293.         cmp     [edx + TCP_segment.UrgentPointer], 0
  1294.         jz      .not_urgent
  1295.  
  1296.         cmp     [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
  1297.         je      .not_urgent
  1298.  
  1299. ; Ignore bogus urgent offsets
  1300.  
  1301.         ;;; 1040-1050
  1302.  
  1303.         movzx   eax, [edx + TCP_segment.UrgentPointer]
  1304.         add     eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1305.         cmp     eax, SOCKET_MAXDATA
  1306.         jle     .not_urgent
  1307.  
  1308.         mov     [edx + TCP_segment.UrgentPointer], 0
  1309.         and     [edx + TCP_segment.Flags], not (TH_URG)
  1310.         jmp     .do_data
  1311.  
  1312.   .not_urgent:
  1313.  
  1314. ;--------------------------------------
  1315. ; processing of received urgent pointer
  1316.  
  1317.         ;;; TODO (1051-1093)
  1318.  
  1319. ;--------------------------------
  1320. ; process the data in the segment
  1321.  
  1322.   .do_data:
  1323.  
  1324.         DEBUGF  1,"TCP: do data (%u)\n", ecx
  1325.  
  1326.         test    [edx + TCP_segment.Flags], TH_FIN
  1327.         jnz     .process_fin
  1328.  
  1329.         cmp     [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
  1330.         jge     .dont_do_data
  1331.  
  1332.         test    ecx, ecx
  1333.         jz      .final_processing
  1334.  
  1335.         DEBUGF  1,"Processing data in segment\n"
  1336.  
  1337. ;; TODO: check if data is in sequence !
  1338.  
  1339.         movzx   eax, [edx + TCP_segment.DataOffset]             ;;; todo: remember this in.. edi ?
  1340.         and     eax, 0xf0
  1341.         shr     al, 2
  1342.  
  1343.         lea     esi, [edx + eax]
  1344.  
  1345.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
  1346.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx
  1347.  
  1348.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  1349.         call    SOCKET_ring_write
  1350.  
  1351.         mov     eax, ebx
  1352.         call    SOCKET_notify_owner
  1353.  
  1354.         jmp     .final_processing
  1355.  
  1356.  
  1357.   .dont_do_data:
  1358.  
  1359. ;---------------
  1360. ; FIN processing
  1361.  
  1362.   .process_fin:
  1363.  
  1364.         DEBUGF  1,"Processing FIN\n"
  1365.  
  1366.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1367.         shl     eax, 2
  1368.         jmp     dword [eax + .FIN_sw_list]
  1369.  
  1370.   .FIN_sw_list:
  1371.         dd      .no_fin         ;TCB_CLOSED
  1372.         dd      .no_fin         ;TCB_LISTEN
  1373.         dd      .no_fin         ;TCB_SYN_SENT
  1374.         dd      .fin_syn_est    ;TCB_SYN_RECEIVED
  1375.         dd      .fin_syn_est    ;TCB_ESTABLISHED
  1376.         dd      .no_fin         ;TCB_CLOSE_WAIT
  1377.         dd      .fin_wait1      ;TCB_FIN_WAIT_1
  1378.         dd      .no_fin         ;TCB_CLOSING
  1379.         dd      .no_fin         ;TCB_LAST_ACK
  1380.         dd      .fin_wait2      ;TCB_FIN_WAIT_2
  1381.         dd      .fin_timed      ;TCB_TIMED_WAIT
  1382.  
  1383.  
  1384.  
  1385.   .fin_syn_est:
  1386.  
  1387.         jmp     .final_processing
  1388.  
  1389.   .fin_wait1:
  1390.  
  1391.         jmp     .final_processing
  1392.  
  1393.   .fin_wait2:
  1394.  
  1395.         jmp     .final_processing
  1396.  
  1397.   .fin_timed:
  1398.  
  1399.         jmp     .final_processing
  1400.  
  1401.   .no_fin:
  1402.  
  1403. ;-----------------
  1404. ; Final processing
  1405.  
  1406.   .final_processing:
  1407.  
  1408.         DEBUGF  1,"Final processing\n"
  1409.  
  1410.         mov     [ebx + SOCKET.lock], 0
  1411.  
  1412.         ;;; if debug enabled, output packet
  1413.  
  1414.         ;test    needoutput, needoutput
  1415.         ;jz      .dumpit
  1416.  
  1417.         test    [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1418.         jz      .dumpit
  1419.  
  1420.         DEBUGF  1,"ACK now!\n"
  1421.  
  1422.         push    ebx
  1423.         mov     eax, ebx
  1424.         call    TCP_output
  1425.         pop     ebx
  1426.  
  1427.   .dumpit:
  1428.  
  1429.         call    kernel_free
  1430.         add     esp, 4
  1431.         ret
  1432.  
  1433. ;------------------------------------------
  1434. ; Generate an ACK, droping incoming segment
  1435.  
  1436. align 4
  1437. .drop_after_ack:
  1438.  
  1439.         DEBUGF  1,"Drop after ACK\n"
  1440.  
  1441.         test    [edx + TCP_segment.Flags], TH_RST
  1442.         jnz     .drop
  1443.  
  1444.         and     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1445.  
  1446.         push    ebx
  1447.         mov     eax, ebx
  1448.         call    TCP_output
  1449.         pop     ebx
  1450.  
  1451.         call    kernel_free
  1452.         add     esp, 4
  1453.         ret
  1454.  
  1455.  
  1456. ;-------------------------------------------
  1457. ; Generate an RST, dropping incoming segment
  1458.  
  1459. align 4
  1460. .drop_with_reset:
  1461.  
  1462.         DEBUGF  1,"Drop with reset\n"
  1463.  
  1464.         test    [edx + TCP_segment.Flags], TH_RST
  1465.         jnz     .drop
  1466.  
  1467.         ;;; if its a multicast/broadcast, also drop
  1468.  
  1469.         test    [edx + TCP_segment.Flags], TH_ACK
  1470.         jnz     .respond_ack
  1471.  
  1472.         test    [edx + TCP_segment.Flags], TH_SYN
  1473.         jnz     .respond_syn
  1474.  
  1475.         call    kernel_free
  1476.         add     esp, 4
  1477.         ret
  1478.  
  1479.   .respond_ack:
  1480.  
  1481.         mov     dl, TH_RST
  1482.  
  1483.         push    ebx
  1484.         call    TCP_respond_segment
  1485.         pop     ebx
  1486.  
  1487.         jmp     .destroy_new_socket
  1488.  
  1489.  
  1490.   .respond_syn:
  1491.  
  1492.         mov     dl, TH_RST + TH_ACK
  1493.  
  1494.         push    ebx
  1495.         call    TCP_respond_socket
  1496.         pop     ebx
  1497.  
  1498.         jmp     .destroy_new_socket
  1499.  
  1500. ;-----
  1501. ; Drop
  1502.  
  1503. align 4
  1504. .drop:
  1505.  
  1506.         DEBUGF  1,"Dropping packet\n"
  1507.  
  1508.         ;;;; If debugging options are enabled, output the packet somwhere
  1509.  
  1510.   .destroy_new_socket:
  1511.  
  1512.         ;;;; kill the newly created socket
  1513.  
  1514.         call    kernel_free
  1515.         add     esp, 4
  1516.         ret
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523. ;---------------------------
  1524. ;
  1525. ; TCP_pull_out_of_band
  1526. ;
  1527. ; IN:  eax =
  1528. ;      ebx = socket ptr
  1529. ;      edx = tcp packet ptr
  1530. ;
  1531. ; OUT: /
  1532. ;
  1533. ;---------------------------
  1534.  
  1535. align 4
  1536. TCP_pull_out_of_band:
  1537.  
  1538.         DEBUGF  1,"TCP_pull_out_of_band\n"
  1539.  
  1540.         ;;;; 1282-1305
  1541.  
  1542.         ret
  1543.  
  1544.  
  1545.  
  1546. ;-----------------------------------------------------------------
  1547. ;
  1548. ; TCP_output
  1549. ;
  1550. ; IN:  eax = socket pointer
  1551. ;
  1552. ; OUT: /
  1553. ;
  1554. ;-----------------------------------------------------------------
  1555. align 4
  1556. TCP_output:
  1557.  
  1558.         DEBUGF 1,"TCP_output, socket: %x\n", eax
  1559.  
  1560. ; We'll detect the length of the data to be transmitted, and flags to be used
  1561. ; If there is some data, or any critical controls to send (SYN / RST), then transmit
  1562. ; Otherwise, investigate further
  1563.  
  1564.         mov     ebx, [eax + TCP_SOCKET.SND_MAX]
  1565.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1566.         jne     .not_idle
  1567.  
  1568.         mov     ebx, [eax + TCP_SOCKET.t_idle]
  1569.         cmp     ebx, [eax + TCP_SOCKET.t_rxtcur]
  1570.         jle     .not_idle
  1571.  
  1572. ; We have been idle for a while and no ACKS are expected to clock out any data we send..
  1573. ; Slow start to get ack "clock" running again.
  1574.  
  1575.         mov     ebx, [eax + TCP_SOCKET.t_maxseg]
  1576.         mov     [eax + TCP_SOCKET.SND_CWND], ebx
  1577.  
  1578.   .not_idle:
  1579.   .again:
  1580.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]         ; calculate offset
  1581.         sub     ebx, [eax + TCP_SOCKET.SND_UNA]         ;
  1582.  
  1583.         mov     ecx, [eax + TCP_SOCKET.SND_WND]         ; determine window
  1584.         cmp     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1585.         jl      @f                                      ;
  1586.         mov     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1587.        @@:                                              ;
  1588.  
  1589.         call    TCP_outflags    ; in dl
  1590.  
  1591. ; If in persist timeout with window of 0, send 1 byte.
  1592. ; Otherwise, if window is small but nonzero, and timer expired,
  1593. ; we will send what we can and go to transmit state
  1594.  
  1595.         test    [eax + TCP_SOCKET.t_force], -1
  1596.         jz      .no_persist_timeout
  1597.  
  1598.         test    ecx, ecx
  1599.         jnz     .no_zero_window
  1600.  
  1601.         cmp     ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1602.         jge     @f
  1603.  
  1604.         and     dl, not (TH_FIN)          ; clear the FIN flag    ??? how can it be set before?
  1605.  
  1606.        @@:
  1607.         inc     ecx
  1608.         jmp     .no_persist_timeout
  1609.  
  1610.   .no_zero_window:
  1611.  
  1612.         mov     [eax + TCP_SOCKET.timer_persist], 0
  1613.         mov     [eax + TCP_SOCKET.t_rxtshift], 0
  1614.  
  1615.   .no_persist_timeout:
  1616.  
  1617. ;;;106
  1618.  
  1619.         mov     esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1620.         cmp     esi, ecx
  1621.         jl      @f
  1622.         mov     esi, ecx
  1623.        @@:
  1624.         sub     esi, ebx
  1625.  
  1626.         cmp     esi, -1
  1627.         jne     .not_minus_one
  1628.  
  1629. ; If FIN has been set, but not ACKed, and we havent been called to retransmit,
  1630. ; len (esi) will be -1
  1631. ; Otherwise, window shrank after we sent into it.
  1632. ; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
  1633. ; We will enter persist state below.
  1634. ; If window didn't close completely, just wait for an ACK
  1635.  
  1636.         xor     esi, esi
  1637.  
  1638.         test    ecx, ecx
  1639.         jnz     @f
  1640.  
  1641.         mov     [eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
  1642.  
  1643.         push    [eax + TCP_SOCKET.SND_UNA]
  1644.         pop     [eax + TCP_SOCKET.SND_NXT]
  1645.        @@:
  1646.  
  1647.   .not_minus_one:
  1648.  
  1649. ;;; 124
  1650.  
  1651.         cmp     esi, [eax + TCP_SOCKET.t_maxseg]
  1652.         jle     @f
  1653.  
  1654.         mov     esi, [eax + TCP_SOCKET.t_maxseg]
  1655.         ;sendalot = 1
  1656.  
  1657.        @@:
  1658.  
  1659. ;;; 128
  1660.  
  1661.         mov     edi, [eax + TCP_SOCKET.SND_NXT]
  1662.         add     edi, esi        ; len
  1663.         sub     edi, [eax + TCP_SOCKET.SND_UNA]
  1664.         add     edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1665.         cmp     edi, 0
  1666.         jle     @f
  1667.  
  1668.         and     dl, not (TH_FIN)          ; clear the FIN flag
  1669.  
  1670.        @@:
  1671.  
  1672.  
  1673. ; set ecx to space available in receive buffer
  1674. ; From now on, ecx will be the window we advertise to the other end
  1675.  
  1676.         mov     ecx, SOCKET_MAXDATA
  1677.         sub     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1678.  
  1679. ;------------------------------
  1680. ; Sender silly window avoidance
  1681.  
  1682.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]
  1683.         je      .send
  1684.  
  1685. ;;; TODO: 144-145
  1686.  
  1687.         test    [eax + TCP_SOCKET.t_force], -1
  1688.         jnz     .send
  1689.  
  1690.         mov     ebx, [eax + TCP_SOCKET.max_sndwnd]
  1691.         shr     ebx, 1
  1692.         cmp     ecx, ebx
  1693.         jge     .send
  1694.  
  1695.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1696.         cmp     ebx, [eax + TCP_SOCKET.SND_MAX]
  1697.         jl      .send
  1698.  
  1699. ;----------------------------------------
  1700. ; Check if a window update should be sent
  1701.  
  1702.         test    ecx, ecx        ; window
  1703.         jz      .no_window
  1704.  
  1705. ;;; TODO 154-172
  1706.  
  1707.   .no_window:
  1708.  
  1709. ;--------------------------
  1710. ; Should a segment be sent?
  1711.  
  1712.         test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  1713.         jnz     .send
  1714.  
  1715.         test    dl, TH_SYN + TH_RST
  1716.         jnz     .send
  1717.  
  1718.         mov     ebx, [eax + TCP_SOCKET.SND_UP]
  1719.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1720.         jg      .send
  1721.  
  1722.         test    dl, TH_FIN
  1723.         jz      .enter_persist
  1724.  
  1725.         test    [eax + TCP_SOCKET.t_flags], TF_SENTFIN
  1726.         jnz     .send
  1727.  
  1728.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1729.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1730.         je      .send
  1731.  
  1732. ;--------------------
  1733. ; Enter persist state
  1734.  
  1735.   .enter_persist:
  1736.  
  1737.         DEBUGF  1,"Entering persist state\n"
  1738.  
  1739. ;--------------------------------------
  1740. ; No reason to send a segment, just ret
  1741.  
  1742.         DEBUGF  1,"No reason to send a segment\n"
  1743.  
  1744.         ret
  1745.  
  1746.  
  1747. ;-----------------------------------------------
  1748. ;
  1749. ; Send a segment
  1750. ;
  1751. ; eax = socket pointer
  1752. ;  dl = flags
  1753. ;
  1754. ;-----------------------------------------------
  1755.  
  1756.   .send:
  1757.  
  1758.         DEBUGF  1,"Preparing to send a segment\n"
  1759.  
  1760.         mov     edi, TCP_segment.Data   ; edi will contain headersize
  1761.  
  1762.         sub     esp, 8                  ; create some space on stack
  1763.         push    eax                     ; save this too..
  1764.  
  1765. ;------------------------------------
  1766. ; Send options with first SYN segment
  1767.  
  1768.         test    dl, TH_SYN
  1769.         jz      .no_options
  1770.  
  1771.         push    [eax + TCP_SOCKET.ISS]
  1772.         pop     [eax + TCP_SOCKET.SND_NXT]
  1773.  
  1774.         test    [eax + TCP_SOCKET.t_flags], TF_NOOPT
  1775.         jnz     .no_options
  1776.  
  1777.         mov     ecx, 1460
  1778.         or      ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
  1779.         bswap   ecx
  1780.         push    ecx
  1781.         add     di, 4
  1782.  
  1783.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
  1784.         jz      .no_syn
  1785.  
  1786.         test    dl, TH_ACK
  1787.         jnz     .scale_opt
  1788.  
  1789.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
  1790.         jz      .no_syn
  1791.  
  1792.   .scale_opt:
  1793.         movzx   ecx, byte [eax + TCP_SOCKET.request_r_scale]
  1794.         or      ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
  1795.         bswap   ecx
  1796.         pushd   ecx
  1797.         add     di, 4
  1798.  
  1799.   .no_syn:
  1800.  
  1801. ;------------------------------------
  1802. ; Make the timestamp option if needed
  1803.  
  1804.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
  1805.         jz      .no_timestamp
  1806.  
  1807.         test    dl, TH_RST
  1808.         jnz     .no_timestamp
  1809.  
  1810.         test    dl, TH_ACK
  1811.         jz      .timestamp
  1812.  
  1813.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
  1814.         jz      .no_timestamp
  1815.  
  1816.   .timestamp:
  1817.         mov     esi, [timer_ticks]
  1818.         bswap   esi
  1819.         push    esi
  1820.         pushw   0
  1821.         pushd   TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
  1822.         add     di, 10
  1823.  
  1824.   .no_timestamp:
  1825.         ;; TODO: check if we dont exceed the max segment size
  1826.  
  1827.   .no_options:
  1828.         ; eax = socket ptr
  1829.         ; edx = flags
  1830.         ; ecx = data size
  1831.         ; edi = header size
  1832.         ; esi = snd ring buff ptr
  1833.  
  1834.         mov     ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1835.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]                        ;;; right?
  1836.         jle     @f
  1837.         mov     ecx, [eax + TCP_SOCKET.t_maxseg]
  1838.        @@:
  1839.         add     ecx, edi        ; total TCP segment size
  1840.  
  1841. ; Start by pushing all TCP header values in reverse order on stack
  1842. ; (essentially, creating the tcp header!)
  1843.  
  1844.         pushw   0       ;        .UrgentPointer          dw ?
  1845.         pushw   0       ;        .Checksum               dw ?
  1846.         pushw   0x00a0  ;        .Window                 dw ?    ;;;;;;;
  1847.         shl     edi, 2  ;        .DataOffset             db ?  only 4 left-most bits
  1848.         shl     dx, 8
  1849.         or      dx, di  ;        .Flags                  db ?
  1850.         pushw   dx
  1851.         shr     edi, 2  ;        .DataOffset             db ? ;;;;
  1852.  
  1853.         push    [eax + TCP_SOCKET.RCV_NXT]      ;        .AckNumber              dd ?
  1854.         ntohd   [esp]
  1855.  
  1856.         push    [eax + TCP_SOCKET.SND_NXT]      ;        .SequenceNumber         dd ?
  1857.         ntohd   [esp]
  1858.  
  1859.         push    [eax + TCP_SOCKET.RemotePort]   ;        .DestinationPort        dw ?
  1860.         ntohw   [esp]
  1861.  
  1862.         push    [eax + TCP_SOCKET.LocalPort]    ;        .SourcePort             dw ?
  1863.         ntohw   [esp]
  1864.  
  1865.         push    edi             ; header size
  1866.  
  1867. ; Create the IP packet
  1868.         mov     ebx, [eax + IP_SOCKET.LocalIP]  ; source ip
  1869.         mov     eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
  1870.         mov     di, IP_PROTO_TCP shl 8 + 128
  1871.         call    IPv4_output
  1872.         jz      .fail
  1873.  
  1874. ;-----------------------------------------
  1875. ; Move TCP header from stack to TCP packet
  1876.  
  1877.         push    ecx
  1878.         mov     ecx, [esp+4]
  1879.         lea     esi, [esp+4+4]
  1880.         shr     ecx, 2
  1881.         rep     movsd
  1882.         pop     ecx             ; full TCP packet size
  1883.  
  1884.         pop     esi             ; headersize
  1885.         add     esp, esi
  1886.  
  1887.         mov     [esp + 4], eax          ; packet ptr
  1888.         mov     [esp + 4+4], edx        ; packet size
  1889.  
  1890.         mov     edx, edi                ; begin of data
  1891.         sub     edx, esi                ; begin of packet (edi = begin of data)
  1892.         push    ecx
  1893.         sub     ecx, esi                ; data size
  1894.  
  1895. ;--------------
  1896. ; Copy the data
  1897.  
  1898. ; eax = ptr to ring struct
  1899. ; ecx = buffer size
  1900. ; edi = ptr to buffer
  1901.  
  1902. ;        test    ecx, ecx
  1903.         mov     eax, [esp+4]              ; socket ptr
  1904.         add     [eax + TCP_SOCKET.SND_NXT], ecx
  1905.         add     eax, STREAM_SOCKET.snd
  1906.         push    edx
  1907.         call    SOCKET_ring_read
  1908.         pop     esi
  1909.         pop     ecx
  1910.         pop     eax
  1911.  
  1912.         test    [esi + TCP_segment.Flags], TH_SYN + TH_FIN
  1913.         jz      @f
  1914.         inc     [eax + TCP_SOCKET.SND_NXT]
  1915.         ;;; TODO: update sentfin flag
  1916.        @@:
  1917.  
  1918.         mov     edx, [eax + TCP_SOCKET.SND_NXT]
  1919.         cmp     edx, [eax + TCP_SOCKET.SND_MAX]
  1920.         jle     @f
  1921.         mov     [eax + TCP_SOCKET.SND_MAX], edx
  1922.  
  1923.         ;;;; TODO: time transmission (420)
  1924.        @@:
  1925.  
  1926.         ;;; TODO: set retransmission timer
  1927.  
  1928. ;--------------------
  1929. ; Create the checksum
  1930.  
  1931.         DEBUGF  1,"checksum: ptr=%x size=%u\n", esi, ecx
  1932.  
  1933.         TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
  1934.         mov     [esi+TCP_segment.Checksum], dx
  1935.  
  1936. ;----------------
  1937. ; Send the packet
  1938.  
  1939.         DEBUGF  1,"Sending TCP Packet to device %x\n", ebx
  1940.         call    [ebx + NET_DEVICE.transmit]
  1941.         ret
  1942.  
  1943.  
  1944.   .fail:
  1945.         pop     ecx
  1946.         add     esp, ecx
  1947.         add     esp, 4+8
  1948.         DEBUGF 1,"TCP_output: failed\n"
  1949.         ret
  1950.  
  1951.  
  1952.  
  1953. ;-------------------------
  1954. ;
  1955. ; TCP_outflags
  1956. ;
  1957. ;  IN:  eax = socket ptr
  1958. ;
  1959. ;  OUT: edx = flags
  1960. ;
  1961. ;-------------------------
  1962. align 4
  1963. TCP_outflags:
  1964.  
  1965.         mov     edx, [eax + TCP_SOCKET.t_state]
  1966.         movzx   edx, byte [edx + .flaglist]
  1967.  
  1968.         DEBUGF  1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
  1969.  
  1970.         ret
  1971.  
  1972.   .flaglist:
  1973.  
  1974.         db      TH_RST + TH_ACK         ; TCB_CLOSED
  1975.         db      0                       ; TCB_LISTEN
  1976.         db      TH_SYN                  ; TCB_SYN_SENT
  1977.         db      TH_SYN + TH_ACK         ; TCB_SYN_RECEIVED
  1978.         db               TH_ACK         ; TCB_ESTABLISHED
  1979.         db               TH_ACK         ; TCB_CLOSE_WAIT
  1980.         db      TH_SYN + TH_ACK         ; TCB_FIN_WAIT_1
  1981.         db      TH_SYN + TH_ACK         ; TCB_CLOSING
  1982.         db      TH_SYN + TH_ACK         ; TCB_LAST_ACK
  1983.         db               TH_ACK         ; TCB_FIN_WAIT_2
  1984.         db               TH_ACK         ; TCB_TIMED_WAIT
  1985.  
  1986.  
  1987.  
  1988.  
  1989. ;-------------------------
  1990. ;
  1991. ; TCP_drop
  1992. ;
  1993. ;  IN:  eax = socket ptr
  1994. ;       ebx = error number
  1995. ;
  1996. ;  OUT: eax = socket ptr
  1997. ;
  1998. ;-------------------------
  1999. align 4
  2000. TCP_drop:
  2001.  
  2002.         DEBUGF  1,"TCP_drop\n"
  2003.  
  2004.         cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  2005.         jl      .no_syn_received
  2006.  
  2007.         mov     [eax + TCP_SOCKET.t_state], TCB_CLOSED
  2008.  
  2009.         call    TCP_output
  2010.  
  2011. ;;; TODO: update stats
  2012.  
  2013.         jmp     TCP_close
  2014.  
  2015.   .no_syn_received:
  2016.  
  2017. ;;; TODO: update stats
  2018.  
  2019. ;;; TODO: check if error code is "Connection timed out' and handle accordingly
  2020.  
  2021.         mov     [eax + SOCKET.errorcode], ebx
  2022.  
  2023.         jmp     TCP_close
  2024.  
  2025.  
  2026. ;-------------------------
  2027. ;
  2028. ; TCP_close
  2029. ;
  2030. ;  IN:  eax = socket ptr
  2031. ;  OUT: eax = socket ptr
  2032. ;
  2033. ;-------------------------
  2034. align 4
  2035. TCP_close:
  2036.  
  2037.         DEBUGF  1,"TCP_close\n"
  2038.  
  2039. ;;; TODO: update RTT and mean deviation
  2040. ;;; TODO: update slow start threshold
  2041. ;;; TODO: release connection resources
  2042.  
  2043. ; Now, mark the socket as being disconnected
  2044.  
  2045.         mov     [eax + SOCKET.state], 0 ;;; FIXME
  2046.  
  2047.         ret
  2048.  
  2049.  
  2050.  
  2051.  
  2052. ;---------------------------------------
  2053. ;
  2054. ; The easy way to send an ACK/RST/keepalive segment
  2055. ;
  2056. ; TCP_respond_socket:
  2057. ;
  2058. ;  IN:  ebx = socket ptr
  2059. ;        cl = flags
  2060. ;
  2061. ;--------------------------------------
  2062. align 4
  2063. TCP_respond_socket:
  2064.  
  2065.         DEBUGF  1,"TCP_respond_socket\n"
  2066.  
  2067. ;---------------------
  2068. ; Create the IP packet
  2069.  
  2070.         push    cx ebx
  2071.         mov     eax, [ebx + IP_SOCKET.RemoteIP]
  2072.         mov     ebx, [ebx + IP_SOCKET.LocalIP]
  2073.         mov     ecx, TCP_segment.Data
  2074.         mov     di , IP_PROTO_TCP shl 8 + 128
  2075.         call    IPv4_output
  2076.         test    edi, edi
  2077.         jz      .error
  2078.         pop     esi cx
  2079.         push    edx eax
  2080.  
  2081. ;-----------------------------------------------
  2082. ; Fill in the TCP header by using the socket ptr
  2083.  
  2084.         mov     ax, [esi + TCP_SOCKET.LocalPort]
  2085.         rol     ax, 8
  2086.         stosw
  2087.         mov     ax, [esi + TCP_SOCKET.RemotePort]
  2088.         rol     ax, 8
  2089.         stosw
  2090.         mov     eax, [esi + TCP_SOCKET.SND_NXT]
  2091.         bswap   eax
  2092.         stosd
  2093.         mov     eax, [esi + TCP_SOCKET.RCV_NXT]
  2094.         bswap   eax
  2095.         stosd
  2096.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2097.         stosb
  2098.         mov     al, cl
  2099.         stosb
  2100.         mov     ax, [esi + TCP_SOCKET.RCV_WND]
  2101.         rol     ax, 8
  2102.         stosw                   ; window
  2103.         xor     eax, eax
  2104.         stosd                   ; checksum + urgentpointer
  2105.  
  2106. ;---------------------
  2107. ; Fill in the checksum
  2108.  
  2109.   .checksum:
  2110.         sub     edi, TCP_segment.Data
  2111.         mov     ecx, TCP_segment.Data
  2112.         xchg    esi, edi
  2113.         TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
  2114.         mov     [esi+TCP_segment.Checksum], dx
  2115.  
  2116. ;--------------------
  2117. ; And send the segment
  2118.  
  2119.         call    [ebx + NET_DEVICE.transmit]
  2120.         ret
  2121.  
  2122.   .error:
  2123.         DEBUGF  1,"TCP_respond failed\n"
  2124.         add     esp, 2+4
  2125.  
  2126.         ret
  2127.  
  2128.  
  2129.  
  2130. ;-------------------------
  2131. ; TCP_respond.segment:
  2132. ;
  2133. ;  IN:  edx = segment ptr (a previously received segment)
  2134. ;        cl = flags
  2135.  
  2136. align 4
  2137. TCP_respond_segment:
  2138.  
  2139.         DEBUGF  1,"TCP_respond_segment\n"
  2140.  
  2141. ;---------------------
  2142. ; Create the IP packet
  2143.  
  2144.         push    cx edx
  2145.         mov     ebx, [edx - 20 + IPv4_Packet.SourceAddress]      ;;;; and what if ip packet had options?!
  2146.         mov     eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
  2147.         mov     ecx, TCP_segment.Data
  2148.         mov     di , IP_PROTO_TCP shl 8 + 128
  2149.         call    IPv4_output
  2150.         jz      .error
  2151.         pop     esi cx
  2152.  
  2153.         push    edx eax
  2154.  
  2155. ;---------------------------------------------------
  2156. ; Fill in the TCP header by using a received segment
  2157.  
  2158.         mov     ax, [esi + TCP_segment.DestinationPort]
  2159.         rol     ax, 8
  2160.         stosw
  2161.         mov     ax, [esi + TCP_segment.SourcePort]
  2162.         rol     ax, 8
  2163.         stosw
  2164.         mov     eax, [esi + TCP_segment.AckNumber]
  2165.         bswap   eax
  2166.         stosd
  2167.         xor     eax, eax
  2168.         stosd
  2169.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2170.         stosb
  2171.         mov     al, cl
  2172.         stosb
  2173.         mov     ax, 1280
  2174.         rol     ax, 8
  2175.         stosw                   ; window
  2176.         xor     eax, eax
  2177.         stosd                   ; checksum + urgentpointer
  2178.  
  2179. ;---------------------
  2180. ; Fill in the checksum
  2181.  
  2182.   .checksum:
  2183.         lea     esi, [edi - TCP_segment.Data]
  2184.         mov     ecx, TCP_segment.Data
  2185.         TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
  2186.         mov     [esi+TCP_segment.Checksum], dx
  2187.  
  2188. ;--------------------
  2189. ; And send the segment
  2190.  
  2191.         call    [ebx + NET_DEVICE.transmit]
  2192.         ret
  2193.  
  2194.   .error:
  2195.         DEBUGF  1,"TCP_respond failed\n"
  2196.         add     esp, 2+4
  2197.  
  2198.         ret
  2199.  
  2200.  
  2201.  
  2202.  
  2203. ;---------------------------------------------------------------------------
  2204. ;
  2205. ; TCP_API
  2206. ;
  2207. ; This function is called by system function 75
  2208. ;
  2209. ; IN:  subfunction number in bl
  2210. ;      device number in bh
  2211. ;      ecx, edx, .. depends on subfunction
  2212. ;
  2213. ; OUT:
  2214. ;
  2215. ;---------------------------------------------------------------------------
  2216. align 4
  2217. TCP_API:
  2218.  
  2219.         movzx   eax, bh
  2220.         shl     eax, 2
  2221.  
  2222.         test    bl, bl
  2223.         jz      .packets_tx     ; 0
  2224.         dec     bl
  2225.         jz      .packets_rx     ; 1
  2226.  
  2227. .error:
  2228.         mov     eax, -1
  2229.         ret
  2230.  
  2231. .packets_tx:
  2232.         add     eax, TCP_segments_tx
  2233.         mov     eax, [eax]
  2234.         ret
  2235.  
  2236. .packets_rx:
  2237.         add     eax, TCP_segments_rx
  2238.         mov     eax, [eax]
  2239.         ret
  2240.