Subversion Repositories Kolibri OS

Rev

Rev 2953 | Blame | Last modification | View Log | Download | RSS feed

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