Subversion Repositories Kolibri OS

Rev

Rev 1534 | 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: 1536 $
  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.Type], IP_PROTO_TCP
  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.Type], IP_PROTO_TCP
  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.         ntohld  [edx + TCP_segment.SequenceNumber]
  360.         ntohld  [edx + TCP_segment.AckNumber]
  361.  
  362.         ntohlw  [edx + TCP_segment.Window]
  363.         ntohlw  [edx + TCP_segment.UrgentPointer]
  364.         ntohlw  [edx + TCP_segment.SourcePort]
  365.         ntohlw  [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.Type], IP_PROTO_TCP
  382.         jne     .socket_loop
  383.  
  384.         mov     ax, [edx + TCP_segment.DestinationPort]
  385.         cmp     [ebx + TCP_SOCKET.LocalPort], ax
  386.         jne     .socket_loop
  387.  
  388.         mov     eax, [ebx + IP_SOCKET.RemoteIP]
  389.         cmp     eax, edi                        ; sender IP
  390.         je      @f
  391.         test    eax, eax
  392.         jnz     .socket_loop
  393.        @@:
  394.  
  395.         mov     ax, [ebx + TCP_SOCKET.RemotePort]
  396.         cmp     [edx + TCP_segment.SourcePort] , ax
  397.         je      .found_socket
  398.         test    ax, ax
  399.         jnz     .socket_loop
  400.   .found_socket:
  401.         DEBUGF  1,"Socket ptr: %x\n", ebx
  402.  
  403. ; ebx now contains the pointer to the socket
  404.  
  405. ;----------------------------
  406. ; Check if socket isnt closed
  407.  
  408.         cmp     [ebx + TCP_SOCKET.t_state], TCB_CLOSED
  409.         je      .drop
  410.  
  411. ;----------------
  412. ; Lock the socket
  413.  
  414. ;;        add     ebx, SOCKET.lock ; TODO: figure out if we should lock now already
  415. ;;        call    wait_mutex
  416. ;;        sub     ebx, SOCKET.lock
  417.  
  418.         DEBUGF  1,"Socket locked\n"
  419.  
  420. ;----------------------------------------------------------------------------------------
  421. ; unscale the window into a 32 bit value (notice that SND_SCALE must be initialised to 0)
  422.  
  423.         movzx   eax, [edx + TCP_segment.Window]
  424.         push    ecx
  425.         mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
  426.         shl     eax, cl
  427.         pop     ecx
  428.  
  429.         ;;;; do something with eax
  430.  
  431. ;-----------------------------------
  432. ; Is this socket a listening socket?
  433.  
  434.         test    [ebx + SOCKET.options], SO_ACCEPTCON
  435. ;        jnz     .listening_socket                       ;;;;; TODO
  436.  
  437. ;-------------------------------------
  438. ; Reset idle timer and keepalive timer
  439.  
  440.         mov     [ebx + TCP_SOCKET.t_idle], 0
  441.         mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
  442.  
  443. ;--------------------
  444. ; Process TCP options
  445.  
  446.         cmp     esi, 20                         ; esi is headersize
  447.         je      .no_options
  448.  
  449.         DEBUGF  1,"Segment has options\n"
  450.  
  451.         cmp     [ebx + TCP_SOCKET.t_state], TCB_LISTEN          ; no options when in listen state
  452.         jz      .no_options
  453.  
  454.         lea     edi, [edx + TCP_segment.Data]
  455.         lea     eax, [edx + esi]
  456.  
  457.   .opt_loop:
  458.         cmp     edi, eax
  459.         jge     .no_options
  460.  
  461.         cmp     byte [edi], TCP_OPT_EOL         ; end of option list?
  462.         jz      .no_options
  463.  
  464.         cmp     byte [edi], TCP_OPT_NOP         ; nop ?
  465.         jz      .opt_nop
  466.  
  467.         cmp     byte [edi], TCP_OPT_MAXSEG
  468.         je      .opt_maxseg
  469.  
  470.         cmp     byte [edi], TCP_OPT_WINDOW
  471.         je      .opt_window
  472.  
  473.         cmp     byte [edi], TCP_OPT_TIMESTAMP
  474.         je      .opt_timestamp
  475.  
  476.         jmp     .no_options     ; If we reach here, some unknown options were received, skip them all!
  477.  
  478.   .opt_nop:
  479.         inc     edi
  480.         jmp     .opt_loop
  481.  
  482.   .opt_maxseg:
  483.         cmp     byte [edi+1], 4
  484.         jne     .no_options             ; error occured, ignore all options!
  485.  
  486.         test    [edx + TCP_segment.Flags], TH_SYN
  487.         jz      @f
  488.  
  489.         movzx   eax, word[edi+2]
  490.         rol     ax, 8
  491.         DEBUGF  1,"Maxseg: %u\n", ax
  492.  
  493.         mov     [ebx + TCP_SOCKET.t_maxseg], eax
  494.  
  495.        @@:
  496.         add     edi, 4
  497.         jmp     .opt_loop
  498.  
  499.  
  500.   .opt_window:
  501.         cmp     byte [edi+1], 3
  502.         jne     .no_options
  503.  
  504.         test    [edx + TCP_segment.Flags], TH_SYN
  505.         jz      @f
  506.  
  507.         DEBUGF  1,"Got window option\n"
  508.  
  509.         ;;;;;
  510.        @@:
  511.         add     edi, 3
  512.         jmp     .opt_loop
  513.  
  514.  
  515.   .opt_timestamp:
  516.         cmp     byte [edi+1], 10
  517.         jne     .no_options
  518.  
  519.         DEBUGF  1,"Got timestamp option\n"
  520.  
  521.         ;;;;;
  522.  
  523.         add     edi, 10
  524.         jmp     .opt_loop
  525.  
  526.   .no_options:
  527.  
  528. ;-----------------------------------------------------------------------
  529. ; Time to do some header prediction (Original Principle by Van Jacobson)
  530.  
  531. ; There are two common cases for an uni-directional data transfer.
  532. ;
  533. ; General rule: the packets has no control flags, is in-sequence,
  534. ;   window width didnt change and we're not retransmitting.
  535. ;
  536. ; Second rules:
  537. ;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
  538. ;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
  539. ;
  540. ;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
  541. ;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
  542.  
  543.         cmp     [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
  544.         jnz     .not_uni_xfer
  545.  
  546.         test    [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
  547.         jnz     .not_uni_xfer
  548.  
  549.         test    [edx + TCP_segment.Flags], TH_ACK
  550.         jz      .not_uni_xfer
  551.  
  552.         mov     eax, [edx + TCP_segment.SequenceNumber]
  553.         cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
  554.         jne     .not_uni_xfer
  555.  
  556.         movzx   eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value instead: todo: figure out where to store it)
  557.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  558.         jne     .not_uni_xfer
  559.  
  560.         mov     eax, [ebx + TCP_SOCKET.SND_NXT]
  561.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  562.         jne     .not_uni_xfer
  563.  
  564. ;---------------------------------------
  565. ; check if we are sender in the uni-xfer
  566.  
  567. ; If the following 4 conditions are all true, this segment is a pure ACK.
  568. ;
  569. ; - The segment contains no data.
  570.         test    ecx, ecx
  571.         jnz     .not_sender
  572.  
  573. ; - The congestion window is greater than or equal to the current send window.
  574. ;     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.
  575.         mov     eax, [ebx + TCP_SOCKET.SND_CWND]
  576.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  577.         jl      .not_uni_xfer
  578.  
  579. ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
  580.         mov     eax, [edx + TCP_segment.AckNumber]
  581.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  582.         jg      .not_uni_xfer
  583.  
  584. ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
  585.         sub     eax, [ebx + TCP_SOCKET.SND_UNA]
  586.         jle     .not_uni_xfer
  587.  
  588.         DEBUGF  1,"Header prediction: we are sender\n"
  589.  
  590. ;---------------------------------
  591. ; Packet is a pure ACK, process it
  592.  
  593. ; Update RTT estimators
  594.  
  595. ; Delete acknowledged bytes from send buffer
  596.         mov     ecx, eax
  597.         lea     eax, [ebx + STREAM_SOCKET.snd]
  598.         call    SOCKET_ring_free
  599.  
  600. ; update window pointers
  601.         mov     eax, [edx + TCP_segment.AckNumber]
  602.         dec     eax
  603.         mov     [ebx + TCP_SOCKET.SND_WL1], eax
  604.  
  605. ; Stop retransmit timer
  606.         mov     [ebx + TCP_SOCKET.timer_ack], 0
  607.  
  608. ; Awaken waiting processes
  609.         mov     eax, ebx
  610.         call    SOCKET_notify_owner
  611.  
  612. ;; Generate more output
  613. ;;        mov     eax, ebx
  614. ;;        call    TCP_output
  615. ;;
  616. ;;        jmp     .drop
  617.         jmp     .step6
  618.  
  619. ;-------------------------------------------------
  620. ; maybe we are the receiver in the uni-xfer then..
  621.  
  622.   .not_sender:
  623. ; - The amount of data in the segment is greater than 0 (data count is in ecx)
  624.  
  625. ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
  626.         mov     eax, [edx + TCP_segment.AckNumber]
  627.         cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
  628.         jne     .not_uni_xfer
  629.  
  630. ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). ;;;;;;;
  631.  
  632.         jnz     .not_uni_xfer
  633.  
  634. ;-------------------------------------
  635. ; Complete processing of received data
  636.  
  637.         DEBUGF  1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
  638.  
  639.         add     esi, edx
  640.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  641.         call    SOCKET_ring_write                       ; Add the data to the socket buffer
  642.  
  643.         mov     eax, ebx
  644.         call    SOCKET_notify_owner
  645.  
  646.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
  647.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
  648.  
  649.         jmp     .drop
  650.  
  651. ;----------------------------------------------------
  652. ; Header prediction failed, doing it the slow way..     ;;;;; current implementation of header prediction destroys some regs (ecx) !!
  653.  
  654.   .not_uni_xfer:
  655.  
  656.         DEBUGF  1,"Header prediction failed\n"          ; time to do it the "slow" way :)
  657.  
  658. ;------------------------------
  659. ; Calculate receive window size
  660.  
  661.         ;;;;
  662.  
  663.         cmp     [ebx + TCP_SOCKET.t_state], TCB_LISTEN
  664.         je      .LISTEN
  665.  
  666.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
  667.         je      .SYN_SENT
  668.  
  669. ;--------------------------------------------
  670. ; Protection Against Wrapped Sequence Numbers
  671.  
  672. ; First, check if timestamp is present
  673.  
  674. ;;;; TODO
  675.  
  676. ; Then, check if at least some bytes of data are within window
  677.  
  678. ;;;; TODO
  679.  
  680.         jmp     .trim_then_step6
  681.  
  682. ;-------------
  683. ; Passive Open
  684.  
  685. align 4
  686. .LISTEN:
  687.  
  688.         DEBUGF  1,"TCP state: listen\n"
  689.  
  690.         test    [edx + TCP_segment.Flags], TH_RST
  691.         jnz     .drop
  692.  
  693.         test    [edx + TCP_segment.Flags], TH_ACK
  694.         jnz     .drop_with_reset
  695.  
  696.         test    [edx + TCP_segment.Flags], TH_SYN
  697.         jz      .drop
  698.  
  699.         cmp     esi, 0xffffff           ; destination ip = 255.255.255.255 ?
  700.         jz      .drop
  701.  
  702.         ; TODO: check if it's a broadcast or multicast, and drop if so
  703.  
  704.         call    SOCKET_fork
  705.         jz      .drop           ; if we could not open a new connection, drop segment (;;;; should we send RST too?)
  706.  
  707. ;-----------------------
  708. ; Fill in some variables
  709.  
  710.         add     [TCP_sequence_num], 64000
  711.  
  712.         push    [edx + TCP_segment.SourcePort]
  713.         pop     [eax + TCP_SOCKET.RemotePort]
  714.  
  715.         push    [edx + TCP_segment.SequenceNumber]
  716.         pop     [eax + TCP_SOCKET.IRS]
  717.  
  718.         push    [eax + TCP_SOCKET.ISS]
  719.         pop     [eax + TCP_SOCKET.SND_NXT]
  720.  
  721.         mov     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  722.         mov     [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  723.         mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
  724.  
  725.         mov     ebx, eax
  726.         jmp     .trim_then_step6
  727.  
  728.  
  729. ;------------
  730. ; Active Open
  731.  
  732. align 4
  733. .SYN_SENT:
  734.  
  735.         DEBUGF  1,"TCP state: syn_sent\n"
  736.  
  737.         test    [edx + TCP_segment.Flags], TH_ACK
  738.         jz      @f
  739.  
  740.         mov     eax, [edx + TCP_segment.AckNumber]
  741.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  742.         jle     .drop_with_reset
  743.  
  744. ;        mov     eax, [edx + TCP_segment.AckNumber]
  745.         cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
  746.         jg      .drop_with_reset
  747.        @@:
  748.  
  749.         test    [edx + TCP_segment.Flags], TH_RST
  750.         jz      @f
  751.  
  752.         test    [edx + TCP_segment.Flags], TH_ACK
  753.         jz      .drop
  754.  
  755.         ;tp = tcp_drop(tp, ECONNREFUSED)
  756.  
  757.         jmp     .drop
  758.        @@:
  759.  
  760.         test    [edx + TCP_segment.Flags], TH_SYN
  761.         jz      .drop
  762.  
  763. ; at this point, segment seems to be valid
  764.  
  765.         test    [edx + TCP_segment.Flags], TH_ACK
  766.         jz      .no_syn_ack
  767.  
  768. ; now, process received SYN in response to an active open
  769.  
  770.         mov     eax, [edx + TCP_segment.AckNumber]
  771.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  772.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  773.         jle     @f
  774.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  775.        @@:
  776.  
  777.   .no_syn_ack:
  778.  
  779.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
  780.  
  781.         push    [edx + TCP_segment.SequenceNumber]
  782.         pop     [ebx + TCP_SOCKET.IRS]
  783.  
  784.         TCP_rcvseqinit ebx
  785.  
  786.         mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  787.  
  788.         mov     eax, [ebx + TCP_SOCKET.SND_UNA]
  789.         cmp     eax, [ebx + TCP_SOCKET.ISS]
  790.         jle     .simultaneous_open
  791.  
  792.         test    [edx + TCP_segment.Flags], TH_ACK
  793.         jz      .simultaneous_open
  794.  
  795.         DEBUGF  1,"TCP: active open\n"
  796.  
  797. ; TODO: update stats
  798. ; TODO: set general socket state to connected
  799.  
  800.         mov     [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
  801.  
  802. ; TODO: check if we should scale the connection (567-572)
  803. ; TODO: update RTT estimators
  804.  
  805.         jmp     .trimthenstep6
  806.  
  807.   .simultaneous_open:
  808.  
  809.         DEBUGF  1,"TCP: simultaneous open\n"
  810. ; We have received a syn but no ACK, so we are having a simultaneous open..
  811.         mov     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  812.  
  813. ;-------------------------------------
  814. ; Common processing for receipt of SYN
  815.  
  816.   .trimthenstep6:
  817.  
  818.         inc     [edx + TCP_segment.SequenceNumber]
  819.  
  820.         cmp     cx, [ebx + TCP_SOCKET.RCV_WND]
  821.         jle     @f
  822.  
  823.         movzx   eax, cx
  824.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  825.         ; TODO: 592
  826.         mov     cx, [ebx + TCP_SOCKET.RCV_WND]
  827.         ; TODO...
  828.        @@:
  829.         ;;;;;
  830.         jmp     .step6
  831.  
  832.  
  833.  
  834.  
  835.  
  836.   .trim_then_step6:
  837.  
  838. ;----------------------------
  839. ; trim any data not in window
  840.  
  841.         DEBUGF  1,"Trimming window\n"
  842.  
  843.         mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
  844.         sub     eax, [edx + TCP_segment.SequenceNumber]
  845.  
  846.         test    eax, eax
  847.         jz      .no_duplicate
  848.  
  849.         test    [edx + TCP_segment.Flags], TH_SYN
  850.         jz      .no_drop
  851.  
  852.         and     [edx + TCP_segment.Flags], not (TH_SYN)
  853.         inc     [edx + TCP_segment.SequenceNumber]
  854.  
  855.         cmp     [edx + TCP_segment.UrgentPointer], 1
  856.         jl      @f
  857.  
  858.         dec     [edx + TCP_segment.UrgentPointer]
  859.  
  860.         jmp     .no_drop
  861.        @@:
  862.  
  863.         and     [edx + TCP_segment.Flags], not (TH_URG)
  864.         dec     eax
  865.         jz      .no_duplicate
  866.   .no_drop:
  867.  
  868.         DEBUGF  1,"Going to drop %u out of %u bytes\n", eax, ecx
  869.  
  870. ; eax holds number of bytes to drop
  871.  
  872. ;----------------------------------
  873. ; Check for entire duplicate packet
  874.  
  875.         cmp     eax, ecx
  876.         jge     .duplicate
  877.  
  878.         ;;; TODO: figure 28.30
  879.  
  880. ;------------------------
  881. ; Check for duplicate FIN
  882.  
  883.         test    [edx + TCP_segment.Flags], TH_FIN
  884.         jz      @f
  885.         inc     ecx
  886.         cmp     eax, ecx
  887.         dec     ecx
  888.         jne     @f
  889.  
  890.         mov     eax, ecx
  891.         and     [edx + TCP_segment.Flags], not TH_FIN
  892.         or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  893.         jmp     .no_duplicate
  894.        @@:
  895.  
  896.         ; Handle the case when a bound socket connects to itself
  897.         ; Allow packets with a SYN and an ACKto continue with the processing
  898.  
  899. ;-------------------------------------
  900. ; Generate duplicate ACK if nescessary
  901.  
  902. ; This code also handles simultaneous half-open or self-connects
  903.  
  904.         test    eax, eax
  905.         jnz     .drop_after_ack
  906.  
  907.         cmp     [edx + TCP_segment.Flags], TH_ACK
  908.         jz      .drop_after_ack
  909.  
  910.   .duplicate:
  911.  
  912.         DEBUGF  1,"Duplicate received\n"
  913.  
  914. ;----------------------------------------
  915. ; Update statistics for duplicate packets
  916.  
  917.         ;;; TODO
  918.  
  919.         jmp     .drop          ;;; DROP the packet ??
  920.  
  921.   .no_duplicate:
  922.  
  923. ;-----------------------------------------------
  924. ; Remove duplicate data and update urgent offset
  925.  
  926.         add     [edx + TCP_segment.SequenceNumber], eax
  927.  
  928.         ;;; TODO
  929.  
  930.         sub     [edx + TCP_segment.UrgentPointer], ax
  931.         jg      @f
  932.  
  933.         and     [edx + TCP_segment.Flags], not (TH_URG)
  934.         mov     [edx + TCP_segment.UrgentPointer], 0
  935.        @@:
  936.  
  937. ;--------------------------------------------------
  938. ; Handle data that arrives after process terminates
  939.  
  940.         cmp     [ebx + SOCKET.PID], 0
  941.         jg      @f
  942.  
  943.         cmp     [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
  944.         jle     @f
  945.  
  946.         test    ecx, ecx
  947.         jz      @f
  948.  
  949.         ;;; Close the socket
  950.         ;;; update stats
  951.  
  952.         jmp     .drop_with_reset
  953.        @@:
  954.  
  955. ;----------------------------------------
  956. ; Remove data beyond right edge of window
  957.  
  958.         mov     eax, [edx + TCP_segment.SequenceNumber]
  959.         add     eax, ecx
  960.         sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
  961.         sub     ax, [ebx + TCP_SOCKET.RCV_WND]
  962.  
  963.         ; eax now holds the number of bytes to drop
  964.  
  965.         jle     .no_excess_data
  966.  
  967.         ;;; TODO: update stats
  968.  
  969.         cmp     eax, ecx
  970.         jl      .dont_drop_all
  971.  
  972. ;;; TODO 700-736
  973.  
  974.   .dont_drop_all:
  975.  
  976.   .no_excess_data:
  977.  
  978. ;-----------------
  979. ; Record timestamp
  980.  
  981.         ;;; TODO 737-746
  982.  
  983. ;------------------
  984. ; Process RST flags
  985.  
  986.         test    [edx + TCP_segment.Flags], TH_RST
  987.         jz      .rst_skip
  988.  
  989.         DEBUGF  1,"Got an RST flag"
  990.  
  991.         mov     eax, [ebx + TCP_SOCKET.t_state]
  992.         shl     eax, 2
  993.         jmp     dword [eax + .rst_sw_list]
  994.  
  995.   .rst_sw_list:
  996.         dd      .rst_skip       ;TCB_CLOSED
  997.         dd      .rst_skip       ;TCB_LISTEN
  998.         dd      .rst_skip       ;TCB_SYN_SENT
  999.         dd      .econnrefused   ;TCB_SYN_RECEIVED
  1000.         dd      .econnreset     ;TCB_ESTABLISHED
  1001.         dd      .econnreset     ;TCB_CLOSE_WAIT
  1002.         dd      .econnreset     ;TCB_FIN_WAIT_1
  1003.         dd      .rst_close      ;TCB_CLOSING
  1004.         dd      .rst_close      ;TCB_LAST_ACK
  1005.         dd      .econnreset     ;TCB_FIN_WAIT_2
  1006.         dd      .rst_close      ;TCB_TIMED_WAIT
  1007.  
  1008.   .econnrefused:
  1009.  
  1010.         DEBUGF  1,"Connection refused"
  1011.  
  1012.         ;;; TODO: debug info
  1013.  
  1014.         jmp     .close
  1015.  
  1016.   .econnreset:
  1017.  
  1018.         DEBUGF  1,"Connection reset"
  1019.  
  1020.         ;;; TODO: debug info
  1021.   .close:
  1022.  
  1023.         DEBUGF  1,"Closing connection"
  1024.  
  1025.         ;;; update stats
  1026.  
  1027.   .rst_close:
  1028.  
  1029.         DEBUGF  1,"Closing with reset\n"
  1030.  
  1031.         ;;; Close the socket
  1032.         jmp     .drop
  1033.  
  1034.   .rst_skip:
  1035.  
  1036. ;--------------------------------------
  1037. ; handle SYN-full and ACK-less segments
  1038.  
  1039.         test    [edx + TCP_segment.Flags], TH_SYN
  1040.         jz      @f
  1041.  
  1042.         ;;; tcp_drop ( ECONNRESET)
  1043.         jmp     .drop_with_reset
  1044.  
  1045.         test    [edx + TCP_segment.Flags], TH_ACK
  1046.         jz      .drop
  1047.       @@:
  1048. ;----------------
  1049. ; Process the ACK
  1050.  
  1051.         cmp     [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  1052.         jg      .ack_dup
  1053.         jl      .ack_nodup
  1054.  
  1055.         DEBUGF  1,"TCP state = syn received\n"
  1056.  
  1057.         ;;;;;
  1058.  
  1059.   .ack_nodup:
  1060.  
  1061.         DEBUGF  1,"New ACK\n"
  1062.  
  1063.  
  1064.  
  1065.   .ack_dup:
  1066.  
  1067.         ;;;;
  1068.  
  1069. ;-------------------------------------------------
  1070. ; If the congestion window was inflated to account
  1071. ; for the other side's cached packets, retrace it
  1072.  
  1073.         ;;;; 888 -  902
  1074.  
  1075.  
  1076. ;------------------------------------------
  1077. ; RTT measurements and retransmission timer
  1078.  
  1079.         ;;;;; 903 - 926
  1080.  
  1081.         mov     [ebx + TCP_SOCKET.timer_retransmission], 0
  1082.  
  1083.         mov     eax, [ebx + TCP_SOCKET.SND_MAX]
  1084.         cmp     eax, [edx + TCP_segment.AckNumber]
  1085.         je      .all_outstanding
  1086.         mov     [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value
  1087.   .all_outstanding:
  1088.  
  1089. ;-------------------------------------------
  1090. ; Open congestion window in response to ACKs
  1091.  
  1092.         ;;;;
  1093.  
  1094.  
  1095. ;------------------------------------------
  1096. ; Remove acknowledged data from send buffer
  1097.  
  1098.         pusha
  1099. ; Delete acknowledged bytes from send buffer
  1100.         mov     ecx, [edx + TCP_segment.AckNumber]
  1101.         sub     ecx, [ebx + TCP_SOCKET.SND_UNA]
  1102.         lea     eax, [ebx + STREAM_SOCKET.snd]
  1103.         call    SOCKET_ring_free
  1104.         popa
  1105.  
  1106.  
  1107. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  code missing (943?)
  1108.  
  1109.         mov     eax, [edx + TCP_segment.AckNumber]
  1110.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  1111.  
  1112.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  1113.         jl      @f
  1114.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  1115.        @@:
  1116.  
  1117. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1118.  
  1119. ;---------------------------------------
  1120. ; Wake up process waiting on send buffer
  1121.  
  1122.         mov     eax, ebx
  1123.         call    SOCKET_notify_owner
  1124.  
  1125.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1126.         shl     eax, 2
  1127.         jmp     dword [eax + .ACK_sw_list]
  1128.  
  1129.   .ACK_sw_list:
  1130.         dd      .step6          ;TCB_CLOSED
  1131.         dd      .step6          ;TCB_LISTEN
  1132.         dd      .step6          ;TCB_SYN_SENT
  1133.         dd      .step6          ;TCB_SYN_RECEIVED
  1134.         dd      .step6          ;TCB_ESTABLISHED
  1135.         dd      .step6          ;TCB_CLOSE_WAIT
  1136.         dd      ._963           ;TCB_FIN_WAIT_1
  1137.         dd      ._958           ;TCB_CLOSING
  1138.         dd      ._999           ;TCB_LAST_ACK
  1139.         dd      .step6          ;TCB_FIN_WAIT_2
  1140.         dd      ._1010          ;TCB_TIMED_WAIT
  1141.  
  1142.  
  1143.   ._963:
  1144.  
  1145.  
  1146.         jmp     .step6
  1147.  
  1148.  
  1149.   ._958:
  1150.  
  1151.         jmp     .step6
  1152.  
  1153.   ._999:
  1154.  
  1155.         jmp     .step6
  1156.  
  1157.  
  1158.   ._1010:
  1159.  
  1160.         jmp     .step6
  1161.  
  1162.  
  1163.   .step6:
  1164.  
  1165.         DEBUGF  1,"step 6\n"
  1166.  
  1167. ;----------------------------------------------
  1168. ; check if we need to update window information
  1169.  
  1170.         test    [edx + TCP_segment.Flags], TH_ACK
  1171.         jz      .no_window_update
  1172.  
  1173.         mov     eax, [ebx + TCP_SOCKET.SND_WL1]
  1174.         cmp     eax, [edx + TCP_segment.SequenceNumber]
  1175.         jl      .update_window
  1176.         jg      @f
  1177.  
  1178.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1179.         cmp     eax, [edx + TCP_segment.AckNumber]
  1180.         jl      .update_window
  1181.         jg      .no_window_update
  1182.        @@:
  1183.  
  1184.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]           ;;;;
  1185.         cmp     eax, [edx + TCP_segment.AckNumber]
  1186.         jne     .no_window_update
  1187.  
  1188.         movzx   eax, [edx + TCP_segment.Window]
  1189.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1190.         jle     .no_window_update
  1191.  
  1192.   .update_window:
  1193.  
  1194.         DEBUGF  1,"Updating window\n"
  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.         movzx   eax, [edx + TCP_segment.Window]         ;;; FIXME: use pre-calculated value instead!
  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.         push    [edx + TCP_segment.SequenceNumber]
  1222.         pop     [ebx + TCP_SOCKET.SND_WL1]
  1223.  
  1224.         push    [edx + TCP_segment.AckNumber]
  1225.         pop     [ebx + TCP_SOCKET.SND_WL2]
  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. ;
  1500. ; OUT: /
  1501. ;
  1502. ;-----------------------------------------------------------------
  1503. align 4
  1504. TCP_output:
  1505.  
  1506.         DEBUGF 1,"TCP_output, socket: %x\n", eax
  1507.  
  1508. ; We'll detect the length of the data to be transmitted, and flags to be used
  1509. ; If there is some data, or any critical controls to send (SYN / RST), then transmit
  1510. ; Otherwise, investigate further
  1511.  
  1512.         mov     ebx, [eax + TCP_SOCKET.SND_MAX]
  1513.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1514.         jne     .not_idle
  1515.  
  1516.         mov     ebx, [eax + TCP_SOCKET.t_idle]
  1517.         cmp     ebx, [eax + TCP_SOCKET.t_rxtcur]
  1518.         jle     .not_idle
  1519.  
  1520. ; We have been idle for a while and no ACKS are expected to clock out any data we send..
  1521. ; Slow start to get ack "clock" running again.
  1522.  
  1523.         mov     ebx, [eax + TCP_SOCKET.t_maxseg]
  1524.         mov     [eax + TCP_SOCKET.SND_CWND], ebx
  1525.  
  1526.   .not_idle:
  1527.   .again:
  1528.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]         ; calculate offset
  1529.         sub     ebx, [eax + TCP_SOCKET.SND_UNA]         ;
  1530.  
  1531.         mov     ecx, [eax + TCP_SOCKET.SND_WND]         ; determine window
  1532.         cmp     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1533.         jl      @f                                      ;
  1534.         mov     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1535.        @@:                                              ;
  1536.  
  1537.         call    TCP_outflags    ; in dl
  1538.  
  1539. ; If in persist timeout with window of 0, send 1 byte.
  1540. ; Otherwise, if window is small but nonzero, and timer expired,
  1541. ; we will send what we can and go to transmit state
  1542.  
  1543.         test    [eax + TCP_SOCKET.t_force], -1
  1544.         jz      .no_persist_timeout
  1545.  
  1546.         test    ecx, ecx
  1547.         jnz     .no_zero_window
  1548.  
  1549.         cmp     ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1550.         jge     @f
  1551.  
  1552.         and     dl, not (TH_FIN)          ; clear the FIN flag    ??? how can it be set before?
  1553.  
  1554.        @@:
  1555.         inc     ecx
  1556.         jmp     .no_persist_timeout
  1557.  
  1558.   .no_zero_window:
  1559.  
  1560.         mov     [eax + TCP_SOCKET.timer_persist], 0     ;;;;
  1561.         mov     [eax + TCP_SOCKET.t_rxtshift], 0
  1562.  
  1563.   .no_persist_timeout:
  1564.  
  1565. ;;;106
  1566.  
  1567.         mov     esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1568.         cmp     esi, ecx
  1569.         jl      @f
  1570.         mov     esi, ecx
  1571.        @@:
  1572.         sub     esi, ebx
  1573.  
  1574.         cmp     esi, -1
  1575.         jne     .not_minus_one
  1576.  
  1577. ; If FIN has been set, but not ACKed, and we havent been called to retransmit,
  1578. ; len (esi) will be -1
  1579. ; Otherwise, window shrank after we sent into it.
  1580. ; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
  1581. ; We will enter persist state below.
  1582. ; If window didn't close completely, just wait for an ACK
  1583.  
  1584.         xor     esi, esi
  1585.  
  1586.         test    ecx, ecx
  1587.         jnz     @f
  1588.  
  1589.         mov     [eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
  1590.  
  1591.         push    [eax + TCP_SOCKET.SND_UNA]
  1592.         pop     [eax + TCP_SOCKET.SND_NXT]
  1593.        @@:
  1594.  
  1595.   .not_minus_one:
  1596.  
  1597. ;;; 124
  1598.  
  1599.         cmp     esi, [eax + TCP_SOCKET.t_maxseg]
  1600.         jle     @f
  1601.  
  1602.         mov     esi, [eax + TCP_SOCKET.t_maxseg]
  1603.         ;sendalot = 1
  1604.  
  1605.        @@:
  1606.  
  1607. ;;; 128
  1608.  
  1609.         mov     edi, [eax + TCP_SOCKET.SND_NXT]
  1610.         add     edi, esi        ; len
  1611.         sub     edi, [eax + TCP_SOCKET.SND_UNA]
  1612.         add     edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1613.         cmp     edi, 0
  1614.         jle     @f
  1615.  
  1616.         and     dl, not (TH_FIN)          ; clear the FIN flag
  1617.  
  1618.        @@:
  1619.  
  1620.  
  1621. ; set ecx to space available in receive buffer
  1622. ; From now on, ecx will be the window we advertise to the other end
  1623.  
  1624.         mov     ecx, SOCKET_MAXDATA
  1625.         sub     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1626.  
  1627. ;------------------------------
  1628. ; Sender silly window avoidance
  1629.  
  1630.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]
  1631.         je      .send
  1632.  
  1633. ;;; TODO: 144-145
  1634.  
  1635.         test    [eax + TCP_SOCKET.t_force], -1
  1636.         jnz     .send
  1637.  
  1638.         mov     ebx, [eax + TCP_SOCKET.max_sndwnd]
  1639.         shr     ebx, 1
  1640.         cmp     ecx, ebx
  1641.         jge     .send
  1642.  
  1643.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1644.         cmp     ebx, [eax + TCP_SOCKET.SND_MAX]
  1645.         jl      .send
  1646.  
  1647. ;----------------------------------------
  1648. ; Check if a window update should be sent
  1649.  
  1650.         test    ecx, ecx        ; window
  1651.         jz      .no_window
  1652.  
  1653. ;;; TODO 154-172
  1654.  
  1655.   .no_window:
  1656.  
  1657. ;--------------------------
  1658. ; Should a segment be sent?
  1659.  
  1660.         test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  1661.         jnz     .send
  1662.  
  1663.         test    dl, TH_SYN + TH_RST
  1664.         jnz     .send
  1665.  
  1666.         mov     ebx, [eax + TCP_SOCKET.SND_UP]
  1667.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1668.         jg      .send
  1669.  
  1670.         test    dl, TH_FIN
  1671.         jz      .enter_persist
  1672.  
  1673.         test    [eax + TCP_SOCKET.t_flags], TF_SENTFIN
  1674.         jnz     .send
  1675.  
  1676.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1677.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1678.         je      .send
  1679.  
  1680. ;--------------------
  1681. ; Enter persist state
  1682.  
  1683.   .enter_persist:
  1684.  
  1685.         DEBUGF  1,"Entering persist state\n"
  1686.  
  1687. ;--------------------------------------
  1688. ; No reason to send a segment, just ret
  1689.  
  1690.         DEBUGF  1,"No reason to send a segment\n"
  1691.  
  1692.         ret
  1693.  
  1694.  
  1695. ;-----------------------------------------------
  1696. ;
  1697. ; Send a segment
  1698. ;
  1699. ; eax = socket pointer
  1700. ;  dl = flags
  1701. ;
  1702. ;-----------------------------------------------
  1703.  
  1704.   .send:
  1705.  
  1706.         DEBUGF  1,"Preparing to send a segment\n"
  1707.  
  1708.         mov     edi, TCP_segment.Data   ; edi will contain headersize
  1709.  
  1710.         sub     esp, 8                  ; create some space on stack
  1711.         push    eax                     ; save this too..
  1712.  
  1713. ;------------------------------------
  1714. ; Send options with first SYN segment
  1715.  
  1716.         test    dl, TH_SYN
  1717.         jz      .no_options
  1718.  
  1719.         push    [eax + TCP_SOCKET.ISS]
  1720.         pop     [eax + TCP_SOCKET.SND_NXT]
  1721.  
  1722.         test    [eax + TCP_SOCKET.t_flags], TF_NOOPT
  1723.         jnz     .no_options
  1724.  
  1725.         mov     ecx, 1460
  1726.         or      ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
  1727.         bswap   ecx
  1728.         push    ecx
  1729.         add     di, 4
  1730.  
  1731.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
  1732.         jz      .no_syn
  1733.  
  1734.         test    dl, TH_ACK
  1735.         jnz     .scale_opt
  1736.  
  1737.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
  1738.         jz      .no_syn
  1739.  
  1740.   .scale_opt:
  1741.         movzx   ecx, byte [eax + TCP_SOCKET.request_r_scale]
  1742.         or      ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
  1743.         bswap   ecx
  1744.         pushd   ecx
  1745.         add     di, 4
  1746.  
  1747.   .no_syn:
  1748.  
  1749. ;------------------------------------
  1750. ; Make the timestamp option if needed
  1751.  
  1752.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
  1753.         jz      .no_timestamp
  1754.  
  1755.         test    dl, TH_RST
  1756.         jnz     .no_timestamp
  1757.  
  1758.         test    dl, TH_ACK
  1759.         jz      .timestamp
  1760.  
  1761.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
  1762.         jz      .no_timestamp
  1763.  
  1764.   .timestamp:
  1765.         mov     esi, [timer_ticks]
  1766.         bswap   esi
  1767.         push    esi
  1768.         pushw   0
  1769.         pushd   TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
  1770.         add     di, 10
  1771.  
  1772.   .no_timestamp:
  1773.         ;; TODO: check if we dont exceed the max segment size
  1774.  
  1775.   .no_options:
  1776.         ; eax = socket ptr
  1777.         ; edx = flags
  1778.         ; ecx = data size
  1779.         ; edi = header size
  1780.         ; esi = snd ring buff ptr
  1781.  
  1782.         mov     ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1783.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]                        ;;; right?
  1784.         jle     @f
  1785.         mov     ecx, [eax + TCP_SOCKET.t_maxseg]
  1786.        @@:
  1787.         add     ecx, edi        ; total TCP segment size
  1788.  
  1789. ; Start by pushing all TCP header values in reverse order on stack
  1790. ; (essentially, creating the tcp header!)
  1791.  
  1792.         pushw   0       ;        .UrgentPointer          dw ?
  1793.         pushw   0       ;        .Checksum               dw ?
  1794.         pushw   0x00a0  ;        .Window                 dw ?    ;;;;;;;
  1795.         shl     edi, 2  ;        .DataOffset             db ?  only 4 left-most bits
  1796.         shl     dx, 8
  1797.         or      dx, di  ;        .Flags                  db ?
  1798.         pushw   dx
  1799.         shr     edi, 2  ;        .DataOffset             db ? ;;;;
  1800.  
  1801.         push    [eax + TCP_SOCKET.RCV_NXT]      ;        .AckNumber              dd ?
  1802.         ntohld  [esp]
  1803.  
  1804.         push    [eax + TCP_SOCKET.SND_NXT]      ;        .SequenceNumber         dd ?
  1805.         ntohld  [esp]
  1806.  
  1807.         push    [eax + TCP_SOCKET.RemotePort]   ;        .DestinationPort        dw ?
  1808.         ntohlw  [esp]
  1809.  
  1810.         push    [eax + TCP_SOCKET.LocalPort]    ;        .SourcePort             dw ?
  1811.         ntohlw  [esp]
  1812.  
  1813.         push    edi             ; header size
  1814.  
  1815. ; Create the IP packet
  1816.         mov     ebx, [eax + IP_SOCKET.LocalIP]  ; source ip
  1817.         mov     eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
  1818.         mov     di, IP_PROTO_TCP shl 8 + 128
  1819.         call    IPv4_output
  1820.         jz      .fail
  1821.  
  1822. ;-----------------------------------------
  1823. ; Move TCP header from stack to TCP packet
  1824.  
  1825.         push    ecx
  1826.         mov     ecx, [esp+4]
  1827.         lea     esi, [esp+4+4]
  1828.         shr     ecx, 2
  1829.         rep     movsd
  1830.         pop     ecx             ; full TCP packet size
  1831.  
  1832.         pop     esi             ; headersize
  1833.         add     esp, esi
  1834.  
  1835.         mov     [esp + 4], eax          ; packet ptr
  1836.         mov     [esp + 4+4], edx        ; packet size
  1837.  
  1838.         mov     edx, edi                ; begin of data
  1839.         sub     edx, esi                ; begin of packet (edi = begin of data)
  1840.         push    ecx
  1841.         sub     ecx, esi                ; data size
  1842.  
  1843. ;--------------
  1844. ; Copy the data
  1845.  
  1846. ; eax = ptr to ring struct
  1847. ; ecx = buffer size
  1848. ; edi = ptr to buffer
  1849.  
  1850. ;        test    ecx, ecx
  1851.         mov     eax, [esp+4]              ; socket ptr
  1852.         add     [eax + TCP_SOCKET.SND_NXT], ecx
  1853.         add     eax, STREAM_SOCKET.snd
  1854.         push    edx
  1855.         call    SOCKET_ring_read
  1856.         pop     esi
  1857.         pop     ecx
  1858.         pop     eax
  1859.  
  1860.         test    [esi + TCP_segment.Flags], TH_SYN + TH_FIN
  1861.         jz      @f
  1862.         inc     [eax + TCP_SOCKET.SND_NXT]
  1863.         ;;; TODO: update sentfin flag
  1864.        @@:
  1865.  
  1866.         mov     edx, [eax + TCP_SOCKET.SND_NXT]
  1867.         cmp     edx, [eax + TCP_SOCKET.SND_MAX]
  1868.         jle     @f
  1869.         mov     [eax + TCP_SOCKET.SND_MAX], edx
  1870.  
  1871.         ;;;; TODO: time transmission (420)
  1872.        @@:
  1873.  
  1874.         ;;; TODO: set retransmission timer
  1875.  
  1876. ;--------------------
  1877. ; Create the checksum
  1878.  
  1879.         DEBUGF  1,"checksum: ptr=%x size=%u\n", esi, ecx
  1880.  
  1881.         TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
  1882.         mov     [esi+TCP_segment.Checksum], dx
  1883.  
  1884. ;----------------
  1885. ; Send the packet
  1886.  
  1887.         DEBUGF  1,"Sending TCP Packet to device %x\n", ebx
  1888.         call    [ebx + NET_DEVICE.transmit]
  1889.         ret
  1890.  
  1891.  
  1892.   .fail:
  1893.         pop     ecx
  1894.         add     esp, ecx
  1895.         add     esp, 4+8
  1896.         DEBUGF 1,"TCP_output: failed\n"
  1897.         ret
  1898.  
  1899.  
  1900.  
  1901. ;-------------------------
  1902. ;
  1903. ; TCP_outflags
  1904. ;
  1905. ;  IN:  eax = socket ptr
  1906. ;
  1907. ;  OUT: edx = flags
  1908. ;
  1909. ;-------------------------
  1910. align 4
  1911. TCP_outflags:
  1912.  
  1913.         mov     edx, [eax + TCP_SOCKET.t_state]
  1914.         movzx   edx, byte [edx + .flaglist]
  1915.  
  1916.         DEBUGF  1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
  1917.  
  1918.         ret
  1919.  
  1920.   .flaglist:
  1921.  
  1922.         db      TH_RST + TH_ACK         ; TCB_CLOSED
  1923.         db      0                       ; TCB_LISTEN
  1924.         db      TH_SYN                  ; TCB_SYN_SENT
  1925.         db      TH_SYN + TH_ACK         ; TCB_SYN_RECEIVED
  1926.         db               TH_ACK         ; TCB_ESTABLISHED
  1927.         db               TH_ACK         ; TCB_CLOSE_WAIT
  1928.         db      TH_SYN + TH_ACK         ; TCB_FIN_WAIT_1
  1929.         db      TH_SYN + TH_ACK         ; TCB_CLOSING
  1930.         db      TH_SYN + TH_ACK         ; TCB_LAST_ACK
  1931.         db               TH_ACK         ; TCB_FIN_WAIT_2
  1932.         db               TH_ACK         ; TCB_TIMED_WAIT
  1933.  
  1934.  
  1935.  
  1936.  
  1937. ;-------------------------
  1938. ;
  1939. ; TCP_drop
  1940. ;
  1941. ;  IN:  eax = socket ptr
  1942. ;
  1943. ;  OUT: /
  1944. ;
  1945. ;-------------------------
  1946. align 4
  1947. TCP_drop:
  1948.  
  1949.         DEBUGF  1,"TCP_drop\n"
  1950.  
  1951. ;        cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
  1952. ;        jl      .no_syn_received
  1953.  
  1954.         mov     [eax + TCP_SOCKET.t_state], TCB_CLOSED
  1955.  
  1956.         call    TCP_output
  1957.  
  1958. ;  .no_syn_received:
  1959.  
  1960.         ret
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966. ;---------------------------------------
  1967. ;
  1968. ; The easy way to send an ACK/RST/keepalive segment
  1969. ;
  1970. ; TCP_respond_socket:
  1971. ;
  1972. ;  IN:  ebx = socket ptr
  1973. ;        cl = flags
  1974. ;
  1975. ;--------------------------------------
  1976. align 4
  1977. TCP_respond_socket:
  1978.  
  1979.         DEBUGF  1,"TCP_respond_socket\n"
  1980.  
  1981. ;---------------------
  1982. ; Create the IP packet
  1983.  
  1984.         push    cx ebx
  1985.         mov     eax, [ebx + IP_SOCKET.RemoteIP]
  1986.         mov     ebx, [ebx + IP_SOCKET.LocalIP]
  1987.         mov     ecx, TCP_segment.Data
  1988.         mov     di , IP_PROTO_TCP shl 8 + 128
  1989.         call    IPv4_output
  1990.         test    edi, edi
  1991.         jz      .error
  1992.         pop     esi cx
  1993.         push    edx eax
  1994.  
  1995. ;-----------------------------------------------
  1996. ; Fill in the TCP header by using the socket ptr
  1997.  
  1998.         mov     ax, [esi + TCP_SOCKET.LocalPort]
  1999.         rol     ax, 8
  2000.         stosw
  2001.         mov     ax, [esi + TCP_SOCKET.RemotePort]
  2002.         rol     ax, 8
  2003.         stosw
  2004.         mov     eax, [esi + TCP_SOCKET.SND_NXT]
  2005.         bswap   eax
  2006.         stosd
  2007.         mov     eax, [esi + TCP_SOCKET.RCV_NXT]
  2008.         bswap   eax
  2009.         stosd
  2010.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2011.         stosb
  2012.         mov     al, cl
  2013.         stosb
  2014.         mov     ax, [esi + TCP_SOCKET.RCV_WND]
  2015.         rol     ax, 8
  2016.         stosw                   ; window
  2017.         xor     eax, eax
  2018.         stosd                   ; checksum + urgentpointer
  2019.  
  2020. ;---------------------
  2021. ; Fill in the checksum
  2022.  
  2023.   .checksum:
  2024.         sub     edi, TCP_segment.Data
  2025.         mov     ecx, TCP_segment.Data
  2026.         xchg    esi, edi
  2027.         TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
  2028.         mov     [esi+TCP_segment.Checksum], dx
  2029.  
  2030. ;--------------------
  2031. ; And send the segment
  2032.  
  2033.         call    [ebx + NET_DEVICE.transmit]
  2034.         ret
  2035.  
  2036.   .error:
  2037.         DEBUGF  1,"TCP_respond failed\n"
  2038.         add     esp, 2+4
  2039.  
  2040.         ret
  2041.  
  2042.  
  2043.  
  2044. ;-------------------------
  2045. ; TCP_respond.segment:
  2046. ;
  2047. ;  IN:  edx = segment ptr (a previously received segment)
  2048. ;        cl = flags
  2049.  
  2050. align 4
  2051. TCP_respond_segment:
  2052.  
  2053.         DEBUGF  1,"TCP_respond_segment\n"
  2054.  
  2055. ;---------------------
  2056. ; Create the IP packet
  2057.  
  2058.         push    cx edx
  2059.         mov     ebx, [edx - 20 + IPv4_Packet.SourceAddress]      ;;;; and what if ip packet had options?!
  2060.         mov     eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
  2061.         mov     ecx, TCP_segment.Data
  2062.         mov     di , IP_PROTO_TCP shl 8 + 128
  2063.         call    IPv4_output
  2064.         jz      .error
  2065.         pop     esi cx
  2066.  
  2067.         push    edx eax
  2068.  
  2069. ;---------------------------------------------------
  2070. ; Fill in the TCP header by using a received segment
  2071.  
  2072.         mov     ax, [esi + TCP_segment.DestinationPort]
  2073.         rol     ax, 8
  2074.         stosw
  2075.         mov     ax, [esi + TCP_segment.SourcePort]
  2076.         rol     ax, 8
  2077.         stosw
  2078.         mov     eax, [esi + TCP_segment.AckNumber]
  2079.         bswap   eax
  2080.         stosd
  2081.         xor     eax, eax
  2082.         stosd
  2083.         mov     al, 0x50        ; Dataoffset: 20 bytes
  2084.         stosb
  2085.         mov     al, cl
  2086.         stosb
  2087.         mov     ax, 1280
  2088.         rol     ax, 8
  2089.         stosw                   ; window
  2090.         xor     eax, eax
  2091.         stosd                   ; checksum + urgentpointer
  2092.  
  2093. ;---------------------
  2094. ; Fill in the checksum
  2095.  
  2096.   .checksum:
  2097.         lea     esi, [edi - TCP_segment.Data]
  2098.         mov     ecx, TCP_segment.Data
  2099.         TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
  2100.         mov     [esi+TCP_segment.Checksum], dx
  2101.  
  2102. ;--------------------
  2103. ; And send the segment
  2104.  
  2105.         call    [ebx + NET_DEVICE.transmit]
  2106.         ret
  2107.  
  2108.   .error:
  2109.         DEBUGF  1,"TCP_respond failed\n"
  2110.         add     esp, 2+4
  2111.  
  2112.         ret
  2113.  
  2114.  
  2115.  
  2116.  
  2117. ;---------------------------------------------------------------------------
  2118. ;
  2119. ; TCP_API
  2120. ;
  2121. ; This function is called by system function 75
  2122. ;
  2123. ; IN:  subfunction number in bl
  2124. ;      device number in bh
  2125. ;      ecx, edx, .. depends on subfunction
  2126. ;
  2127. ; OUT:
  2128. ;
  2129. ;---------------------------------------------------------------------------
  2130. align 4
  2131. TCP_API:
  2132.  
  2133.         movzx   eax, bh
  2134.         shl     eax, 2
  2135.  
  2136.         test    bl, bl
  2137.         jz      .packets_tx     ; 0
  2138.         dec     bl
  2139.         jz      .packets_rx     ; 1
  2140.  
  2141. .error:
  2142.         mov     eax, -1
  2143.         ret
  2144.  
  2145. .packets_tx:
  2146.         add     eax, TCP_segments_tx
  2147.         mov     eax, [eax]
  2148.         ret
  2149.  
  2150. .packets_rx:
  2151.         add     eax, TCP_segments_rx
  2152.         mov     eax, [eax]
  2153.         ret
  2154.