Subversion Repositories Kolibri OS

Rev

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