Subversion Repositories Kolibri OS

Rev

Rev 7098 | Rev 7974 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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