Subversion Repositories Kolibri OS

Rev

Rev 1536 | 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: 1542 $
  20.  
  21. ; Socket states
  22. TCB_CLOSED              equ 0
  23. TCB_LISTEN              equ 1
  24. TCB_SYN_SENT            equ 2
  25. TCB_SYN_RECEIVED        equ 3
  26. TCB_ESTABLISHED         equ 4
  27. TCB_CLOSE_WAIT          equ 5
  28. TCB_FIN_WAIT_1          equ 6
  29. TCB_CLOSING             equ 7
  30. TCB_LAST_ACK            equ 8
  31. TCB_FIN_WAIT_2          equ 9
  32. TCB_TIMED_WAIT          equ 10
  33.  
  34. ; Socket Flags
  35. TF_ACKNOW               equ 1 shl 0     ; ack peer immediately
  36. TF_DELACK               equ 1 shl 1     ; ack, but try to delay it
  37. TF_NODELAY              equ 1 shl 2     ; don't delay packets to coalesce
  38. TF_NOOPT                equ 1 shl 3     ; don't use tcp options
  39. TF_SENTFIN              equ 1 shl 4     ; have sent FIN
  40. TF_REQ_SCALE            equ 1 shl 5     ; have/will request window scaling
  41. TF_RCVD_SCALE           equ 1 shl 6     ; other side has requested scaling
  42. TF_REQ_TSTMP            equ 1 shl 7     ; have/will request timestamps
  43. TF_RCVD_TSTMP           equ 1 shl 8     ; a timestamp was received in SYN
  44. TF_SACK_PERMIT          equ 1 shl 9     ; other side said I could SACK
  45.  
  46. ; Segment flags
  47. TH_FIN                  equ 1 shl 0
  48. TH_SYN                  equ 1 shl 1
  49. TH_RST                  equ 1 shl 2
  50. TH_PUSH                 equ 1 shl 3
  51. TH_ACK                  equ 1 shl 4
  52. TH_URG                  equ 1 shl 5
  53.  
  54. ; Segment header options
  55. TCP_OPT_EOL             equ 0           ; End of option list.
  56. TCP_OPT_NOP             equ 1           ; No-Operation.
  57. TCP_OPT_MAXSEG          equ 2           ; Maximum Segment Size.
  58. TCP_OPT_WINDOW          equ 3           ; window scale
  59. TCP_OPT_TIMESTAMP       equ 8
  60.  
  61. ; Fundamental timer values
  62. TCP_time_MSL            equ 47          ; max segment lifetime (30s)
  63. TCP_time_re_min         equ 2           ; min retransmission (1,28s)
  64. TCP_time_re_max         equ 100         ; max retransmission (64s)
  65. TCP_time_pers_min       equ 8           ; min persist (5,12s)
  66. TCP_time_pers_max       equ 94          ; max persist (60,16s)
  67. TCP_time_keep_init      equ 118         ; connectione stablishment (75,52s)
  68. TCP_time_keep_idle      equ 4608        ; idle time before 1st probe (2h)
  69. TCP_time_keep_interval  equ 118         ; between probes when no response (75,52s)
  70. TCP_time_rtt_default    equ 5           ; default Round Trip Time (3,2s)
  71.  
  72. ; timer constants
  73. TCP_max_rxtshift        equ 12          ; max retransmissions waiting for ACK
  74. TCP_max_keepcnt         equ 8           ; max keepalive probes
  75.  
  76. ;
  77. TCP_max_winshift        equ 14
  78. TCP_max_win             equ 65535
  79.  
  80. struct  TCP_segment
  81.         .SourcePort             dw ?
  82.         .DestinationPort        dw ?
  83.         .SequenceNumber         dd ?
  84.         .AckNumber              dd ?
  85.         .DataOffset             db ?    ; DataOffset[0-3 bits] and Reserved[4-7]
  86.         .Flags                  db ?    ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
  87.         .Window                 dw ?
  88.         .Checksum               dw ?
  89.         .UrgentPointer          dw ?
  90.         .Data:                          ; ..or options
  91. ends
  92.  
  93. align 4
  94. uglobal
  95.         TCP_segments_tx         rd IP_MAX_INTERFACES
  96.         TCP_segments_rx         rd IP_MAX_INTERFACES
  97.         TCP_bytes_rx            rq IP_MAX_INTERFACES
  98.         TCP_bytes_tx            rq IP_MAX_INTERFACES
  99.         TCP_sequence_num        dd ?
  100. endg
  101.  
  102.  
  103. ;-----------------------------------------------------------------
  104. ;
  105. ; TCP_init
  106. ;
  107. ;  This function resets all TCP variables
  108. ;
  109. ;-----------------------------------------------------------------
  110. macro   TCP_init {
  111.  
  112.         xor     eax, eax
  113.         mov     edi, TCP_segments_tx
  114.         mov     ecx, (6*IP_MAX_INTERFACES)
  115.         rep     stosd
  116.  
  117.         pseudo_random   eax
  118.         mov     [TCP_sequence_num], eax
  119.  
  120. }
  121.  
  122.  
  123. ;----------------------
  124. ;
  125. ;
  126. ;----------------------
  127. macro   TCP_timer_160ms {
  128.  
  129. local   .loop
  130. local   .exit
  131.  
  132.         mov     eax, net_sockets
  133.   .loop:
  134.         mov     eax, [eax + SOCKET.NextPtr]
  135.         or      eax, eax
  136.         jz      .exit
  137.  
  138.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP           ;;; We should also check if family is AF_INET
  139.         jne     .loop
  140.  
  141.         dec     [eax + TCP_SOCKET.timer_ack]
  142.         jnz     .loop
  143.  
  144.         DEBUGF  1,"TCP ack for socket %x expired, time to piggyback!\n", eax
  145.  
  146.         push    eax
  147.         call    TCP_respond_socket
  148.         pop     eax
  149.  
  150.         jmp     .loop
  151.  
  152.   .exit:
  153.  
  154. }
  155.  
  156.  
  157. ;-----------------------------------------------------------------
  158. ;
  159. ;
  160. ;-----------------------------------------------------------------
  161. macro   TCP_timer_640ms {
  162.  
  163. local   .loop
  164. local   .exit
  165.  
  166. ; Update TCP sequence number
  167.  
  168.         add     [TCP_sequence_num], 64000
  169.  
  170. ; scan through all the active TCP sockets, decrementing ALL timers
  171. ; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
  172.  
  173.         mov     eax, net_sockets
  174.   .loop:
  175.         mov     eax, [eax + SOCKET.NextPtr]
  176.   .check_only:
  177.         or      eax, eax
  178.         jz      .exit
  179.  
  180.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP     ;;; We should also check if family is AF_INET
  181.         jne     .loop
  182.  
  183.         inc     [eax + TCP_SOCKET.t_idle]
  184.         dec     [eax + TCP_SOCKET.timer_retransmission]
  185.         jnz     .check_more2
  186.  
  187.         DEBUGF  1,"socket %x: Retransmission timer expired\n", eax
  188.  
  189.         push    eax
  190.         call    TCP_output
  191.         pop     eax
  192.  
  193.   .check_more2:
  194.         dec     [eax + TCP_SOCKET.timer_keepalive]
  195.         jnz     .check_more3
  196.  
  197.         DEBUGF  1,"socket %x: Keepalive expired\n", eax
  198.  
  199.         ;;; TODO: check socket state and handle accordingly
  200.  
  201.   .check_more3:
  202.         dec     [eax + TCP_SOCKET.timer_timed_wait]
  203.         jnz     .check_more5
  204.  
  205.         DEBUGF  1,"socket %x: 2MSL timer expired\n", eax
  206.  
  207.   .check_more5:
  208.         dec     [eax + TCP_SOCKET.timer_persist]
  209.         jnz     .loop
  210.  
  211.         DEBUGF  1,"socket %x: persist timer expired\n", eax
  212.  
  213.         jmp     .loop
  214.   .exit:
  215. }
  216.  
  217.  
  218.  
  219.  
  220. macro   TCP_checksum IP1, IP2 {
  221.  
  222. ;-------------
  223. ; Pseudoheader
  224.  
  225.         ; protocol type
  226.         mov     edx, IP_PROTO_TCP
  227.  
  228.         ; source address
  229.         add     dl, byte [IP1+1]
  230.         adc     dh, byte [IP1+0]
  231.         adc     dl, byte [IP1+3]
  232.         adc     dh, byte [IP1+2]
  233.  
  234.         ; destination address
  235.         adc     dl, byte [IP2+1]
  236.         adc     dh, byte [IP2+0]
  237.         adc     dl, byte [IP2+3]
  238.         adc     dh, byte [IP2+2]
  239.  
  240.         ; size
  241.         adc     dl, cl
  242.         adc     dh, ch
  243.  
  244. ;---------------------
  245. ; Real header and data
  246.  
  247.         push    esi
  248.         call    checksum_1
  249.         call    checksum_2
  250.         pop     esi
  251.  
  252. }       ; returns in dx only
  253.  
  254.  
  255. macro   TCP_sendseqinit ptr {
  256.  
  257.         push    edi                     ;;;; i dont like this static use of edi
  258.         mov     edi, [ptr + TCP_SOCKET.ISS]
  259.         mov     [ptr + TCP_SOCKET.SND_UP], edi
  260.         mov     [ptr + TCP_SOCKET.SND_MAX], edi
  261.         mov     [ptr + TCP_SOCKET.SND_NXT], edi
  262.         mov     [ptr + TCP_SOCKET.SND_UNA], edi
  263.         pop     edi
  264.  
  265. }
  266.  
  267. macro   TCP_rcvseqinit ptr {
  268.  
  269.         push    edi
  270.         mov     edi, [ptr + TCP_SOCKET.IRS]
  271.         inc     edi
  272.         mov     [ptr + TCP_SOCKET.RCV_NXT], edi
  273.         mov     [ptr + TCP_SOCKET.RCV_ADV], edi
  274.         pop     edi
  275.  
  276. }
  277.  
  278.  
  279.  
  280. ;-----------------------------------------------------------------
  281. ;
  282. ; TCP_input:
  283. ;
  284. ;  IN:  [esp] = ptr to buffer
  285. ;       [esp+4] = buffer size
  286. ;       ebx = ptr to device struct
  287. ;       ecx = segment size
  288. ;       edx = ptr to TCP segment
  289. ;
  290. ;       esi = ipv4 source address
  291. ;       edi = ipv4 dest   address
  292. ;
  293. ;  OUT: /
  294. ;
  295. ;-----------------------------------------------------------------
  296. align 4
  297. TCP_input:
  298.  
  299.        DEBUGF  1,"TCP_input size=%u\n", ecx
  300. ; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length.
  301.  
  302.         movzx   eax, [edx + TCP_segment.DataOffset]
  303.         and     eax, 0xf0
  304.         shr     al, 2
  305.  
  306.         DEBUGF  1,"headersize=%u\n", eax
  307.  
  308.         cmp     eax, 20
  309.         jl      .drop
  310.  
  311. ;-------------------------------
  312. ; Now, re-calculate the checksum
  313.  
  314.         push    eax ecx edx
  315.         pushw   [edx + TCP_segment.Checksum]
  316.         mov     [edx + TCP_segment.Checksum], 0
  317.         push    esi edi
  318.         mov     esi, edx
  319.         TCP_checksum (esp), (esp+4)
  320.         pop     esi edi ; yes, swap them (we dont need dest addr)
  321.         pop     cx      ; previous checksum
  322.         cmp     cx, dx
  323.         pop     edx ecx esi
  324.         jnz     .drop
  325.  
  326.         DEBUGF  1,"Checksum is correct\n"
  327.  
  328.         sub     ecx, esi        ; update packet size
  329.         jl      .drop
  330.         DEBUGF  1,"we got %u bytes of data\n", ecx
  331.  
  332. ;-----------------------------------------------------------------------------------------
  333. ; Check if this packet has a timestamp option (We do it here so we can process it quickly)
  334.  
  335.         cmp     esi, 20 + 12                                    ; Timestamp option is 12 bytes
  336.         jl      .no_timestamp
  337.         je      .is_ok
  338.  
  339.         cmp     byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list
  340.         jne     .no_timestamp
  341.  
  342.   .is_ok:
  343.         test    [edx + TCP_segment.Flags], TH_SYN               ; SYN flag must not be set
  344.         jnz     .no_timestamp
  345.  
  346.         cmp     dword [edx + TCP_segment.Data], 0x0101080a      ; Timestamp header
  347.         jne     .no_timestamp
  348.  
  349.         DEBUGF  1,"timestamp ok\n"
  350.  
  351.         ; TODO: Parse the option
  352.         ; TODO: Set a Bit in the TCP to tell all options are parsed
  353.  
  354.   .no_timestamp:
  355.  
  356. ;-------------------------------------------
  357. ; Convert Big-endian values to little endian
  358.  
  359.         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.Protocol], IP_PROTO_TCP     ;;; We should also check if family is AF_INET
  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.  
  1110.  
  1111.         mov     eax, [edx + TCP_segment.AckNumber]
  1112.         mov     [ebx + TCP_SOCKET.SND_UNA], eax
  1113.  
  1114.         cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
  1115.         jl      @f
  1116.         mov     [ebx + TCP_SOCKET.SND_NXT], eax
  1117.        @@:
  1118.  
  1119.  
  1120. ;---------------------------------------
  1121. ; Wake up process waiting on send buffer
  1122.  
  1123.         mov     eax, ebx
  1124.         call    SOCKET_notify_owner
  1125.  
  1126.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1127.         shl     eax, 2
  1128.         jmp     dword [eax + .ACK_sw_list]
  1129.  
  1130.   .ACK_sw_list:
  1131.         dd      .step6          ;TCB_CLOSED
  1132.         dd      .step6          ;TCB_LISTEN
  1133.         dd      .step6          ;TCB_SYN_SENT
  1134.         dd      .step6          ;TCB_SYN_RECEIVED
  1135.         dd      .step6          ;TCB_ESTABLISHED
  1136.         dd      .step6          ;TCB_CLOSE_WAIT
  1137.         dd      ._963           ;TCB_FIN_WAIT_1
  1138.         dd      ._958           ;TCB_CLOSING
  1139.         dd      ._999           ;TCB_LAST_ACK
  1140.         dd      .step6          ;TCB_FIN_WAIT_2
  1141.         dd      ._1010          ;TCB_TIMED_WAIT
  1142.  
  1143.  
  1144.   ._963:
  1145.  
  1146.  
  1147.         jmp     .step6
  1148.  
  1149.  
  1150.   ._958:
  1151.  
  1152.         jmp     .step6
  1153.  
  1154.   ._999:
  1155.  
  1156.         jmp     .step6
  1157.  
  1158.  
  1159.   ._1010:
  1160.  
  1161.         jmp     .step6
  1162.  
  1163.  
  1164.   .step6:
  1165.  
  1166.         DEBUGF  1,"step 6\n"
  1167.  
  1168. ;----------------------------------------------
  1169. ; check if we need to update window information
  1170.  
  1171.         test    [edx + TCP_segment.Flags], TH_ACK
  1172.         jz      .no_window_update
  1173.  
  1174.         mov     eax, [ebx + TCP_SOCKET.SND_WL1]
  1175.         cmp     eax, [edx + TCP_segment.SequenceNumber]
  1176.         jl      .update_window
  1177.         jg      @f
  1178.  
  1179.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1180.         cmp     eax, [edx + TCP_segment.AckNumber]
  1181.         jl      .update_window
  1182.         jg      .no_window_update
  1183.        @@:
  1184.  
  1185.         mov     eax, [ebx + TCP_SOCKET.SND_WL2]           ;;;;
  1186.         cmp     eax, [edx + TCP_segment.AckNumber]
  1187.         jne     .no_window_update
  1188.  
  1189.         movzx   eax, [edx + TCP_segment.Window]
  1190.         cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1191.         jle     .no_window_update
  1192.  
  1193.   .update_window:
  1194.  
  1195.         DEBUGF  1,"Updating window\n"
  1196.  
  1197. ;----------------------------------
  1198. ; Keep track of pure window updates
  1199.  
  1200. ;        test    ecx, ecx
  1201. ;        jz      @f
  1202. ;
  1203. ;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
  1204. ;        cmp     eax, [edx + TCP_segment.AckNumber]
  1205. ;        jne     @f
  1206. ;
  1207. ;        ;; mov eax, tiwin
  1208. ;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
  1209. ;        jle     @f
  1210. ;
  1211. ;        ;;; update stats
  1212. ;
  1213. ;       @@:
  1214.  
  1215.         movzx   eax, [edx + TCP_segment.Window]         ;;; FIXME: use pre-calculated value instead!
  1216.         cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
  1217.         jle     @f
  1218.         mov     [ebx + TCP_SOCKET.max_sndwnd], eax
  1219.        @@:
  1220.         mov     [ebx + TCP_SOCKET.SND_WND], eax
  1221.  
  1222.         push    [edx + TCP_segment.SequenceNumber]
  1223.         pop     [ebx + TCP_SOCKET.SND_WL1]
  1224.  
  1225.         push    [edx + TCP_segment.AckNumber]
  1226.         pop     [ebx + TCP_SOCKET.SND_WL2]
  1227.  
  1228.         ;;; needoutput = 1
  1229.  
  1230.   .no_window_update:
  1231.  
  1232. ;-----------------
  1233. ; process URG flag
  1234.  
  1235.         test    [edx + TCP_segment.Flags], TH_URG
  1236.         jz      .not_urgent
  1237.  
  1238.         cmp     [edx + TCP_segment.UrgentPointer], 0
  1239.         jz      .not_urgent
  1240.  
  1241.         cmp     [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
  1242.         je      .not_urgent
  1243.  
  1244. ; Ignore bogus urgent offsets
  1245.  
  1246.         ;;; 1040-1050
  1247.  
  1248.         movzx   eax, [edx + TCP_segment.UrgentPointer]
  1249.         add     eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1250.         cmp     eax, SOCKET_MAXDATA
  1251.         jle     .not_urgent
  1252.  
  1253.         mov     [edx + TCP_segment.UrgentPointer], 0
  1254.         and     [edx + TCP_segment.Flags], not (TH_URG)
  1255.         jmp     .do_data
  1256.  
  1257.   .not_urgent:
  1258.  
  1259. ;--------------------------------------
  1260. ; processing of received urgent pointer
  1261.  
  1262.         ;;; TODO (1051-1093)
  1263.  
  1264. ;--------------------------------
  1265. ; process the data in the segment
  1266.  
  1267.   .do_data:
  1268.  
  1269.         DEBUGF  1,"TCP: do data (%u)\n", ecx
  1270.  
  1271.         test    [edx + TCP_segment.Flags], TH_FIN
  1272.         jnz     .process_fin
  1273.  
  1274.         cmp     [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
  1275.         jge     .dont_do_data
  1276.  
  1277.         test    ecx, ecx
  1278.         jz      .final_processing
  1279.  
  1280.         DEBUGF  1,"Processing data in segment\n"
  1281.  
  1282. ;; TODO: check if data is in sequence !
  1283.  
  1284.         movzx   eax, [edx + TCP_segment.DataOffset]             ;;; todo: remember this in.. edi ?
  1285.         and     eax, 0xf0
  1286.         shr     al, 2
  1287.  
  1288.         lea     esi, [edx + eax]
  1289.  
  1290.         or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
  1291.         add     [ebx + TCP_SOCKET.RCV_NXT], ecx          ;;; right ?
  1292.  
  1293.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  1294.         call    SOCKET_ring_write
  1295.  
  1296.         mov     eax, ebx
  1297.         call    SOCKET_notify_owner
  1298.  
  1299.         jmp     .final_processing
  1300.  
  1301.  
  1302.   .dont_do_data:
  1303.  
  1304. ;---------------
  1305. ; FIN processing
  1306.  
  1307.   .process_fin:
  1308.  
  1309.         DEBUGF  1,"Processing FIN\n"
  1310.  
  1311.         mov     eax, [ebx + TCP_SOCKET.t_state]
  1312.         shl     eax, 2
  1313.         jmp     dword [eax + .FIN_sw_list]
  1314.  
  1315.   .FIN_sw_list:
  1316.         dd      .no_fin         ;TCB_CLOSED
  1317.         dd      .no_fin         ;TCB_LISTEN
  1318.         dd      .no_fin         ;TCB_SYN_SENT
  1319.         dd      .fin_syn_est    ;TCB_SYN_RECEIVED
  1320.         dd      .fin_syn_est    ;TCB_ESTABLISHED
  1321.         dd      .no_fin         ;TCB_CLOSE_WAIT
  1322.         dd      .fin_wait1      ;TCB_FIN_WAIT_1
  1323.         dd      .no_fin         ;TCB_CLOSING
  1324.         dd      .no_fin         ;TCB_LAST_ACK
  1325.         dd      .fin_wait2      ;TCB_FIN_WAIT_2
  1326.         dd      .fin_timed      ;TCB_TIMED_WAIT
  1327.  
  1328.  
  1329.  
  1330.   .fin_syn_est:
  1331.  
  1332.         jmp     .final_processing
  1333.  
  1334.   .fin_wait1:
  1335.  
  1336.         jmp     .final_processing
  1337.  
  1338.   .fin_wait2:
  1339.  
  1340.         jmp     .final_processing
  1341.  
  1342.   .fin_timed:
  1343.  
  1344.         jmp     .final_processing
  1345.  
  1346.   .no_fin:
  1347.  
  1348. ;-----------------
  1349. ; Final processing
  1350.  
  1351.   .final_processing:
  1352.  
  1353.         DEBUGF  1,"Final processing\n"
  1354.  
  1355.         mov     [ebx + SOCKET.lock], 0
  1356.  
  1357.         ;;; if debug enabled, output packet
  1358.  
  1359.         ;test    ;;;needoutput = 1
  1360.         ;jnz     .outputnow
  1361.  
  1362.         test    [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1363.         jnz     .ack_now
  1364.  
  1365.         call    kernel_free
  1366.         add     esp, 4
  1367.         ret
  1368.  
  1369.   .ack_now:
  1370.  
  1371.         DEBUGF  1,"ACK now!\n"
  1372.  
  1373.         push    ebx
  1374.         mov     eax, ebx
  1375.         call    TCP_output
  1376.         pop     ebx
  1377.  
  1378.         call    kernel_free
  1379.         add     esp, 4
  1380.         ret
  1381.  
  1382. ;------------------------------------------
  1383. ; Generate an ACK, droping incoming segment
  1384.  
  1385. align 4
  1386. .drop_after_ack:
  1387.  
  1388.         DEBUGF  1,"Drop after ACK\n"
  1389.  
  1390.         test    [edx + TCP_segment.Flags], TH_RST
  1391.         jnz     .drop
  1392.  
  1393.         and     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
  1394.  
  1395.         push    ebx
  1396.         mov     eax, ebx
  1397.         call    TCP_output
  1398.         pop     ebx
  1399.  
  1400.         call    kernel_free
  1401.         add     esp, 4
  1402.         ret
  1403.  
  1404.  
  1405. ;-------------------------------------------
  1406. ; Generate an RST, dropping incoming segment
  1407.  
  1408. align 4
  1409. .drop_with_reset:
  1410.  
  1411.         DEBUGF  1,"Drop with reset\n"
  1412.  
  1413.         test    [edx + TCP_segment.Flags], TH_RST
  1414.         jnz     .drop
  1415.  
  1416.         ;;; if its a multicast/broadcast, also drop
  1417.  
  1418.         test    [edx + TCP_segment.Flags], TH_ACK
  1419.         jnz     .respond_ack
  1420.  
  1421.         test    [edx + TCP_segment.Flags], TH_SYN
  1422.         jnz     .respond_syn
  1423.  
  1424.         call    kernel_free
  1425.         add     esp, 4
  1426.         ret
  1427.  
  1428.   .respond_ack:
  1429.  
  1430.         mov     dl, TH_RST
  1431.  
  1432.         push    ebx
  1433.         call    TCP_respond_segment
  1434.         pop     ebx
  1435.  
  1436.         jmp     .destroy_new_socket
  1437.  
  1438.  
  1439.   .respond_syn:
  1440.  
  1441.         mov     dl, TH_RST + TH_ACK
  1442.  
  1443.         push    ebx
  1444.         call    TCP_respond_socket
  1445.         pop     ebx
  1446.  
  1447.         jmp     .destroy_new_socket
  1448.  
  1449. ;-----
  1450. ; Drop
  1451.  
  1452. align 4
  1453. .drop:
  1454.  
  1455.         DEBUGF  1,"Dropping packet\n"
  1456.  
  1457.         ;;;; If debugging options are enabled, output the packet somwhere
  1458.  
  1459.   .destroy_new_socket:
  1460.  
  1461.         ;;;; kill the newly created socket
  1462.  
  1463.         call    kernel_free
  1464.         add     esp, 4
  1465.         ret
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.  
  1472. ;---------------------------
  1473. ;
  1474. ; TCP_pull_out_of_band
  1475. ;
  1476. ; IN:  eax =
  1477. ;      ebx = socket ptr
  1478. ;      edx = tcp packet ptr
  1479. ;
  1480. ; OUT: /
  1481. ;
  1482. ;---------------------------
  1483.  
  1484. align 4
  1485. TCP_pull_out_of_band:
  1486.  
  1487.         DEBUGF  1,"TCP_pull_out_of_band\n"
  1488.  
  1489.         ;;;; 1282-1305
  1490.  
  1491.         ret
  1492.  
  1493.  
  1494.  
  1495. ;-----------------------------------------------------------------
  1496. ;
  1497. ; TCP_output
  1498. ;
  1499. ; IN:  eax = socket pointer
  1500. ;
  1501. ; OUT: /
  1502. ;
  1503. ;-----------------------------------------------------------------
  1504. align 4
  1505. TCP_output:
  1506.  
  1507.         DEBUGF 1,"TCP_output, socket: %x\n", eax
  1508.  
  1509. ; We'll detect the length of the data to be transmitted, and flags to be used
  1510. ; If there is some data, or any critical controls to send (SYN / RST), then transmit
  1511. ; Otherwise, investigate further
  1512.  
  1513.         mov     ebx, [eax + TCP_SOCKET.SND_MAX]
  1514.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1515.         jne     .not_idle
  1516.  
  1517.         mov     ebx, [eax + TCP_SOCKET.t_idle]
  1518.         cmp     ebx, [eax + TCP_SOCKET.t_rxtcur]
  1519.         jle     .not_idle
  1520.  
  1521. ; We have been idle for a while and no ACKS are expected to clock out any data we send..
  1522. ; Slow start to get ack "clock" running again.
  1523.  
  1524.         mov     ebx, [eax + TCP_SOCKET.t_maxseg]
  1525.         mov     [eax + TCP_SOCKET.SND_CWND], ebx
  1526.  
  1527.   .not_idle:
  1528.   .again:
  1529.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]         ; calculate offset
  1530.         sub     ebx, [eax + TCP_SOCKET.SND_UNA]         ;
  1531.  
  1532.         mov     ecx, [eax + TCP_SOCKET.SND_WND]         ; determine window
  1533.         cmp     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1534.         jl      @f                                      ;
  1535.         mov     ecx, [eax + TCP_SOCKET.SND_CWND]        ;
  1536.        @@:                                              ;
  1537.  
  1538.         call    TCP_outflags    ; in dl
  1539.  
  1540. ; If in persist timeout with window of 0, send 1 byte.
  1541. ; Otherwise, if window is small but nonzero, and timer expired,
  1542. ; we will send what we can and go to transmit state
  1543.  
  1544.         test    [eax + TCP_SOCKET.t_force], -1
  1545.         jz      .no_persist_timeout
  1546.  
  1547.         test    ecx, ecx
  1548.         jnz     .no_zero_window
  1549.  
  1550.         cmp     ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1551.         jge     @f
  1552.  
  1553.         and     dl, not (TH_FIN)          ; clear the FIN flag    ??? how can it be set before?
  1554.  
  1555.        @@:
  1556.         inc     ecx
  1557.         jmp     .no_persist_timeout
  1558.  
  1559.   .no_zero_window:
  1560.  
  1561.         mov     [eax + TCP_SOCKET.timer_persist], 0     ;;;;
  1562.         mov     [eax + TCP_SOCKET.t_rxtshift], 0
  1563.  
  1564.   .no_persist_timeout:
  1565.  
  1566. ;;;106
  1567.  
  1568.         mov     esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1569.         cmp     esi, ecx
  1570.         jl      @f
  1571.         mov     esi, ecx
  1572.        @@:
  1573.         sub     esi, ebx
  1574.  
  1575.         cmp     esi, -1
  1576.         jne     .not_minus_one
  1577.  
  1578. ; If FIN has been set, but not ACKed, and we havent been called to retransmit,
  1579. ; len (esi) will be -1
  1580. ; Otherwise, window shrank after we sent into it.
  1581. ; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
  1582. ; We will enter persist state below.
  1583. ; If window didn't close completely, just wait for an ACK
  1584.  
  1585.         xor     esi, esi
  1586.  
  1587.         test    ecx, ecx
  1588.         jnz     @f
  1589.  
  1590.         mov     [eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
  1591.  
  1592.         push    [eax + TCP_SOCKET.SND_UNA]
  1593.         pop     [eax + TCP_SOCKET.SND_NXT]
  1594.        @@:
  1595.  
  1596.   .not_minus_one:
  1597.  
  1598. ;;; 124
  1599.  
  1600.         cmp     esi, [eax + TCP_SOCKET.t_maxseg]
  1601.         jle     @f
  1602.  
  1603.         mov     esi, [eax + TCP_SOCKET.t_maxseg]
  1604.         ;sendalot = 1
  1605.  
  1606.        @@:
  1607.  
  1608. ;;; 128
  1609.  
  1610.         mov     edi, [eax + TCP_SOCKET.SND_NXT]
  1611.         add     edi, esi        ; len
  1612.         sub     edi, [eax + TCP_SOCKET.SND_UNA]
  1613.         add     edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1614.         cmp     edi, 0
  1615.         jle     @f
  1616.  
  1617.         and     dl, not (TH_FIN)          ; clear the FIN flag
  1618.  
  1619.        @@:
  1620.  
  1621.  
  1622. ; set ecx to space available in receive buffer
  1623. ; From now on, ecx will be the window we advertise to the other end
  1624.  
  1625.         mov     ecx, SOCKET_MAXDATA
  1626.         sub     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
  1627.  
  1628. ;------------------------------
  1629. ; Sender silly window avoidance
  1630.  
  1631.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]
  1632.         je      .send
  1633.  
  1634. ;;; TODO: 144-145
  1635.  
  1636.         test    [eax + TCP_SOCKET.t_force], -1
  1637.         jnz     .send
  1638.  
  1639.         mov     ebx, [eax + TCP_SOCKET.max_sndwnd]
  1640.         shr     ebx, 1
  1641.         cmp     ecx, ebx
  1642.         jge     .send
  1643.  
  1644.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1645.         cmp     ebx, [eax + TCP_SOCKET.SND_MAX]
  1646.         jl      .send
  1647.  
  1648. ;----------------------------------------
  1649. ; Check if a window update should be sent
  1650.  
  1651.         test    ecx, ecx        ; window
  1652.         jz      .no_window
  1653.  
  1654. ;;; TODO 154-172
  1655.  
  1656.   .no_window:
  1657.  
  1658. ;--------------------------
  1659. ; Should a segment be sent?
  1660.  
  1661.         test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
  1662.         jnz     .send
  1663.  
  1664.         test    dl, TH_SYN + TH_RST
  1665.         jnz     .send
  1666.  
  1667.         mov     ebx, [eax + TCP_SOCKET.SND_UP]
  1668.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1669.         jg      .send
  1670.  
  1671.         test    dl, TH_FIN
  1672.         jz      .enter_persist
  1673.  
  1674.         test    [eax + TCP_SOCKET.t_flags], TF_SENTFIN
  1675.         jnz     .send
  1676.  
  1677.         mov     ebx, [eax + TCP_SOCKET.SND_NXT]
  1678.         cmp     ebx, [eax + TCP_SOCKET.SND_UNA]
  1679.         je      .send
  1680.  
  1681. ;--------------------
  1682. ; Enter persist state
  1683.  
  1684.   .enter_persist:
  1685.  
  1686.         DEBUGF  1,"Entering persist state\n"
  1687.  
  1688. ;--------------------------------------
  1689. ; No reason to send a segment, just ret
  1690.  
  1691.         DEBUGF  1,"No reason to send a segment\n"
  1692.  
  1693.         ret
  1694.  
  1695.  
  1696. ;-----------------------------------------------
  1697. ;
  1698. ; Send a segment
  1699. ;
  1700. ; eax = socket pointer
  1701. ;  dl = flags
  1702. ;
  1703. ;-----------------------------------------------
  1704.  
  1705.   .send:
  1706.  
  1707.         DEBUGF  1,"Preparing to send a segment\n"
  1708.  
  1709.         mov     edi, TCP_segment.Data   ; edi will contain headersize
  1710.  
  1711.         sub     esp, 8                  ; create some space on stack
  1712.         push    eax                     ; save this too..
  1713.  
  1714. ;------------------------------------
  1715. ; Send options with first SYN segment
  1716.  
  1717.         test    dl, TH_SYN
  1718.         jz      .no_options
  1719.  
  1720.         push    [eax + TCP_SOCKET.ISS]
  1721.         pop     [eax + TCP_SOCKET.SND_NXT]
  1722.  
  1723.         test    [eax + TCP_SOCKET.t_flags], TF_NOOPT
  1724.         jnz     .no_options
  1725.  
  1726.         mov     ecx, 1460
  1727.         or      ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
  1728.         bswap   ecx
  1729.         push    ecx
  1730.         add     di, 4
  1731.  
  1732.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
  1733.         jz      .no_syn
  1734.  
  1735.         test    dl, TH_ACK
  1736.         jnz     .scale_opt
  1737.  
  1738.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
  1739.         jz      .no_syn
  1740.  
  1741.   .scale_opt:
  1742.         movzx   ecx, byte [eax + TCP_SOCKET.request_r_scale]
  1743.         or      ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
  1744.         bswap   ecx
  1745.         pushd   ecx
  1746.         add     di, 4
  1747.  
  1748.   .no_syn:
  1749.  
  1750. ;------------------------------------
  1751. ; Make the timestamp option if needed
  1752.  
  1753.         test    [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
  1754.         jz      .no_timestamp
  1755.  
  1756.         test    dl, TH_RST
  1757.         jnz     .no_timestamp
  1758.  
  1759.         test    dl, TH_ACK
  1760.         jz      .timestamp
  1761.  
  1762.         test    [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
  1763.         jz      .no_timestamp
  1764.  
  1765.   .timestamp:
  1766.         mov     esi, [timer_ticks]
  1767.         bswap   esi
  1768.         push    esi
  1769.         pushw   0
  1770.         pushd   TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
  1771.         add     di, 10
  1772.  
  1773.   .no_timestamp:
  1774.         ;; TODO: check if we dont exceed the max segment size
  1775.  
  1776.   .no_options:
  1777.         ; eax = socket ptr
  1778.         ; edx = flags
  1779.         ; ecx = data size
  1780.         ; edi = header size
  1781.         ; esi = snd ring buff ptr
  1782.  
  1783.         mov     ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
  1784.         cmp     ecx, [eax + TCP_SOCKET.t_maxseg]                        ;;; right?
  1785.         jle     @f
  1786.         mov     ecx, [eax + TCP_SOCKET.t_maxseg]
  1787.        @@:
  1788.         add     ecx, edi        ; total TCP segment size
  1789.  
  1790. ; Start by pushing all TCP header values in reverse order on stack
  1791. ; (essentially, creating the tcp header!)
  1792.  
  1793.         pushw   0       ;        .UrgentPointer          dw ?
  1794.         pushw   0       ;        .Checksum               dw ?
  1795.         pushw   0x00a0  ;        .Window                 dw ?    ;;;;;;;
  1796.         shl     edi, 2  ;        .DataOffset             db ?  only 4 left-most bits
  1797.         shl     dx, 8
  1798.         or      dx, di  ;        .Flags                  db ?
  1799.         pushw   dx
  1800.         shr     edi, 2  ;        .DataOffset             db ? ;;;;
  1801.  
  1802.         push    [eax + TCP_SOCKET.RCV_NXT]      ;        .AckNumber              dd ?
  1803.         ntohld  [esp]
  1804.  
  1805.         push    [eax + TCP_SOCKET.SND_NXT]      ;        .SequenceNumber         dd ?
  1806.         ntohld  [esp]
  1807.  
  1808.         push    [eax + TCP_SOCKET.RemotePort]   ;        .DestinationPort        dw ?
  1809.         ntohlw  [esp]
  1810.  
  1811.         push    [eax + TCP_SOCKET.LocalPort]    ;        .SourcePort             dw ?
  1812.         ntohlw  [esp]
  1813.  
  1814.         push    edi             ; header size
  1815.  
  1816. ; Create the IP packet
  1817.         mov     ebx, [eax + IP_SOCKET.LocalIP]  ; source ip
  1818.         mov     eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
  1819.         mov     di, IP_PROTO_TCP shl 8 + 128
  1820.         call    IPv4_output
  1821.         jz      .fail
  1822.  
  1823. ;-----------------------------------------
  1824. ; Move TCP header from stack to TCP packet
  1825.  
  1826.         push    ecx
  1827.         mov     ecx, [esp+4]
  1828.         lea     esi, [esp+4+4]
  1829.         shr     ecx, 2
  1830.         rep     movsd
  1831.         pop     ecx             ; full TCP packet size
  1832.  
  1833.         pop     esi             ; headersize
  1834.         add     esp, esi
  1835.  
  1836.         mov     [esp + 4], eax          ; packet ptr
  1837.         mov     [esp + 4+4], edx        ; packet size
  1838.  
  1839.         mov     edx, edi                ; begin of data
  1840.         sub     edx, esi                ; begin of packet (edi = begin of data)
  1841.         push    ecx
  1842.         sub     ecx, esi                ; data size
  1843.  
  1844. ;--------------
  1845. ; Copy the data
  1846.  
  1847. ; eax = ptr to ring struct
  1848. ; ecx = buffer size
  1849. ; edi = ptr to buffer
  1850.  
  1851. ;        test    ecx, ecx
  1852.         mov     eax, [esp+4]              ; socket ptr
  1853.         add     [eax + TCP_SOCKET.SND_NXT], ecx
  1854.         add     eax, STREAM_SOCKET.snd
  1855.         push    edx
  1856.         call    SOCKET_ring_read
  1857.         pop     esi
  1858.         pop     ecx
  1859.         pop     eax
  1860.  
  1861.         test    [esi + TCP_segment.Flags], TH_SYN + TH_FIN
  1862.         jz      @f
  1863.         inc     [eax + TCP_SOCKET.SND_NXT]
  1864.         ;;; TODO: update sentfin flag
  1865.        @@:
  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+8
  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.