Subversion Repositories Kolibri OS

Rev

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