forked from KolibriOS/kolibrios
Updates of TCP_output for net branch
git-svn-id: svn://kolibrios.org@1761 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
224ec76fad
commit
e9daec20c8
@ -33,7 +33,7 @@ TCP_output:
|
|||||||
|
|
||||||
.not_idle:
|
.not_idle:
|
||||||
.again:
|
.again:
|
||||||
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset
|
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
|
||||||
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
|
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
|
||||||
|
|
||||||
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
|
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
|
||||||
@ -42,14 +42,17 @@ TCP_output:
|
|||||||
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
|
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
|
||||||
@@: ;
|
@@: ;
|
||||||
|
|
||||||
call TCP_outflags ; in dl
|
call TCP_outflags ; flags in dl
|
||||||
|
|
||||||
|
;------------------------
|
||||||
|
; data being forced out ?
|
||||||
|
|
||||||
; If in persist timeout with window of 0, send 1 byte.
|
; If in persist timeout with window of 0, send 1 byte.
|
||||||
; Otherwise, if window is small but nonzero, and timer expired,
|
; Otherwise, if window is small but nonzero, and timer expired,
|
||||||
; we will send what we can and go to transmit state
|
; we will send what we can and go to transmit state
|
||||||
|
|
||||||
test [eax + TCP_SOCKET.t_force], -1
|
test [eax + TCP_SOCKET.t_force], -1
|
||||||
jz .no_persist_timeout
|
jz .no_force
|
||||||
|
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jnz .no_zero_window
|
jnz .no_zero_window
|
||||||
@ -61,16 +64,16 @@ TCP_output:
|
|||||||
|
|
||||||
@@:
|
@@:
|
||||||
inc ecx
|
inc ecx
|
||||||
jmp .no_persist_timeout
|
jmp .no_force
|
||||||
|
|
||||||
.no_zero_window:
|
.no_zero_window:
|
||||||
|
|
||||||
mov [eax + TCP_SOCKET.timer_persist], 0
|
mov [eax + TCP_SOCKET.timer_persist], 0
|
||||||
mov [eax + TCP_SOCKET.t_rxtshift], 0
|
mov [eax + TCP_SOCKET.t_rxtshift], 0
|
||||||
|
|
||||||
.no_persist_timeout:
|
.no_force:
|
||||||
|
|
||||||
;;;106
|
;--------------------------------
|
||||||
|
; Calculate how much data to send (106)
|
||||||
|
|
||||||
mov esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
|
mov esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
|
||||||
cmp esi, ecx
|
cmp esi, ecx
|
||||||
@ -79,104 +82,119 @@ TCP_output:
|
|||||||
@@:
|
@@:
|
||||||
sub esi, ebx
|
sub esi, ebx
|
||||||
|
|
||||||
cmp esi, -1
|
;------------------------
|
||||||
jne .not_minus_one
|
; check for window shrink (107)
|
||||||
|
|
||||||
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
|
; If FIN has been set, but not ACKed, but we havent been called to retransmit, esi will be -1
|
||||||
; len (esi) will be -1
|
|
||||||
; Otherwise, window shrank after we sent into it.
|
; Otherwise, window shrank after we sent into it.
|
||||||
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
|
|
||||||
; We will enter persist state below.
|
|
||||||
; If window didn't close completely, just wait for an ACK
|
|
||||||
|
|
||||||
|
jnc .bigger_than_zero
|
||||||
|
|
||||||
|
; enter persist state
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
|
|
||||||
|
; If window shrank to 0
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jnz @f
|
jnz @f
|
||||||
|
|
||||||
mov [eax + TCP_SOCKET.timer_retransmission], 0 ; cancel retransmit
|
; cancel pending retransmit
|
||||||
|
mov [eax + TCP_SOCKET.timer_retransmission], 0
|
||||||
|
|
||||||
|
; pull SND_NXT back to (closed) window, We will enter persist state below.
|
||||||
push [eax + TCP_SOCKET.SND_UNA]
|
push [eax + TCP_SOCKET.SND_UNA]
|
||||||
pop [eax + TCP_SOCKET.SND_NXT]
|
pop [eax + TCP_SOCKET.SND_NXT]
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
.not_minus_one:
|
; If window didn't close completely, just wait for an ACK
|
||||||
|
|
||||||
;;; 124
|
.bigger_than_zero:
|
||||||
|
|
||||||
|
;---------------------------
|
||||||
|
; Send one segment at a time (124)
|
||||||
|
|
||||||
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||||
jle @f
|
jle @f
|
||||||
|
|
||||||
mov esi, [eax + TCP_SOCKET.t_maxseg]
|
mov esi, [eax + TCP_SOCKET.t_maxseg]
|
||||||
;sendalot = 1
|
|
||||||
|
;;; sendalot = 1
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
;;; 128
|
;--------------------------------------------
|
||||||
|
; Turn of FIN flag if send buffer not emptied (128)
|
||||||
|
|
||||||
mov edi, [eax + TCP_SOCKET.SND_NXT]
|
mov edi, [eax + TCP_SOCKET.SND_NXT]
|
||||||
add edi, esi ; len
|
add edi, esi
|
||||||
sub edi, [eax + TCP_SOCKET.SND_UNA]
|
sub edi, [eax + TCP_SOCKET.SND_UNA]
|
||||||
add edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
|
sub edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
|
||||||
cmp edi, 0
|
|
||||||
jle @f
|
|
||||||
|
|
||||||
and dl, not (TH_FIN) ; clear the FIN flag
|
cmp edi, 0
|
||||||
|
jge @f
|
||||||
|
|
||||||
|
and dl, not (TH_FIN)
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
|
;-------------------------------
|
||||||
; set ecx to space available in receive buffer
|
; calculate window advertisement (130)
|
||||||
; From now on, ecx will be the window we advertise to the other end
|
|
||||||
|
|
||||||
mov ecx, SOCKET_MAXDATA
|
mov ecx, SOCKET_MAXDATA
|
||||||
sub ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
|
sub ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
|
||||||
|
|
||||||
;------------------------------
|
;------------------------------
|
||||||
; Sender silly window avoidance
|
; Sender silly window avoidance (131)
|
||||||
|
|
||||||
cmp ecx, [eax + TCP_SOCKET.t_maxseg]
|
test esi, esi
|
||||||
|
jz .len_zero
|
||||||
|
|
||||||
|
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||||
je .send
|
je .send
|
||||||
|
|
||||||
;;; TODO: 144-145
|
;;; if (idle or TF_NODELAY) && (esi + ebx >= so_snd.sb_cc), send
|
||||||
|
|
||||||
test [eax + TCP_SOCKET.t_force], -1
|
test [eax + TCP_SOCKET.t_force], -1 ;;;
|
||||||
jnz .send
|
jnz .send
|
||||||
|
|
||||||
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
|
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
|
||||||
shr ebx, 1
|
shr ebx, 1
|
||||||
cmp ecx, ebx
|
cmp esi, ebx
|
||||||
jge .send
|
jge .send
|
||||||
|
|
||||||
mov ebx, [eax + TCP_SOCKET.SND_NXT]
|
mov ebx, [eax + TCP_SOCKET.SND_NXT]
|
||||||
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
|
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
|
||||||
jl .send
|
jl .send
|
||||||
|
|
||||||
;----------------------------------------
|
.len_zero:
|
||||||
; Check if a window update should be sent
|
|
||||||
|
|
||||||
test ecx, ecx ; window
|
;----------------------------------------
|
||||||
|
; Check if a window update should be sent (154)
|
||||||
|
|
||||||
|
test ecx, ecx
|
||||||
jz .no_window
|
jz .no_window
|
||||||
|
|
||||||
;;; TODO 154-172
|
;;; TODO 167-172
|
||||||
|
|
||||||
.no_window:
|
.no_window:
|
||||||
|
|
||||||
;--------------------------
|
;--------------------------
|
||||||
; Should a segment be sent?
|
; Should a segment be sent? (174)
|
||||||
|
|
||||||
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
|
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
|
||||||
jnz .send
|
jnz .send
|
||||||
|
|
||||||
test dl, TH_SYN + TH_RST
|
test dl, TH_SYN + TH_RST ; we need to send a SYN or RST
|
||||||
jnz .send
|
jnz .send
|
||||||
|
|
||||||
mov ebx, [eax + TCP_SOCKET.SND_UP]
|
mov ebx, [eax + TCP_SOCKET.SND_UP] ; when urgent pointer is beyond start of send bufer
|
||||||
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
||||||
jg .send
|
jg .send
|
||||||
|
|
||||||
test dl, TH_FIN
|
test dl, TH_FIN
|
||||||
jz .enter_persist
|
jz .enter_persist ; no reason to send, enter persist state
|
||||||
|
|
||||||
|
; FIN was set, only send if not already sent, or on retransmit
|
||||||
|
|
||||||
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
|
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
|
||||||
jnz .send
|
jnz .send
|
||||||
@ -186,27 +204,38 @@ TCP_output:
|
|||||||
je .send
|
je .send
|
||||||
|
|
||||||
;--------------------
|
;--------------------
|
||||||
; Enter persist state
|
; Enter persist state (191)
|
||||||
|
|
||||||
.enter_persist:
|
.enter_persist:
|
||||||
|
|
||||||
DEBUGF 1,"Entering persist state\n"
|
DEBUGF 1,"Entering persist state\n"
|
||||||
|
|
||||||
;--------------------------------------
|
|
||||||
; No reason to send a segment, just ret
|
;;; 213 - 217
|
||||||
|
|
||||||
|
;----------------------------
|
||||||
|
; No reason to send a segment (219)
|
||||||
|
|
||||||
DEBUGF 1,"No reason to send a segment\n"
|
DEBUGF 1,"No reason to send a segment\n"
|
||||||
|
|
||||||
mov [ebx + SOCKET.lock], 0
|
mov [eax + SOCKET.lock], 0
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------
|
;-----------------------------------------------
|
||||||
;
|
;
|
||||||
; Send a segment
|
; Send a segment (222)
|
||||||
;
|
;
|
||||||
; eax = socket pointer
|
; eax = socket pointer
|
||||||
|
; esi = data len
|
||||||
; dl = flags
|
; dl = flags
|
||||||
;
|
;
|
||||||
;-----------------------------------------------
|
;-----------------------------------------------
|
||||||
@ -218,19 +247,19 @@ TCP_output:
|
|||||||
mov edi, TCP_segment.Data ; edi will contain headersize
|
mov edi, TCP_segment.Data ; edi will contain headersize
|
||||||
|
|
||||||
sub esp, 8 ; create some space on stack
|
sub esp, 8 ; create some space on stack
|
||||||
push eax ; save this too..
|
push eax ; save socket pointer
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
; Send options with first SYN segment
|
; Send options with first SYN segment
|
||||||
|
|
||||||
test dl, TH_SYN
|
test dl, TH_SYN
|
||||||
jz .no_options
|
jz .options_done
|
||||||
|
|
||||||
push [eax + TCP_SOCKET.ISS]
|
push [eax + TCP_SOCKET.ISS]
|
||||||
pop [eax + TCP_SOCKET.SND_NXT]
|
pop [eax + TCP_SOCKET.SND_NXT]
|
||||||
|
|
||||||
test [eax + TCP_SOCKET.t_flags], TF_NOOPT
|
test [eax + TCP_SOCKET.t_flags], TF_NOOPT
|
||||||
jnz .no_options
|
jnz .options_done
|
||||||
|
|
||||||
mov ecx, 1460
|
mov ecx, 1460
|
||||||
or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
|
or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
|
||||||
@ -272,32 +301,47 @@ TCP_output:
|
|||||||
jz .no_timestamp
|
jz .no_timestamp
|
||||||
|
|
||||||
.timestamp:
|
.timestamp:
|
||||||
mov esi, [timer_ticks]
|
mov ebx, [timer_ticks]
|
||||||
bswap esi
|
bswap ebx
|
||||||
push esi
|
push ebx
|
||||||
pushw 0
|
pushw 0
|
||||||
pushd TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
|
pushd TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
|
||||||
add di, 10
|
add di, 10
|
||||||
|
|
||||||
.no_timestamp:
|
.no_timestamp:
|
||||||
;; TODO: check if we dont exceed the max segment size
|
|
||||||
|
|
||||||
.no_options:
|
; <Add additional options here>
|
||||||
; eax = socket ptr
|
|
||||||
; edx = flags
|
|
||||||
; ecx = data size
|
|
||||||
; edi = header size
|
|
||||||
; esi = snd ring buff ptr
|
|
||||||
|
|
||||||
mov ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
|
|
||||||
cmp ecx, [eax + TCP_SOCKET.t_maxseg] ;;; right?
|
|
||||||
jle @f
|
|
||||||
mov ecx, [eax + TCP_SOCKET.t_maxseg]
|
|
||||||
@@:
|
|
||||||
add ecx, edi ; total TCP segment size
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.options_done:
|
||||||
|
|
||||||
|
; eax = socket ptr
|
||||||
|
; edx = flags
|
||||||
|
; edi = header size
|
||||||
|
; esi = data len
|
||||||
|
|
||||||
|
;---------------------------------------------
|
||||||
|
; check if we dont exceed the max segment size (270)
|
||||||
|
|
||||||
|
add esi, edi ; total TCP segment size
|
||||||
|
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||||
|
jle .no_overflow
|
||||||
|
|
||||||
|
mov esi, [eax + TCP_SOCKET.t_maxseg]
|
||||||
|
|
||||||
|
;;; sendalot = 1
|
||||||
|
|
||||||
|
.no_overflow:
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
; Start by pushing all TCP header values in reverse order on stack
|
; Start by pushing all TCP header values in reverse order on stack
|
||||||
; (essentially, creating the tcp header!)
|
; (essentially, creating the tcp header on the stack!)
|
||||||
|
|
||||||
pushw 0 ; .UrgentPointer dw ?
|
pushw 0 ; .UrgentPointer dw ?
|
||||||
pushw 0 ; .Checksum dw ?
|
pushw 0 ; .Checksum dw ?
|
||||||
@ -322,7 +366,11 @@ TCP_output:
|
|||||||
|
|
||||||
push edi ; header size
|
push edi ; header size
|
||||||
|
|
||||||
|
;---------------------
|
||||||
; Create the IP packet
|
; Create the IP packet
|
||||||
|
|
||||||
|
mov ecx, esi
|
||||||
|
|
||||||
mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip
|
mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip
|
||||||
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
|
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
|
||||||
mov di, IP_PROTO_TCP shl 8 + 128
|
mov di, IP_PROTO_TCP shl 8 + 128
|
||||||
@ -357,20 +405,26 @@ TCP_output:
|
|||||||
; ecx = buffer size
|
; ecx = buffer size
|
||||||
; edi = ptr to buffer
|
; edi = ptr to buffer
|
||||||
|
|
||||||
; test ecx, ecx
|
mov eax, [esp+4] ; get socket ptr
|
||||||
mov eax, [esp+4] ; socket ptr
|
|
||||||
add [eax + TCP_SOCKET.SND_NXT], ecx
|
add [eax + TCP_SOCKET.SND_NXT], ecx ; update sequence number
|
||||||
|
|
||||||
add eax, STREAM_SOCKET.snd
|
add eax, STREAM_SOCKET.snd
|
||||||
push edx
|
push edx
|
||||||
call SOCKET_ring_read
|
call SOCKET_ring_read
|
||||||
pop esi
|
pop esi ; begin of data
|
||||||
pop ecx
|
pop ecx ; full packet size
|
||||||
pop eax
|
pop eax ; socket ptr
|
||||||
|
|
||||||
|
;----------------------------------
|
||||||
|
; update sequence number and timers (400)
|
||||||
|
|
||||||
test [esi + TCP_segment.Flags], TH_SYN + TH_FIN
|
test [esi + TCP_segment.Flags], TH_SYN + TH_FIN
|
||||||
jz @f
|
jz @f
|
||||||
inc [eax + TCP_SOCKET.SND_NXT]
|
inc [eax + TCP_SOCKET.SND_NXT] ; syn and fin take a sequence number
|
||||||
;;; TODO: update sentfin flag
|
test [esi + TCP_segment.Flags], TH_FIN
|
||||||
|
jz @f
|
||||||
|
or [eax + TCP_SOCKET.t_flags], TF_SENTFIN ; if we sent a fin, set the sentfin flag
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
mov edx, [eax + TCP_SOCKET.SND_NXT]
|
mov edx, [eax + TCP_SOCKET.SND_NXT]
|
||||||
@ -379,9 +433,25 @@ TCP_output:
|
|||||||
mov [eax + TCP_SOCKET.SND_MAX], edx
|
mov [eax + TCP_SOCKET.SND_MAX], edx
|
||||||
|
|
||||||
;;;; TODO: time transmission (420)
|
;;;; TODO: time transmission (420)
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
;;; TODO: set retransmission timer
|
; set retransmission timer if not already set, and not doing an ACK or keepalive probe
|
||||||
|
|
||||||
|
cmp [eax + TCP_SOCKET.timer_retransmission], 1000 ;;;;
|
||||||
|
jl .retransmit_set
|
||||||
|
|
||||||
|
cmp edx, [eax + TCP_SOCKET.SND_UNA] ; edx = [eax + TCP_SOCKET.SND_NXT]
|
||||||
|
je .retransmit_set
|
||||||
|
|
||||||
|
mov edx, [eax + TCP_SOCKET.t_rxtcur]
|
||||||
|
mov [eax + TCP_SOCKET.timer_retransmission], dx
|
||||||
|
|
||||||
|
mov [eax + TCP_SOCKET.timer_persist], 0
|
||||||
|
mov [eax + TCP_SOCKET.t_rxtshift], 0 ;;; TODO: only do this if timer_persist was set
|
||||||
|
|
||||||
|
|
||||||
|
.retransmit_set:
|
||||||
|
|
||||||
;--------------------
|
;--------------------
|
||||||
; Create the checksum
|
; Create the checksum
|
||||||
@ -391,6 +461,10 @@ TCP_output:
|
|||||||
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
|
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
|
||||||
mov [esi+TCP_segment.Checksum], dx
|
mov [esi+TCP_segment.Checksum], dx
|
||||||
|
|
||||||
|
; unlock socket
|
||||||
|
|
||||||
|
mov [eax + SOCKET.lock], 0
|
||||||
|
|
||||||
;----------------
|
;----------------
|
||||||
; Send the packet
|
; Send the packet
|
||||||
|
|
||||||
@ -403,6 +477,7 @@ TCP_output:
|
|||||||
pop ecx
|
pop ecx
|
||||||
add esp, ecx
|
add esp, ecx
|
||||||
add esp, 4+8
|
add esp, 4+8
|
||||||
|
mov [eax + SOCKET.lock], 0
|
||||||
DEBUGF 1,"TCP_output: failed\n"
|
DEBUGF 1,"TCP_output: failed\n"
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -60,17 +60,6 @@ local .exit
|
|||||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||||
jne .loop
|
jne .loop
|
||||||
|
|
||||||
|
|
||||||
;---------------
|
|
||||||
|
|
||||||
cmp [eax + SOCKET.lock], 0
|
|
||||||
jz @f
|
|
||||||
|
|
||||||
DEBUGF 1,"\nlocked\n"
|
|
||||||
@@:
|
|
||||||
|
|
||||||
;-----------
|
|
||||||
|
|
||||||
inc [eax + TCP_SOCKET.t_idle]
|
inc [eax + TCP_SOCKET.t_idle]
|
||||||
dec [eax + TCP_SOCKET.timer_retransmission]
|
dec [eax + TCP_SOCKET.timer_retransmission]
|
||||||
jnz .check_more2
|
jnz .check_more2
|
||||||
|
Loading…
Reference in New Issue
Block a user