Subversion Repositories Kolibri OS

Rev

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