Subversion Repositories Kolibri OS

Rev

Rev 7974 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  Part of the TCP/IP network stack for KolibriOS                 ;;
  7. ;;                                                                 ;;
  8. ;;   Written by hidnplayr@kolibrios.org                            ;;
  9. ;;                                                                 ;;
  10. ;;    Based on the code of 4.4BSD                                  ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. $Revision: 8026 $
  18.  
  19. align 4
  20. iglobal
  21.         TCP_backoff     db 0,1,2,3,4,5,6,6,6,6,6,6,6
  22. endg
  23.  
  24. macro   tcp_checksum IP1, IP2 {
  25.  
  26. ;-------------
  27. ; Pseudoheader
  28.  
  29.         ; protocol type
  30.         mov     edx, IP_PROTO_TCP
  31.  
  32.         ; source address
  33.         add     dl, byte [IP1+1]
  34.         adc     dh, byte [IP1+0]
  35.         adc     dl, byte [IP1+3]
  36.         adc     dh, byte [IP1+2]
  37.  
  38.         ; destination address
  39.         adc     dl, byte [IP2+1]
  40.         adc     dh, byte [IP2+0]
  41.         adc     dl, byte [IP2+3]
  42.         adc     dh, byte [IP2+2]
  43.  
  44.         ; size
  45.         adc     dl, cl
  46.         adc     dh, ch
  47.  
  48.         adc     edx, 0
  49.  
  50. ;---------------------
  51. ; Real header and data
  52.  
  53.         push    esi
  54.         call    checksum_1
  55.         call    checksum_2
  56.         pop     esi
  57.  
  58. }       ; returns in dx only
  59.  
  60.  
  61.  
  62.  
  63. macro   tcp_sendseqinit ptr {
  64.  
  65.         push    edi                     ;;;; FIXME: i dont like this static use of edi
  66.         mov     edi, [ptr + TCP_SOCKET.ISS]
  67.         mov     [ptr + TCP_SOCKET.SND_UP], edi
  68.         mov     [ptr + TCP_SOCKET.SND_MAX], edi
  69.         mov     [ptr + TCP_SOCKET.SND_NXT], edi
  70.         mov     [ptr + TCP_SOCKET.SND_UNA], edi
  71.         pop     edi
  72.  
  73. }
  74.  
  75.  
  76.  
  77. macro   tcp_rcvseqinit ptr {
  78.  
  79.         push    edi
  80.         mov     edi, [ptr + TCP_SOCKET.IRS]
  81.         inc     edi                             ; SYN ocupies a sequence number
  82.         mov     [ptr + TCP_SOCKET.RCV_NXT], edi
  83.         mov     [ptr + TCP_SOCKET.RCV_ADV], edi
  84.         pop     edi
  85.  
  86. }
  87.  
  88.  
  89.  
  90. macro   tcp_init_socket socket {
  91.  
  92. ; new tcp control block
  93.  
  94.         mov     [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
  95.         mov     [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
  96.  
  97.         mov     [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
  98.         mov     [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
  99.         mov     [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
  100. ;;; TODO: TCP_time_rangeset
  101.  
  102.         mov     [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
  103.         mov     [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
  104.  
  105.         mov     [socket + TCP_SOCKET.RCV_SCALE], 0
  106.         mov     [socket + TCP_SOCKET.SND_SCALE], 0
  107.  
  108. }
  109.  
  110.  
  111. ;-----------------------------------------------------------------;
  112. ;                                                                 ;
  113. ; tcp_pull_out_of_band                                            ;
  114. ;                                                                 ;
  115. ;  IN:  eax = ?                                                   ;
  116. ;       ebx = socket ptr                                          ;
  117. ;       edx = tcp packet ptr                                      ;
  118. ;                                                                 ;
  119. ; OUT:  /                                                         ;
  120. ;                                                                 ;
  121. ;-----------------------------------------------------------------;
  122. align 4
  123. tcp_pull_out_of_band:
  124.  
  125.         DEBUGF  DEBUG_NETWORK_VERBOSE, "tcp_pull_out_of_band\n"
  126.  
  127.         ;;;; 1282-1305
  128.  
  129.         ret
  130.  
  131.  
  132.  
  133. ;-----------------------------------------------------------------;
  134. ;                                                                 ;
  135. ; tcp_drop                                                        ;
  136. ;                                                                 ;
  137. ;  IN:  eax = socket ptr                                          ;
  138. ;       ebx = error number                                        ;
  139. ;                                                                 ;
  140. ;  OUT: eax = socket ptr                                          ;
  141. ;                                                                 ;
  142. ;-----------------------------------------------------------------;
  143. align 4
  144. tcp_drop:
  145.  
  146. ;;; TODO: check if error code is "Connection timed out' and handle accordingly
  147.  
  148.         DEBUGF  DEBUG_NETWORK_VERBOSE, "tcp_drop: %x\n", eax
  149.  
  150.         cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
  151.         jb      .no_syn_received
  152.  
  153.         mov     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
  154.  
  155.         push    eax
  156.         call    tcp_output
  157.         pop     eax
  158.  
  159.         inc     [TCPS_drops]
  160.  
  161.         mov     [eax + SOCKET.errorcode], ebx
  162.         jmp     tcp_close
  163.  
  164.   .no_syn_received:
  165.         inc     [TCPS_conndrops]
  166.  
  167.         mov     [eax + SOCKET.errorcode], ebx
  168.         jmp     tcp_close
  169.  
  170.  
  171. ;-----------------------------------------------------------------;
  172. ;                                                                 ;
  173. ; tcp_disconnect                                                  ;
  174. ;                                                                 ;
  175. ;  IN:  eax = socket ptr                                          ;
  176. ;                                                                 ;
  177. ;  OUT: eax = socket ptr / 0                                      ;
  178. ;                                                                 ;
  179. ;-----------------------------------------------------------------;
  180. align 4
  181. tcp_disconnect:
  182.  
  183.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
  184.  
  185.         cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
  186.         jb      tcp_close       ; Connection not yet synchronised, just get rid of the socket
  187.  
  188.         test    [eax + SOCKET.options], SO_LINGER
  189.         jz      .nolinger
  190.  
  191. ; TODO: implement LINGER
  192. ;        cmp     [eax + SOCKET.so_linger], 0
  193. ;        je     TCP_drop
  194.  
  195.   .nolinger:
  196.         call    socket_is_disconnecting
  197.  
  198.         push    eax
  199.         add     eax, STREAM_SOCKET.rcv
  200.         mov     ecx, [eax + RING_BUFFER.size]
  201.         call    socket_ring_free
  202.         pop     eax
  203.  
  204.         call    tcp_usrclosed
  205.  
  206.         test    eax, eax
  207.         jz      @f
  208.         push    eax
  209.         call    tcp_output
  210.         pop     eax
  211.   @@:
  212.         ret
  213.  
  214.  
  215. ;-----------------------------------------------------------------;
  216. ;                                                                 ;
  217. ; tcp_close                                                       ;
  218. ;                                                                 ;
  219. ;  IN:  eax = socket ptr                                          ;
  220. ;                                                                 ;
  221. ;  OUT: /                                                         ;
  222. ;                                                                 ;
  223. ;-----------------------------------------------------------------;
  224. align 4
  225. tcp_close:
  226.  
  227.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
  228.  
  229. ;;; TODO: update RTT and mean deviation
  230. ;;; TODO: update slow start threshold
  231.  
  232.         call    socket_is_disconnected
  233.         call    socket_free
  234.  
  235.         inc     [TCPS_closed]
  236.  
  237.         xor     eax, eax
  238.         ret
  239.  
  240.  
  241.  
  242. ;-----------------------------------------------------------------;
  243. ;                                                                 ;
  244. ; tcp_outflags                                                    ;
  245. ;                                                                 ;
  246. ;  IN:  eax = socket ptr                                          ;
  247. ;                                                                 ;
  248. ;  OUT: edx = flags                                               ;
  249. ;                                                                 ;
  250. ;-----------------------------------------------------------------;
  251. align 4
  252. tcp_outflags:
  253.  
  254.         mov     edx, [eax + TCP_SOCKET.t_state]
  255.         movzx   edx, byte[edx + .flaglist]
  256.  
  257.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
  258.  
  259.         ret
  260.  
  261.   .flaglist:
  262.         db      TH_RST + TH_ACK         ; TCPS_CLOSED
  263.         db      0                       ; TCPS_LISTEN
  264.         db      TH_SYN                  ; TCPS_SYN_SENT
  265.         db      TH_SYN + TH_ACK         ; TCPS_SYN_RECEIVED
  266.         db               TH_ACK         ; TCPS_ESTABLISHED
  267.         db               TH_ACK         ; TCPS_CLOSE_WAIT
  268.         db      TH_FIN + TH_ACK         ; TCPS_FIN_WAIT_1
  269.         db      TH_FIN + TH_ACK         ; TCPS_CLOSING
  270.         db      TH_FIN + TH_ACK         ; TCPS_LAST_ACK
  271.         db               TH_ACK         ; TCPS_FIN_WAIT_2
  272.         db               TH_ACK         ; TCPS_TIME_WAIT
  273.  
  274.  
  275. ;-----------------------------------------------------------------;
  276. ;                                                                 ;
  277. ; TCP_respond: Fast way to send an ACK/RST/keepalive segment.     ;
  278. ;                                                                 ;
  279. ;  IN:  ebx = socket ptr                                          ;
  280. ;        cl = flags                                               ;
  281. ;                                                                 ;
  282. ; OUT:  /                                                         ;
  283. ;                                                                 ;
  284. ;-----------------------------------------------------------------;
  285. align 4
  286. tcp_respond:
  287.  
  288.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
  289.  
  290. ;---------------------
  291. ; Create the IP packet
  292.  
  293.         push    cx ebx
  294.         mov     edx, [ebx + IP_SOCKET.LocalIP]
  295.         mov     edi, [ebx + IP_SOCKET.RemoteIP]
  296.         mov     al, [ebx + IP_SOCKET.ttl]
  297.         mov     ah, IP_PROTO_TCP
  298.         mov     ecx, sizeof.TCP_header
  299.         mov     ebx, [ebx + IP_SOCKET.device]
  300.         call    ipv4_output
  301.         jz      .error
  302.         pop     esi cx
  303.         push    eax
  304.  
  305. ;-----------------------------------------------
  306. ; Fill in the TCP header by using the socket ptr
  307.  
  308.         mov     ax, [esi + TCP_SOCKET.LocalPort]
  309.         stosw
  310.         mov     ax, [esi + TCP_SOCKET.RemotePort]
  311.         stosw
  312.         mov     eax, [esi + TCP_SOCKET.SND_NXT]
  313.         bswap   eax
  314.         stosd
  315.         mov     eax, [esi + TCP_SOCKET.RCV_NXT]
  316.         bswap   eax
  317.         stosd
  318.         mov     al, 0x50        ; Dataoffset: 20 bytes (TCP_header.DataOffset)
  319.         stosb
  320.         mov     al, cl
  321.         stosb
  322.         mov     eax, SOCKET_BUFFER_SIZE
  323.         sub     eax, [esi + STREAM_SOCKET.rcv.size]
  324.         cmp     eax, TCP_max_win
  325.         jbe     .lessthanmax
  326.         mov     eax, TCP_max_win
  327.   .lessthanmax:
  328.         mov     cl, [esi + TCP_SOCKET.RCV_SCALE]
  329.         shr     eax, cl
  330.  
  331.         xchg    al, ah
  332.         stosw                   ; window
  333.         xor     eax, eax
  334.         stosd                   ; checksum + urgentpointer
  335.  
  336. ;---------------------
  337. ; Fill in the checksum
  338.  
  339.   .checksum:
  340.         sub     edi, sizeof.TCP_header
  341.         mov     ecx, sizeof.TCP_header
  342.         xchg    esi, edi
  343.         tcp_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
  344.         mov     [esi+TCP_header.Checksum], dx
  345.  
  346. ;--------------------
  347. ; And send the segment
  348.  
  349.         call    [ebx + NET_DEVICE.transmit]
  350.         test    eax, eax
  351.         jnz     @f
  352.         call    net_ptr_to_num4
  353.         inc     [TCP_segments_tx + edi]
  354.        @@:
  355.         ret
  356.  
  357.   .error:
  358.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
  359.         add     esp, 2 + 4
  360.  
  361.         ret
  362.  
  363.  
  364. ;-----------------------------------------------------------------;
  365. ;                                                                 ;
  366. ; tcp_respond_segment                                             ;
  367. ;                                                                 ;
  368. ;  IN:  ebx = device ptr                                          ;
  369. ;       edx = segment ptr (a previously received segment)         ;
  370. ;       edi = ptr to IPv4 header                                  ;
  371. ;        cl = flags                                               ;
  372. ;                                                                 ;
  373. ;  OUT: /                                                         ;
  374. ;                                                                 ;
  375. ;-----------------------------------------------------------------;
  376. align 4
  377. tcp_respond_segment:
  378.  
  379.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: frame=%x flags=%x\n", edx, cl
  380.  
  381. ;---------------------
  382. ; Create the IP packet
  383.  
  384.         push    cx edx
  385.         mov     edx, [edi + IPv4_header.DestinationAddress]
  386.         mov     edi, [edi + IPv4_header.SourceAddress]
  387.         mov     ecx, sizeof.TCP_header
  388.         mov     ax, IP_PROTO_TCP shl 8 + 128
  389.         call    ipv4_output
  390.         jz      .error
  391.         pop     esi cx
  392.  
  393.         push    eax
  394.  
  395. ;---------------------------------------------------
  396. ; Fill in the TCP header by using a received segment
  397.  
  398.         mov     ax, [esi + TCP_header.DestinationPort]
  399.         stosw
  400.         mov     ax, [esi + TCP_header.SourcePort]
  401.         stosw
  402.         mov     eax, [esi + TCP_header.AckNumber]
  403.         bswap   eax
  404.         stosd
  405.         xor     eax, eax
  406.         stosd
  407.         mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
  408.         stosb
  409.         mov     al, cl
  410.         stosb
  411.         mov     ax, 1280
  412.         rol     ax, 8
  413.         stosw                   ; window
  414.         xor     eax, eax
  415.         stosd                   ; checksum + urgentpointer
  416.  
  417. ;---------------------
  418. ; Fill in the checksum
  419.  
  420.         lea     esi, [edi - sizeof.TCP_header]
  421.         mov     ecx, sizeof.TCP_header
  422.         tcp_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\      ; FIXME
  423.                      (esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
  424.         mov     [esi + TCP_header.Checksum], dx
  425.  
  426. ;--------------------
  427. ; And send the segment
  428.  
  429.         call    [ebx + NET_DEVICE.transmit]
  430.         test    eax, eax
  431.         jnz     @f
  432.         call    net_ptr_to_num4
  433.         inc     [TCP_segments_tx + edi]
  434.        @@:
  435.         ret
  436.  
  437.   .error:
  438.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
  439.         add     esp, 2+4
  440.  
  441.         ret
  442.  
  443.  
  444. macro   tcpt_rangeset   timer, value, min, max {
  445.  
  446. local   .min
  447. local   .max
  448. local   .done
  449.  
  450.         cmp     value, min
  451.         jb      .min
  452.         cmp     value, max
  453.         ja      .max
  454.         mov     timer, value
  455.         jmp     .done
  456.   .min:
  457.         mov     timer, min
  458.         jmp     .done
  459.   .max:
  460.         mov     timer, max
  461.   .done:
  462. }
  463.  
  464. ;-----------------------------------------------------------------;
  465. ;                                                                 ;
  466. ; tcp_set_persist                                                 ;
  467. ;                                                                 ;
  468. ;-----------------------------------------------------------------;
  469. align 4
  470. tcp_set_persist:
  471.  
  472.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
  473.  
  474. ; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
  475.  
  476.         test    [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
  477.         jnz     .exit
  478.  
  479. ; calculate RTO
  480.         push    ebx
  481.         mov     ebx, [eax + TCP_SOCKET.t_srtt]
  482.         shr     ebx, 2
  483.         add     ebx, [eax + TCP_SOCKET.t_rttvar]
  484.         shr     ebx, 1
  485.  
  486.         mov     cl, [eax + TCP_SOCKET.t_rxtshift]
  487.         shl     ebx, cl
  488.  
  489. ; Start/restart persistance timer.
  490.  
  491.         tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
  492.         or      [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
  493.         pop     ebx
  494.  
  495.         cmp     [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
  496.         jae     @f
  497.         inc     [eax + TCP_SOCKET.t_rxtshift]
  498.       @@:
  499.   .exit:
  500.  
  501.         ret
  502.  
  503.  
  504.  
  505. ;-----------------------------------------------------------------;
  506. ;                                                                 ;
  507. ; tcp_xmit_timer: Calculate new smoothed RTT.                     ;
  508. ;                                                                 ;
  509. ;   IN: eax = rtt                                                 ;
  510. ;       ebx = socket ptr                                          ;
  511. ;                                                                 ;
  512. ;  OUT: /                                                         ;
  513. ;                                                                 ;
  514. ;-----------------------------------------------------------------;
  515. align 4
  516. tcp_xmit_timer:
  517.  
  518.         DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=0x%x rtt=%d0ms\n", ebx, eax
  519.  
  520.         inc     [TCPS_rttupdated]
  521.  
  522.         cmp     [ebx + TCP_SOCKET.t_rtt], 0
  523.         je      .no_rtt_yet
  524.  
  525. ; srtt is stored as a fixed point with 3 bits after the binary point.
  526. ; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
  527. ; (srtt = rtt/8 + srtt*7/8 in fixed point)
  528. ; Adjust rtt to origin 0.
  529.  
  530.         push    ecx
  531.         mov     ecx, [ebx + TCP_SOCKET.t_srtt]
  532.         shr     ecx, TCP_RTT_SHIFT
  533.         sub     eax, ecx
  534.         dec     eax
  535.         pop     ecx
  536.  
  537.         add     [ebx + TCP_SOCKET.t_srtt], eax
  538.         ja      @f
  539.         mov     [ebx + TCP_SOCKET.t_srtt], 1
  540.   @@:
  541.  
  542. ; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
  543. ; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
  544. ; rttvar is stored as fixed point with 2 bits after the binary point.
  545. ; The following is equivalent to rfc793 smoothing with an alpha of .75
  546. ; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
  547.  
  548. ; get abs(eax)
  549.         push    edx
  550.         cdq
  551.         xor     eax, edx
  552.         sub     eax, edx
  553.  
  554.         mov     edx, [ebx + TCP_SOCKET.t_rttvar]
  555.         shr     edx, TCP_RTTVAR_SHIFT
  556.         sub     eax, edx
  557.         pop     edx
  558.  
  559.         add     [ebx + TCP_SOCKET.t_rttvar], eax
  560.         ja      @f
  561.         mov     [ebx + TCP_SOCKET.t_rttvar], 1
  562.   @@:
  563.         ret
  564.  
  565.  
  566.   .no_rtt_yet:
  567.         push    ecx
  568.         mov     ecx, eax
  569.         shl     ecx, TCP_RTT_SHIFT
  570.         mov     [ebx + TCP_SOCKET.t_srtt], ecx
  571.  
  572.         shl     eax, TCP_RTTVAR_SHIFT - 1
  573.         mov     [ebx + TCP_SOCKET.t_rttvar], eax
  574.         pop     ecx
  575.  
  576.         ret
  577.  
  578.  
  579. ;-----------------------------------------------------------------;
  580. ;                                                                 ;
  581. ; tcp_mss: Update maximum segment size                            ;
  582. ;                                                                 ;
  583. ;  IN:  eax = max segment size                                    ;
  584. ;       ebx = socket ptr                                          ;
  585. ;                                                                 ;
  586. ;  OUT: /                                                         ;
  587. ;                                                                 ;
  588. ;-----------------------------------------------------------------;
  589. align 4
  590. tcp_mss:
  591.  
  592.         cmp     eax, 1420       ; FIXME
  593.         jbe     @f
  594.         mov     eax, 1420
  595.   @@:
  596.         mov     [ebx + TCP_SOCKET.t_maxseg], eax
  597.  
  598.  
  599.         ret
  600.  
  601.  
  602.  
  603. ;-----------------------------------------------------------------;
  604. ;                                                                 ;
  605. ; tcp_reassemble                                                  ;
  606. ;                                                                 ;
  607. ;   IN: ebx = socket ptr                                          ;
  608. ;       edx = segment ptr                                         ;
  609. ;                                                                 ;
  610. ;  OUT: /                                                         ;
  611. ;                                                                 ;
  612. ;-----------------------------------------------------------------;
  613. align 4
  614. tcp_reassemble:
  615.  
  616.         ;;;;; TODO
  617.  
  618.         ret
  619.  
  620.