Subversion Repositories Kolibri OS

Rev

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

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