Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6476 → Rev 6475

/kernel/trunk/network/tcp_output.inc
16,8 → 16,6
 
$Revision$
 
TCP_BIT_SENDALOT = 1 shl 0
 
;-----------------------------------------------------------------;
; ;
; tcp_output ;
66,23 → 64,17
.again:
mov [temp_bits], 0
 
; Calculate offset
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
sub ebx, [eax + TCP_SOCKET.SND_UNA]
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
cmp ecx, [eax + TCP_SOCKET.SND_CWND] ;
jb @f ;
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
@@: ;
 
; Determine window
call tcp_outflags ; flags in dl
 
mov ecx, [eax + TCP_SOCKET.SND_WND]
cmp ecx, [eax + TCP_SOCKET.SND_CWND]
jb @f
mov ecx, [eax + TCP_SOCKET.SND_CWND]
@@:
 
; get flags in dl
 
call tcp_outflags
 
;------------------------
; data being forced out ?
 
113,7 → 105,7
.no_force:
 
;--------------------------------
; Calculate how much data to send
; Calculate how much data to send (106)
 
mov esi, [eax + STREAM_SOCKET.snd.size]
cmp esi, ecx
123,28 → 115,24
sub esi, ebx
 
;------------------------
; check for window shrink
; check for window shrink (107)
 
; If FIN has been sent, but not ACKed, but we havent been called to retransmit, esi will be -1
; If FIN has been set, but not ACKed, but we havent been called to retransmit, esi will be -1
; Otherwise, window shrank after we sent into it.
 
jae .not_persist
 
; enter persist state
 
xor esi, esi
 
; If window shrank to 0
 
test ecx, ecx
jnz @f
 
; cancel pending retransmit
 
and [eax + TCP_SOCKET.timer_flags], not timer_flag_retransmission
 
; pull SND_NXT back to (closed) window, We will enter persist state below.
 
push [eax + TCP_SOCKET.SND_UNA]
pop [eax + TCP_SOCKET.SND_NXT]
@@:
154,7 → 142,7
.not_persist:
 
;---------------------------
; Send one segment at a time
; Send one segment at a time (124)
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
jbe @f
163,7 → 151,7
@@:
 
;--------------------------------------------
; Turn of FIN flag if send buffer not emptied
; Turn of FIN flag if send buffer not emptied (128)
 
mov edi, [eax + TCP_SOCKET.SND_NXT]
add edi, esi
174,13 → 162,13
@@:
 
;-------------------------------
; calculate window advertisement
; calculate window advertisement (130)
 
mov ecx, SOCKET_BUFFER_SIZE
sub ecx, [eax + STREAM_SOCKET.rcv.size]
 
;------------------------------
; Sender silly window avoidance
; Sender silly window avoidance (131)
 
test esi, esi
jz .len_zero
215,7 → 203,7
.len_zero:
 
;----------------------------------------
; Check if a window update should be sent
; Check if a window update should be sent (154)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: window=%d\n", ecx
 
239,10 → 227,9
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: we can increase window by %d bytes\n", ebx
 
mov edi, [eax + TCP_SOCKET.t_maxseg]
shl edi, 1
 
cmp ebx, edi
jae .send
 
253,10 → 240,8
.no_window:
 
;--------------------------
; Should a segment be sent?
; Should a segment be sent? (174)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: Should a segment be sent?\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz .send
 
267,24 → 252,20
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
ja .send
 
; Do we need to send a FIN according to our state?
 
test dl, TH_FIN
jz .enter_persist ; no reason to send, enter persist state
 
; Do so if we didnt do it already
; FIN was set, only send if not already sent, or on retransmit
 
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
jz .send
 
; Or when we need to retransmit the FIN
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je .send
 
;--------------------
; Enter persist state
; Enter persist state (191)
 
.enter_persist:
 
303,7 → 284,7
@@:
 
;----------------------------
; No reason to send a segment
; No reason to send a segment (219)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: No reason to send a segment\n"
 
319,7 → 300,7
 
;-----------------------------------------------
;
; Send a segment
; Send a segment (222)
;
; eax = socket pointer
; esi = data len
410,7 → 391,7
; esi = data len
 
;---------------------------------------------
; check if we dont exceed the max segment size
; check if we dont exceed the max segment size (270)
 
add esi, edi ; total TCP segment size
cmp esi, [eax + TCP_SOCKET.t_maxseg]
421,7 → 402,6
.no_overflow:
 
; Update stats
 
test esi, esi
jz .zero_data
 
502,23 → 482,23
; Start by pushing all TCP header values in reverse order on stack
; (essentially, creating the tcp header on the stack!)
 
pushw 0 ; UrgentPointer
pushw 0 ; Checksum
pushw bx ; Window
shl edi, 2 ; DataOffset
pushw 0 ; .UrgentPointer dw ?
pushw 0 ; .Checksum dw ?
pushw bx ; .Window dw ?
shl edi, 2 ; .DataOffset db ? only 4 left-most bits
shl dx, 8
or dx, di ; Flags
or dx, di ; .Flags db ?
pushw dx
shr edi, 2 ; DataOffset
shr edi, 2 ; .DataOffset db ?
 
push [eax + TCP_SOCKET.RCV_NXT] ; AckNumber
push [eax + TCP_SOCKET.RCV_NXT] ; .AckNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.SND_NXT] ; SequenceNumber
push [eax + TCP_SOCKET.SND_NXT] ; .SequenceNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.RemotePort] ; DestinationPort
push [eax + TCP_SOCKET.LocalPort] ; SourcePort
push [eax + TCP_SOCKET.RemotePort] ; .DestinationPort dw ?
push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ?
 
push edi ; header size
 
578,8 → 558,8
pop ecx ; full packet size
mov eax, [esp + 8] ; socket ptr
 
;----------------------------
; initialize retransmit timer
;----------------------------------
; initialize retransmit timer (400)
 
;TODO: check t_force and persist
 
604,7 → 584,6
@@:
 
; set retransmission timer if not already set, and not doing an ACK or keepalive probe
 
test [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
jnz .retransmit_set
 
619,6 → 598,7
jz .retransmit_set
and [eax + TCP_SOCKET.timer_flags], not timer_flag_persist
mov [eax + TCP_SOCKET.t_rxtshift], 0
 
.retransmit_set:
 
;--------------------
662,12 → 642,10
@@:
 
; update last ack sent
 
push [eax + TCP_SOCKET.RCV_NXT]
pop [eax + TCP_SOCKET.last_ack_sent]
 
; clear the ACK flags
 
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
 
;--------------
/kernel/trunk/network/socket.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
73,8 → 73,8
SND_UNA dd ? ; sequence number of unack'ed sent Packets
SND_NXT dd ? ; next send sequence number to use
SND_UP dd ? ; urgent pointer
SND_WL1 dd ? ; the sequence number of the last segment used to update the send window
SND_WL2 dd ? ; the acknowledgment number of the last segment used to update the send window
SND_WL1 dd ? ; window minus one
SND_WL2 dd ? ;
ISS dd ? ; initial send sequence number
SND_WND dd ? ; send window
 
/kernel/trunk/network/stack.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; STACK.INC ;;
91,7 → 91,6
SO_REUSEPORT = 1 shl 7
SO_USELOOPBACK = 1 shl 8
SO_BINDTODEVICE = 1 shl 9
SO_LINGER = 1 shl 10
 
SO_NONBLOCK = 1 shl 31
 
132,12 → 131,11
EMSGSIZE = 12
ENOMEM = 18
EADDRINUSE = 20
EADDRNOTAVAIL = 21
ECONNREFUSED = 61
ECONNRESET = 52
ECONNABORTED = 53
EISCONN = 56
ETIMEDOUT = 60
ECONNREFUSED = 61
ECONNABORTED = 53
 
; Api protocol numbers
API_ETH = 0
/kernel/trunk/network/tcp_input.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
16,11 → 16,6
 
$Revision$
 
TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
TCP_BIT_FIN_IS_ACKED = 1 shl 3
 
;-----------------------------------------------------------------;
; ;
; TCP_input: Add a segment to the incoming TCP queue. ;
70,14 → 65,7
ret
 
 
;-----------------------------------------------------------------;
; ;
; TCP_process_input: Process segments from the incoming TCP queue.;
; ;
; IN: / ;
; OUT: / ;
; ;
;-----------------------------------------------------------------;
 
align 4
proc tcp_process_input
 
113,8 → 101,10
 
mov edx, esi
 
; Verify the checksum (if not already done by hw)
cmp ebx, LOOPBACK_DEVICE
je .checksum_ok
 
; re-calculate the checksum (if not already done by hw)
test [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
jnz .checksum_ok
 
129,7 → 119,6
.checksum_ok:
 
; Verify the data offset
 
movzx eax, [edx + TCP_header.DataOffset]
and al, 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
shr al, 2
150,11 → 139,8
ntohw [edx + TCP_header.Window]
ntohw [edx + TCP_header.UrgentPointer]
 
;-----------------------------------------------------------------------------------
;
;------------------------
; Find the socket pointer
;
;-----------------------------------------------------------------------------------
 
; IP Packet TCP Destination Port = local Port
; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0)
234,11 → 220,8
mov dword[edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore
pop ecx
 
;-----------------------------------------------------------------------------------
;
; Accept incoming connections
;
;-----------------------------------------------------------------------------------
;---------------------------------------
; Are we accepting incoming connections?
 
test [ebx + SOCKET.options], SO_ACCEPTCON
jz .no_accept
245,15 → 228,11
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
 
; Unlock current socket
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
; Fork it
 
push ecx edx esi edi
call socket_fork
pop edi esi edx ecx
261,8 → 240,6
test eax, eax
jz .drop_no_socket
 
; Success! Use the new socket from now on (it is already locked)
 
mov ebx, eax
 
mov [temp_bits], TCP_BIT_DROPSOCKET
284,11 → 261,8
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
 
;-----------------------------------------------------------------------------------
;
;--------------------
; Process TCP options
;
;-----------------------------------------------------------------------------------
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
421,7 → 395,7
jmp .opt_loop
 
.paws_drop:
inc [TCPS_rcvduppack]
inc [TCPS_rcvduppack] ; update stats
add [TCPS_rcvdupbyte], ecx
inc [TCPS_pawsdrop]
jmp .drop_after_ack
430,13 → 404,10
 
pop ecx
 
;-----------------------------------------------------------------------------------
;
; Header prediction
;
;-----------------------------------------------------------------------------------
;-----------------------------------------------------------------------
; Time to do some header prediction (Original Principle by Van Jacobson)
 
; According to Van Jacobson, there are two common cases for an uni-directional data transfer.
; There are two common cases for an uni-directional data transfer.
;
; General rule: the packets has no control flags, is in-sequence,
; window width didnt change and we're not retransmitting.
475,25 → 446,21
; If the following 4 conditions are all true, this segment is a pure ACK.
;
; - The segment contains no data.
 
test ecx, ecx
jnz .not_sender
 
; - The congestion window is greater than or equal to the current send window.
; This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
 
mov eax, [ebx + TCP_SOCKET.SND_CWND]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jb .not_uni_xfer
 
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .not_uni_xfer
 
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
 
sub eax, [ebx + TCP_SOCKET.SND_UNA]
jbe .not_uni_xfer
 
502,13 → 469,7
;---------------------------------
; Packet is a pure ACK, process it
 
inc [TCPS_predack]
 
inc [TCPS_rcvackpack]
add [TCPS_rcvackbyte], eax
 
; Delete acknowledged bytes from send buffer
 
pusha
mov ecx, eax
lea eax, [ebx + STREAM_SOCKET.snd]
536,16 → 497,13
.rtt_done:
 
; update window pointers
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
 
; Stop retransmit timer
 
and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
 
; Unlock the socket
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
552,12 → 510,10
popa
 
; Awaken waiting processes
 
mov eax, ebx
call socket_notify
 
; Generate more output
 
call tcp_output
 
jmp .drop_no_socket
566,16 → 522,14
; maybe we are the receiver in the uni-xfer then..
 
.not_sender:
; - The amount of data in the segment is greater than 0 (data count is in ecx)
 
; - The amount of data in the segment is greater than 0 (data count is in ecx)
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jne .not_uni_xfer
 
; - The reassembly list of out-of-order segments for the connection is empty.
 
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .not_uni_xfer
 
596,18 → 550,14
 
jmp .drop
 
;--------------------------------------------------
; Header prediction failed, do it the slow way
 
;-----------------------------------------------------------------------------------
;
; TCP segment processing, the slow way
;
;-----------------------------------------------------------------------------------
.not_uni_xfer:
 
.not_uni_xfer:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
push edx
mov eax, SOCKET_BUFFER_SIZE
sub eax, [ebx + STREAM_SOCKET.rcv.size]
626,22 → 576,17
; If we are in listen or syn_sent state, go to that specific code right away
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
je .state_listen
je .LISTEN
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
je .state_syn_sent
je .SYN_SENT
 
;-----------------------------------------------------------------------------------
;
; Trim any data not in window
;
;-----------------------------------------------------------------------------------
;----------------------------
; trim any data not in window
 
;-------------------------------------------------
; Check for duplicate data at beginning of segment
; 1. Check for duplicate data at beginning of segment
 
; Calculate number of bytes we need to drop
 
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
648,8 → 593,6
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
 
; Check for duplicate SYN
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_dup_syn
 
668,42 → 611,34
dec eax
.no_dup_syn:
 
;-----------------------------------
; Check for entire duplicate segment
 
; 2. Check for entire duplicate segment
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
jb .no_complete_dup
jb .duplicate
jnz @f
test [edx + TCP_header.Flags], TH_FIN
jnz .no_complete_dup
jnz .duplicate
@@:
 
; Any valid FIN must be to the left of the window.
; At this point the FIN must be out of sequence or a duplicate, drop it
 
and [edx + TCP_header.Flags], not TH_FIN
 
; send an ACK to resynchronize and drop any data.
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
 
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
 
inc [TCPS_rcvduppack]
add [TCPS_rcvdupbyte], eax
jmp .dup_processed
.no_complete_dup:
inc [TCPS_rcvpartduppack]
add [TCPS_rcvpartdupbyte], eax
.dup_processed:
 
;;; TODO: update stats
 
;-----------------------------------------------
; Remove duplicate data and update urgent offset
 
.duplicate:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
 
; Trim data from left side of window
 
add [dataoffset], eax
add [edx + TCP_header.SequenceNumber], eax
sub ecx, eax
713,11 → 648,11
and [edx + TCP_header.Flags], not (TH_URG)
mov [edx + TCP_header.UrgentPointer], 0
@@:
.no_duplicate:
 
;--------------------------------------------------
; Handle data that arrives after process terminates
 
.no_duplicate:
cmp [ebx + SOCKET.PID], 0 ;;; TODO: use socket flags instead??
jne .not_terminated
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
729,11 → 664,11
call tcp_close
inc [TCPS_rcvafterclose]
jmp .respond_seg_reset
.not_terminated:
 
;----------------------------------------
; Remove data beyond right edge of window
 
.not_terminated:
mov eax, [edx + TCP_header.SequenceNumber]
add eax, ecx
sub eax, [ebx + TCP_SOCKET.RCV_NXT]
742,20 → 677,15
 
DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
 
inc [TCPS_rcvpackafterwin]
 
;;; TODO: update stats
cmp eax, ecx
jl .dont_drop_all
 
add [TCPS_rcvbyteafterwin], ecx
 
;----------------------------------------------------------------------------------------------------
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
; if the sequence numbers are above the previous ones
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_new_request
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jne .no_new_request
; mov edx, [ebx + TCP_SOCKET.RCV_NXT]
; cmp edx, [edx + TCP_header.SequenceNumber]
775,31 → 705,24
jne .drop_after_ack
 
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
inc [TCPS_rcvwinprobe]
;;; TODO: update stats
.dont_drop_all:
add [TCPS_rcvbyteafterwin], eax
;;; TODO: update stats
DEBUGF DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
 
; remove data from the right side of window (decrease data length)
 
sub ecx, eax
sub ecx, eax ; remove data from the right side of window (decrease data length)
and [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
.no_excess_data:
 
;-----------------------------------------------------------------------------------
;
;-----------------
; Record timestamp
;
;-----------------------------------------------------------------------------------
 
; If last ACK falls within this segments sequence numbers, record its timestamp
 
test [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp
mov eax, [ebx + TCP_SOCKET.last_ack_sent]
sub eax, [edx + TCP_header.SequenceNumber]
jb .no_timestamp
test [edx + TCP_header.Flags], TH_SYN or TH_FIN ; SYN and FIN occupy one byte
test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte
jz @f
dec eax
@@:
814,11 → 737,8
mov [ebx + TCP_SOCKET.ts_recent], eax
.no_timestamp:
 
;-----------------------------------------------------------------------------------
;
; Process RST flag
;
;-----------------------------------------------------------------------------------
;------------------
; Process RST flags
 
test [edx + TCP_header.Flags], TH_RST
jz .no_rst
829,7 → 749,6
shl eax, 2
jmp dword [eax + .rst_sw_list]
 
;-----------------------------------------------------------------------------------
.rst_sw_list:
dd .no_rst ; TCPS_CLOSED
dd .no_rst ; TCPS_LISTEN
841,29 → 760,28
dd .rst_close ; TCPS_CLOSING
dd .rst_close ; TCPS_LAST_ACK
dd .econnreset ; TCPS_FIN_WAIT_2
dd .rst_close ; TCPS_TIME_WAIT
dd .rst_close ; TCPS_TIMED_WAIT
 
;-----------------------------------------------------------------------------------
.econnrefused:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
 
mov [ebx + SOCKET.errorcode], ECONNREFUSED
jmp .close
 
;-----------------------------------------------------------------------------------
.econnreset:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
 
mov [ebx + SOCKET.errorcode], ECONNRESET
 
.close:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
inc [TCPS_drops]
 
 
;;; TODO: update stats (tcp drops)
mov eax, ebx
call tcp_close
jmp .drop_no_socket
 
;-----------------------------------------------------------------------------------
.rst_close:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
 
871,17 → 789,11
call tcp_close
jmp .drop_no_socket
 
;-----------------------------------------------------------------------------------
.no_rst:
 
;-----------------------------------------------------------------------------------
;
; Handle SYN-full and ACK-less segments
;
;-----------------------------------------------------------------------------------
;--------------------------------------
; handle SYN-full and ACK-less segments
 
; If a SYN is in the window, then this is an error so we send an RST and drop the connection
 
test [edx + TCP_header.Flags], TH_SYN
jz .not_syn_full
 
891,17 → 803,12
jmp .drop_with_reset
.not_syn_full:
 
; If ACK bit is off, we drop the segment and return
;---------------
; ACK processing
 
test [edx + TCP_header.Flags], TH_ACK
jz .drop
 
;----------------------------------------------------------------------------------
;
; ACK processing for SYN_RECEIVED state
;
;----------------------------------------------------------------------------------
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .ack_processed ; states: closed, listen, syn_sent
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
914,7 → 821,7
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .drop_with_reset
 
inc [TCPS_connects]
;;; TODO: update stats
 
mov eax, ebx
call socket_is_connected
936,20 → 843,15
mov eax, [edx + TCP_header.SequenceNumber]
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
.no_syn_rcv:
 
;-----------------------------------------------------------------------------------
;
; ACK processing for SYN_RECEIVED state and higher
;
;-----------------------------------------------------------------------------------
 
;-------------------------
; Check for duplicate ACKs
; check for duplicate ACKs
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
ja .dup_ack_complete
ja .not_dup_ack
 
test ecx, ecx
jnz .reset_dupacks
958,7 → 860,6
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .reset_dupacks
 
inc [TCPS_rcvdupack]
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
 
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
966,22 → 867,21
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
 
test [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
jz .reset_dupacks
jz @f
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jne .reset_dupacks
je .dup_ack
 
; Increment dupplicat ACK counter
; If it reaches the threshold, re-transmit the missing segment
@@:
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .not_dup_ack
 
.dup_ack:
inc [ebx + TCP_SOCKET.t_dupacks]
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jb .dup_ack_complete
ja .another_lost
jne .no_re_xmit
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Re-transmitting lost segment\n"
 
push [ebx + TCP_SOCKET.SND_NXT] ; >>>>
 
mov eax, [ebx + TCP_SOCKET.SND_WND]
1010,18 → 910,15
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment
 
mov eax, [esp]
call tcp_output
 
; Lock the socket again
 
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
1028,7 → 925,6
pop ebx
 
; Continue processing
 
xor edx, edx
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mul [ebx + TCP_SOCKET.t_dupacks]
1040,9 → 936,13
jb @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
jmp .drop
 
.another_lost:
 
.no_re_xmit:
jbe .not_dup_ack
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
1049,32 → 949,24
add [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment, again
 
; retransmit missing segment
mov eax, [esp]
call tcp_output
 
; Lock the socket again
 
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
pop ebx
 
; And drop the incoming segment
 
jmp .drop
 
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .ack_processed
 
.dup_ack_complete:
.not_dup_ack:
 
;-------------------------------------------------
; If the congestion window was inflated to account
1103,11 → 995,8
add [TCPS_rcvackbyte], edi
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
 
;-----------------------------------------------------------------------------------
;
;------------------------------------------
; RTT measurements and retransmission timer
;
;-----------------------------------------------------------------------------------
 
; If we have a timestamp, update smoothed RTT
 
1132,6 → 1021,7
test eax, eax
jz .rtt_done_
call tcp_xmit_timer
 
.rtt_done_:
 
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1152,28 → 1042,25
or [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
.no_restart:
 
;-----------------------------------------------------------------------------------
;
 
;-------------------------------------------
; Open congestion window in response to ACKs
;
;-----------------------------------------------------------------------------------
 
; If the window gives us less then sstresh packets in flight, open exponentially.
; Otherwise, open lineary
 
mov esi, [ebx + TCP_SOCKET.SND_CWND]
mov eax, [ebx + TCP_SOCKET.t_maxseg]
 
cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
jbe @f
push edx
push eax
mul eax ; t_maxseg*t_maxseg
div esi ; t_maxseg*t_maxseg/snd_cwnd
pop edx ; t_maxseg
shr edx, 3 ; t_maxseg/8
add eax, edx ; t_maxseg*t_maxseg/snd_cwnd + t_maxseg/8
mul eax
div esi
pop edx
shr edx, 3
add eax, edx
pop edx
@@:
 
add esi, eax
 
push ecx
1188,34 → 1075,24
@@:
mov [ebx + TCP_SOCKET.SND_CWND], esi
 
;-----------------------------------------------------------------------------------
;
;------------------------------------------
; Remove acknowledged data from send buffer
;
;-----------------------------------------------------------------------------------
 
; If the number of bytes acknowledged exceeds the number of bytes on the send buffer,
; snd_wnd is decremented by the number of bytes in the send buffer and TCP knows
; that its FIN has been ACKed. (FIN occupies 1 byte in the sequence number space)
 
cmp edi, [ebx + STREAM_SOCKET.snd.size]
jbe .no_fin_ack
jbe .finiacked
 
; Drop all data in output buffer
 
push ecx edx ebx
mov ecx, [ebx + STREAM_SOCKET.snd.size]
lea eax, [ebx + STREAM_SOCKET.snd]
sub [ebx + TCP_SOCKET.SND_WND], ecx
lea eax, [ebx + STREAM_SOCKET.snd]
call socket_ring_free
pop ebx edx ecx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
or [temp_bits], TCP_BIT_FIN_IS_ACKED
jmp .ack_complete
.no_fin_ack:
jmp .wakeup
 
; Drop acknowledged data
.finiacked:
 
push ecx edx ebx
mov ecx, edi
1224,19 → 1101,17
pop ebx
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
.ack_complete:
 
;-----------------------------------------------------------------------------------
;
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
 
;----------------------------------------
; Wake up process waiting on send buffer
;
;-----------------------------------------------------------------------------------
 
.wakeup:
mov eax, ebx
call socket_notify
 
; Update TCPS
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
1244,16 → 1119,14
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
;-----------------------------------------------------------------------------------
;
; State specific ACK handeling
;
;-----------------------------------------------------------------------------------
; General ACK handling complete
; Now do the state-specific ones
; Carry flag is set when our FIN is acked
 
mov eax, [ebx + TCP_SOCKET.t_state]
jmp dword[.ack_sw_list+eax*4]
jmp dword [eax*4 + .ACK_sw_list]
 
.ack_sw_list:
.ACK_sw_list:
dd .ack_processed ; TCPS_CLOSED
dd .ack_processed ; TCPS_LISTEN
dd .ack_processed ; TCPS_SYN_SENT
1266,17 → 1139,11
dd .ack_processed ; TCPS_FIN_WAIT_2
dd .ack_tw ; TCPS_TIMED_WAIT
 
;-----------------------------------------------------------------------------------
 
.ack_fw1:
; If our FIN is now acked, enter FIN_WAIT_2
 
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
; If we can't receive any more data, then closing user can proceed.
; Starting the timer is contrary to the specification, but if we dont get a FIN,
; we'll hang forever.
 
test [ebx + SOCKET.state], SS_CANTRCVMORE
jnz @f
mov eax, ebx
1287,14 → 1154,11
mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
jmp .ack_processed
 
;-----------------------------------------------------------------------------------
.ack_c:
; Enter the TIME_WAIT state if our FIN is acked in CLOSED state.
 
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call tcp_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1303,11 → 1167,7
call socket_is_disconnected
jmp .ack_processed
 
;-----------------------------------------------------------------------------------
.ack_la:
; In LAST_ACK state, we may still be waiting for data to drain and/or to be acked.
; If our FIN is acked however, enter CLOSED state and return.
 
test [temp_bits], TCP_BIT_FIN_IS_ACKED
jz .ack_processed
 
1314,27 → 1174,27
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
pop ebx
 
mov eax, ebx
call tcp_close
jmp .drop_no_socket
 
;-----------------------------------------------------------------------------------
.ack_tw:
; In TIME_WAIT state the only thing that should arrive is a retransmission of the remote FIN.
; Acknowledge it and restart the FINACK timer
 
mov [ebx + TCP_SOCKET.timer_timed_wait], 2*TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_2msl
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
jmp .drop_after_ack
 
;-----------------------------------------------------------------------------------
;
; Initiation of Passive Open?
;
;-----------------------------------------------------------------------------------
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .ack_processed
 
.state_listen:
;-------
; LISTEN
 
align 4
.LISTEN:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
 
test [edx + TCP_header.Flags], TH_RST
1346,13 → 1206,10
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
inc [TCPS_accepts]
inc [TCPS_accepts] ; update stats
 
;;; TODO: check if it's a broadcast or multicast, and drop if so
 
;-------------------------------------------
; Processing of SYN received in LISTEN state
 
push [edi + IPv4_header.SourceAddress]
pop [ebx + IP_SOCKET.RemoteIP]
 
1363,7 → 1220,7
pop [ebx + TCP_SOCKET.IRS]
 
mov eax, [TCP_sequence_num]
add [TCP_sequence_num], TCP_ISSINCR / 2
add [TCP_sequence_num], 64000 / 2
mov [ebx + TCP_SOCKET.ISS], eax
mov [ebx + TCP_SOCKET.SND_NXT], eax
 
1394,13 → 1251,12
 
jmp .trim
 
;-----------------------------------------------------------------------------------
;
; Completion of active open?
;
;-----------------------------------------------------------------------------------
;------------
; Active Open
 
.state_syn_sent:
align 4
.SYN_SENT:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
 
test [edx + TCP_header.Flags], TH_ACK
1423,29 → 1279,29
mov eax, ebx
mov ebx, ECONNREFUSED
call tcp_drop
 
jmp .drop
@@:
 
;-----------------------------------------------------------------------------------
;
; Process received SYN in response to an active open
;
;-----------------------------------------------------------------------------------
 
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
; at this point, segment seems to be valid
 
test [edx + TCP_header.Flags], TH_ACK
jz @f
jz .no_syn_ack
 
; now, process received SYN in response to an active open
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jbe @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
.no_syn_ack:
and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission ; disable retransmission timer
@@:
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
1463,10 → 1319,9
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
 
inc [TCPS_connects]
;;; TODO: update stats
 
; set socket state to connected
 
push eax
mov eax, ebx
call socket_is_connected
1474,7 → 1329,6
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
 
; Do window scaling on this connection ?
 
mov eax, [ebx + TCP_SOCKET.t_flags]
and eax, TF_REQ_SCALE or TF_RCVD_SCALE
cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE
1486,9 → 1340,6
 
;;; TODO: reassemble packets queue
 
; If we didnt have time to re-transmit the SYN,
; Use its rtt as our initial srtt & rtt var.
 
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
je .trim
1495,40 → 1346,26
call tcp_xmit_timer
jmp .trim
 
;-----------------------------------------------------------------------------------
;
; Simultaneous open (We have received a SYN but no ACK)
;
;-----------------------------------------------------------------------------------
.simultaneous_open:
 
.simultaneous_open:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
; We have received a syn but no ACK, so we are having a simultaneous open..
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
 
;-----------------------------------------------------------------------------------
;
;-------------------------------------
; Common processing for receipt of SYN
;
;-----------------------------------------------------------------------------------
 
.trim:
; Advance sequence number to correspond to first data byte.
; If data, trim to stay within window, dropping FIN if necessary
 
inc [edx + TCP_header.SequenceNumber]
 
; Drop any received data that doesnt fit in the receive window.
 
cmp ecx, [ebx + TCP_SOCKET.RCV_WND]
jbe .dont_trim
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
inc [TCPS_rcvpackafterwin]
sub ecx, [ebx + TCP_SOCKET.RCV_WND]
add [TCPS_rcvbyteafterwin], ecx
 
mov ecx, [ebx + TCP_SOCKET.RCV_WND]
and [edx + TCP_header.Flags], not (TH_FIN)
mov ecx, [ebx + TCP_SOCKET.RCV_WND]
;;; TODO: update stats
 
.dont_trim:
mov eax, [edx + TCP_header.SequenceNumber]
1536,64 → 1373,40
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
;-----------------------------------------------------------------------------------
;
; Update window information (step 6 in RFC793)
;
;-----------------------------------------------------------------------------------
 
.ack_processed:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
 
; dont look at window if no ACK
;----------------------------------------------
; check if we need to update window information
 
test [edx + TCP_header.Flags], TH_ACK
jz .no_window_update
 
; Does the segment contain new data?
 
mov eax, [ebx + TCP_SOCKET.SND_WL1]
cmp eax, [edx + TCP_header.SequenceNumber]
jb .update_window
ja @f
 
; No new data but a new ACK ?
 
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jb .update_window
ja .no_window_update
@@:
 
; No new data or ACK but advertised window is larger then current window?
 
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jne .no_window_update
 
mov eax, dword[edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jbe .no_window_update
 
 
; Keep track of pure window updates
.update_window:
test ecx, ecx
jnz @f
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jne @f
mov eax, dword[edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jbe @f
inc [TCPS_rcvwinupd]
@@:
 
;;; TODO: update stats (Keep track of pure window updates)
 
mov eax, dword[edx + TCP_header.Window]
mov [ebx + TCP_SOCKET.SND_WND], eax
cmp eax, [ebx + TCP_SOCKET.max_sndwnd]
jbe @f
mov [ebx + TCP_SOCKET.max_sndwnd], eax
@@:
mov [ebx + TCP_SOCKET.SND_WND], eax
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
 
1604,13 → 1417,11
pop [ebx + TCP_SOCKET.SND_WL2]
 
or [temp_bits], TCP_BIT_NEEDOUTPUT
 
.no_window_update:
 
;-----------------------------------------------------------------------------------
;
; Process URG flag
;
;-----------------------------------------------------------------------------------
;-----------------
; process URG flag
 
test [edx + TCP_header.Flags], TH_URG
jz .not_urgent
1618,7 → 1429,7
cmp [edx + TCP_header.UrgentPointer], 0
jz .not_urgent
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
je .not_urgent
 
; Ignore bogus urgent offsets
1638,14 → 1449,13
 
;;; TODO (1051-1093)
 
;-----------------------------------------------------------------------------------
;
; Process the data
;
;-----------------------------------------------------------------------------------
 
;---------------------------------------
; process the data in the segment (1094)
 
.do_data:
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .final_processing
 
test [edx + TCP_header.Flags], TH_FIN
1656,23 → 1466,19
@@:
 
; The segment is in order?
 
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .out_of_order
 
; The reassembly queue is empty?
 
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .out_of_order
 
; The connection is established?
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jne .out_of_order
 
; Ok, lets do this.. Set delayed ACK flag and copy data into socket buffer
 
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
 
pusha
1684,7 → 1490,6
popa
 
; Wake up the sleeping process
 
mov eax, ebx
call socket_notify
 
1700,15 → 1505,11
 
; Generate ACK immediately, to let the other end know that a segment was received out of order,
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
 
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
.data_done:
 
;-----------------------------------------------------------------------------------
;
; Process FIN
;
;-----------------------------------------------------------------------------------
;---------------
; FIN processing
 
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
1715,7 → 1516,7
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .not_first_fin
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
1728,9 → 1529,10
 
.not_first_fin:
mov eax, [ebx + TCP_SOCKET.t_state]
jmp dword[.fin_sw_list+eax*4]
shl eax, 2
jmp dword [eax + .FIN_sw_list]
 
.fin_sw_list:
.FIN_sw_list:
dd .final_processing ; TCPS_CLOSED
dd .final_processing ; TCPS_LISTEN
dd .final_processing ; TCPS_SYN_SENT
1743,40 → 1545,26
dd .fin_wait2 ; TCPS_FIN_WAIT_2
dd .fin_timed ; TCPS_TIMED_WAIT
 
;-----------------------------------------------------------------------------------
.fin_syn_est:
; In SYN_RECEIVED and ESTABLISHED state, enter the CLOSE_WAIT state
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jmp .final_processing
 
;-----------------------------------------------------------------------------------
.fin_wait1:
; From FIN_WAIT_1 state, enter CLOSING state (our FIN has not been ACKed)
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
jmp .final_processing
 
;-----------------------------------------------------------------------------------
.fin_wait2:
; From FIN_WAIT_2 state, enter TIME_WAIT state and start the timer
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call tcp_cancel_timers
call socket_is_disconnected
 
;-----------------------------------------------------------------------------------
.fin_timed:
; (re)start the 2 MSL timer
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
 
;-----------------------------------------------------------------------------------
;
; Finally, drop the segment
;
;-----------------------------------------------------------------------------------
;-----------------
; Final processing
 
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
1803,13 → 1591,11
call net_buff_free
jmp .loop
 
;-----------------------------------------------------------------------------------
;
; Drop segment, reply with an RST segment when needed
;
;-----------------------------------------------------------------------------------
 
;-----------------------------------------------------------------------------------
;-----------------
; Drop the segment
 
 
.drop_after_ack:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
 
1824,7 → 1610,6
or [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jmp .need_output
 
;-----------------------------------------------------------------------------------
.drop_with_reset:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
 
1845,6 → 1630,9
jnz .respond_syn
jmp .done
 
;---------
; Respond
 
.respond_ack:
push ebx
mov cl, TH_RST
/kernel/trunk/network/tcp.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
27,7 → 27,7
TCPS_CLOSING = 7
TCPS_LAST_ACK = 8
TCPS_FIN_WAIT_2 = 9
TCPS_TIME_WAIT = 10
TCPS_TIMED_WAIT = 10
 
; Socket Flags
TF_ACKNOW = 1 shl 0 ; ack peer immediately
92,12 → 92,18
TCP_RTT_SHIFT = 3
TCP_RTTVAR_SHIFT = 2
 
; bits used by tcp_input and tcp_output
TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
TCP_BIT_FIN_IS_ACKED = 1 shl 3
 
TCP_BIT_SENDALOT = 1 shl 0
 
TCP_PAWS_IDLE = 24*24*60*60*100 ; 24 days, in 1/100 seconds
 
TCP_QUEUE_SIZE = 50
 
TCP_ISSINCR = 128000
 
struct TCP_header
 
SourcePort dw ?
/kernel/trunk/network/tcp_subr.inc
78,7 → 78,7
 
push edi
mov edi, [ptr + TCP_SOCKET.IRS]
inc edi ; SYN ocupies a sequence number
inc edi
mov [ptr + TCP_SOCKET.RCV_NXT], edi
mov [ptr + TCP_SOCKET.RCV_ADV], edi
pop edi
216,8 → 216,6
call socket_is_disconnected
call socket_free
 
inc [TCPS_closed]
 
xor eax, eax
ret
 
243,6 → 241,7
ret
 
.flaglist:
 
db TH_RST + TH_ACK ; TCPS_CLOSED
db 0 ; TCPS_LISTEN
db TH_SYN ; TCPS_SYN_SENT
253,9 → 252,13
db TH_FIN + TH_ACK ; TCPS_CLOSING
db TH_FIN + TH_ACK ; TCPS_LAST_ACK
db TH_ACK ; TCPS_FIN_WAIT_2
db TH_ACK ; TCPS_TIME_WAIT
db TH_ACK ; TCPS_TIMED_WAIT
 
 
 
 
 
 
;-----------------------------------------------------------------;
; ;
; TCP_respond: Fast way to send an ACK/RST/keepalive segment. ;
499,7 → 502,7
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=0x%x rtt=%d0ms\n", ebx, eax
 
inc [TCPS_rttupdated]
;TODO: update stats
 
cmp [ebx + TCP_SOCKET.t_rtt], 0
je .no_rtt_yet