Subversion Repositories Kolibri OS

Rev

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

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