Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1532 → Rev 1533

/kernel/branches/net/network/ARP.inc
506,16 → 506,18
 
;; TODO: check if driver could transmit packet
 
pop eax
imul eax, ARP_ENTRY.size
add eax, ARP_table
pop esi
imul esi, ARP_ENTRY.size
add esi, ARP_table
 
mov ecx, 25
.wait_loop:
cmp [eax + ARP_ENTRY.Status], 1
cmp [esi + ARP_ENTRY.Status], 1
je .got_it
push esi
mov esi, 10
call delay_ms
pop esi
loop .wait_loop
 
mov eax, -2 ; request send
/kernel/branches/net/network/socket.inc
169,6 → 169,7
.read_ptr dd ? ; Read pointer
.write_ptr dd ? ; Write pointer
.size dd ? ; Number of bytes buffered
.end:
}
 
virtual at 0
179,10 → 180,9
 
virtual at TCP_SOCKET.end
 
rcv RING_BUFFER
snd RING_BUFFER
 
STREAM_SOCKET:
.rcv rd RING_BUFFER.end/4
.snd rd RING_BUFFER.end/4
.end:
 
end virtual
221,14 → 221,6
mov ecx, 4
rep stosd
 
;--- for random port --
 
mov al, 0x0 ; set up 1s timer
out 0x70, al
in al, 0x71
 
;----------------------
 
@@:
pseudo_random eax
cmp ax, MIN_EPHEMERAL_PORT
235,7 → 227,6
jl @r
cmp ax, MAX_EPHEMERAL_PORT
jg @r
 
mov [last_UDP_port], ax
 
@@:
244,7 → 235,6
jl @r
cmp ax, MAX_EPHEMERAL_PORT
jg @r
 
mov [last_TCP_port], ax
 
}
318,23 → 308,14
cmp edx, IP_PROTO_TCP
jnz .no_stream
 
mov esi, eax
stdcall kernel_alloc, SOCKET_MAXDATA
mov [esi + rcv.start_ptr], eax
mov [esi + rcv.write_ptr], eax
mov [esi + rcv.read_ptr], eax
mov [esi + rcv.size], 0
add eax, SOCKET_MAXDATA
mov [esi + rcv.end_ptr], eax
mov ebx, eax
 
stdcall kernel_alloc, SOCKET_MAXDATA
mov [esi + snd.start_ptr], eax
mov [esi + snd.write_ptr], eax
mov [esi + snd.read_ptr], eax
mov [esi + snd.size], 0
add eax, SOCKET_MAXDATA
mov [esi + snd.end_ptr], eax
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
ret
 
.no_stream:
497,10 → 478,12
mov ebx, [TCP_sequence_num]
add [TCP_sequence_num], 6400
mov [eax + TCP_SOCKET.ISS], ebx
mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*640ms => 75,6 seconds
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
 
;;;; mov [ebx + TCP_SOCKET.timer_retransmission],
TCP_sendseqinit eax
 
;;;; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
 
push eax
call TCP_output
pop eax
671,6 → 654,9
call SOCKET_num_to_ptr
jz s_error
 
cmp [eax + SOCKET.Type], IP_PROTO_TCP ;;;;;;;;
je .tcp
 
mov ebx, esi
get_from_queue (eax + SOCKET_QUEUE_LOCATION),\
SOCKET_QUEUE_SIZE,\
707,10 → 693,18
.nd:
; remove the packet ;;; TODO: only if it is empty!!
 
;;;; call TCP_output ; only if it is tcp
 
call kernel_free
ret
 
.tcp:
 
mov ecx, esi
mov edi, edx
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_read
 
mov dword[esp+32], ecx ; return number of bytes copied in ebx
 
ret
 
 
787,8 → 781,13
jz s_error
 
@@:
;;;; TODO: queue the data
 
push eax
mov ecx, esi
mov esi, edx
add eax, STREAM_SOCKET.snd
call SOCKET_ring_write
pop eax
call TCP_output
 
mov [esp+32], eax
1028,58 → 1027,86
 
ret
 
 
;--------------------------
;
; eax = ptr to ring struct (just a buffer of the right size)
;
align 4
SOCKET_ring_create:
 
mov esi, eax
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
 
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
mov [esi + RING_BUFFER.start_ptr], eax
mov [esi + RING_BUFFER.write_ptr], eax
mov [esi + RING_BUFFER.read_ptr], eax
mov [esi + RING_BUFFER.size], 0
add eax, SOCKET_MAXDATA
mov [esi + RING_BUFFER.end_ptr], eax
 
ret
 
;-----------------------------------------------------------------
;
; SOCKET_ring_add
; SOCKET_ring_write
;
; Adds data to a stream socket
; Adds data to a stream socket, and updates write pointer and size
;
; IN: eax = ptr to ring struct
; ecx = data size
; esi = ptr to data
;
; OUT: eax = number of bytes stored
; OUT: ecx = number of bytes stored
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_add:
SOCKET_ring_write:
 
DEBUGF 1,"SOCKET_ring_add: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
mov edi, [eax + RING_BUFFER.size]
add edi, ecx
cmp edi, SOCKET_MAXDATA
add [eax + RING_BUFFER.size], ecx
cmp [eax + RING_BUFFER.size], SOCKET_MAXDATA
jg .too_large
 
mov [eax + RING_BUFFER.size], edi ; update size
.copy:
push ecx ;<<<< 1
mov edi, [eax + RING_BUFFER.write_ptr] ; set write ptr in edi
add [eax + RING_BUFFER.write_ptr], ecx ; update write pointer
mov edx, [eax + RING_BUFFER.end_ptr]
cmp edx, [eax + RING_BUFFER.write_ptr]
jg .copy_in_2
je .wrap_write_ptr
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi
 
.copy_more:
push ecx
and ecx, 3
rep movsb
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
shr ecx, 2
rep movsd
pop ecx ; >>>> 1/2
DEBUGF 2,"Copied %u bytes\n", ecx
 
cmp edi, [eax + RING_BUFFER.end_ptr]
jge .wrap
mov [eax + RING_BUFFER.write_ptr], edi
 
ret
 
.wrap:
sub edi, SOCKET_MAXDATA
mov [eax + RING_BUFFER.write_ptr], edi
 
ret
 
.too_large:
mov ecx, SOCKET_MAXDATA ; calculate number of bytes available in buffer
sub ecx, [eax + RING_BUFFER.size]
jz .full
jge .full
 
mov [eax + RING_BUFFER.size], SOCKET_MAXDATA ; update size, we will fill buffer completely
 
jmp .copy
 
.full:
1087,88 → 1114,57
xor ecx, ecx
ret
 
.copy_in_2:
DEBUGF 1,"Copying in 2 passes\n"
 
mov edx, ecx
mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer
sub ecx, edi
sub edx, ecx
push edx ; <<<< 2
 
mov edi, [eax + RING_BUFFER.start_ptr]
call .copy_more
 
.wrap_write_ptr:
sub [eax + RING_BUFFER.write_ptr], SOCKET_MAXDATA ; update write pointer
jmp .copy_more
 
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_ring_read
;
; reads the data, but let the data remain in the buffer
; reads the data, BUT DOES NOT CLEAR IT FROM MEMORY YET
;
; IN: eax = ptr to ring struct
; ecx = buffer size
; edi = ptr to buffer
;
; OUT: eax = number of bytes read
; OUT: ecx = number of bytes read
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_read:
 
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, edi, ecx
 
cmp [eax + RING_BUFFER.size], ecx ; update size
jl .too_large
cmp ecx, [eax + RING_BUFFER.size]
jg .less_data
 
mov esi, [eax + RING_BUFFER.read_ptr] ; update read ptr
.copy:
push ecx ;<<<< 1
mov edx, [eax + RING_BUFFER.read_ptr]
add edx, ecx
cmp edx, [eax + RING_BUFFER.end_ptr]
jg .copy_in_2
mov esi, [eax + RING_BUFFER.read_ptr]
 
.copy_more:
DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi
push ecx
and ecx, 3
rep movsb
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
shr ecx, 2
rep movsd
pop ecx ; >>>> 1/2
DEBUGF 2,"Copied %u bytes\n", ecx
 
; .no_data_at_all:
ret
 
.too_large:
.less_data:
mov ecx, [eax + RING_BUFFER.size]
test ecx, ecx
; jz .no_data_at_all
jmp .copy
 
.full:
DEBUGF 2,"Ring buffer is full!\n"
xor ecx, ecx
ret
 
.copy_in_2:
DEBUGF 1,"Copying in 2 passes\n"
 
mov edx, ecx
mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer
sub ecx, edi
sub edx, ecx
push edx ; <<<< 2
 
mov esi, [eax + RING_BUFFER.start_ptr]
call .copy_more
 
 
;-----------------------------------------------------------------
;
; SOCKET_ring_free
1186,26 → 1182,19
 
DEBUGF 1,"Trying to free %u bytes of data from ring %x\n", ecx, eax
 
cmp ecx, [eax + RING_BUFFER.size]
jle .go_for_it
 
cmp ecx, SOCKET_MAXDATA ;;;;
jg .moron_input
 
mov ecx, [eax + RING_BUFFER.size]
 
.go_for_it:
sub [eax + RING_BUFFER.size], ecx
jl .sumthinwong
add [eax + RING_BUFFER.read_ptr], ecx
 
mov edx, [eax + RING_BUFFER.end_ptr]
cmp [eax + RING_BUFFER.read_ptr], edx
jl @f
sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA ;;;;;
sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
@@:
ret
 
.moron_input:
.sumthinwong: ; we could free all available bytes, but that would be stupid, i guess..
add [eax + RING_BUFFER.size], ecx
xor ecx, ecx
ret
 
1371,8 → 1360,8
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jnz .no_stream
 
stdcall kernel_free, [eax + rcv.start_ptr]
stdcall kernel_free, [eax + snd.start_ptr]
stdcall kernel_free, [eax + STREAM_SOCKET.rcv + RING_BUFFER.start_ptr]
stdcall kernel_free, [eax + STREAM_SOCKET.snd + RING_BUFFER.start_ptr]
.no_stream:
 
push eax ; this will be passed to kernel_free
1400,9 → 1389,9
ret
 
 
; socket nr in ebx
; new socket nr in eax
; preserver edx
; IN: socket nr in ebx
; OUT: socket nr in eax
; preserves edx
 
align 4
SOCKET_fork:
1440,7 → 1429,7
; Get socket structure address by its number
;
; IN: ecx = socket number
; OUT: ecx = 0 on error, socket ptr otherwise
; OUT: eax = 0 on error, socket ptr otherwise
; ZF = set on error
;
;---------------------------------------------------
/kernel/branches/net/network/tcp.inc
266,7 → 266,31
} ; returns in dx only
 
 
macro TCP_sendseqinit ptr {
 
push edi ;;;; i dont like this static use of edi
mov edi, [ptr + TCP_SOCKET.ISS]
mov [ptr + TCP_SOCKET.SND_UP], edi
mov [ptr + TCP_SOCKET.SND_MAX], edi
mov [ptr + TCP_SOCKET.SND_NXT], edi
mov [ptr + TCP_SOCKET.SND_UNA], edi
pop edi
 
}
 
macro TCP_rcvseqinit ptr {
 
push edi
mov edi, [ptr + TCP_SOCKET.IRS]
inc edi
mov [ptr + TCP_SOCKET.RCV_NXT], edi
mov [ptr + TCP_SOCKET.RCV_ADV], edi
pop edi
 
}
 
 
 
;-----------------------------------------------------------------
;
; TCP_input:
420,7 → 444,7
;-----------------------------------
; Is this socket a listening socket?
 
; test [ebx + SOCKET.options], SO_ACCEPTCON
test [ebx + SOCKET.options], SO_ACCEPTCON
; jnz .listening_socket ;;;;; TODO
 
;-------------------------------------
477,7 → 501,7
 
movzx eax, word[edi+2]
rol ax, 8
DEBUGF 1,"Maxseg: %u", ax
DEBUGF 1,"Maxseg: %u\n", ax
 
mov [ebx + TCP_SOCKET.t_maxseg], eax
 
493,7 → 517,7
test [edx + TCP_segment.Flags], TH_SYN
jz @f
 
DEBUGF 1,"Got window option"
DEBUGF 1,"Got window option\n"
 
;;;;;
@@:
505,7 → 529,7
cmp byte [edi+1], 10
jne .no_options
 
DEBUGF 1,"Got timestamp option"
DEBUGF 1,"Got timestamp option\n"
 
;;;;;
 
532,20 → 556,30
cmp [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
jnz .not_uni_xfer
 
DEBUGF 1,"1\n"
 
test [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
jnz .not_uni_xfer
 
DEBUGF 1,"2\n"
 
test [edx + TCP_segment.Flags], TH_ACK
jz .not_uni_xfer
 
DEBUGF 1,"3\n"
 
mov eax, [edx + TCP_segment.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .not_uni_xfer
 
movzx eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value isntead: todo: figure out where to store it)
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .not_uni_xfer
DEBUGF 1,"4\n"
 
;; movzx eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value isntead: todo: figure out where to store it)
;; cmp eax, [ebx + TCP_SOCKET.SND_WND]
;; jne .not_uni_xfer
 
DEBUGF 1,"5\n"
 
mov eax, [ebx + TCP_SOCKET.SND_NXT]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jne .not_uni_xfer
584,7 → 618,7
; Delete acknowledged bytes from send buffer
; notice how ecx already holds number of bytes ack-ed
 
lea eax, [ebx + snd]
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
 
; Stop retransmit timer
620,9 → 654,12
DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
 
add esi, edx
lea eax, [ebx + rcv]
call SOCKET_ring_add ; Add the data to the socket buffer
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
 
mov eax, ebx
call SOCKET_notify_owner
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag
 
633,7 → 670,7
 
.not_uni_xfer:
 
DEBUGF 1,"Header prediction failed\n"
DEBUGF 1,"Header prediction failed\n" ; time to do it the "slow" way :)
 
;------------------------------
; Calculate receive window size
640,11 → 677,6
 
;;;;
 
;-------------------------
; TCP slow input procedure
 
DEBUGF 1,"TCP slow input procedure\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN
je .LISTEN
 
654,7 → 686,7
;--------------------------------------------
; Protection Against Wrapped Sequence Numbers
 
; First, check timestamp if present
; First, check if timestamp is present
 
;;;; TODO
 
681,7 → 713,9
test [edx + TCP_segment.Flags], TH_SYN
jz .drop
 
; TODO: find sender ip address somewhere!
cmp esi, 0xffffff ; destination ip = 255.255.255.255 ?
jz .drop
 
; TODO: check if it's a broadcast or multicast, and drop if so
 
call SOCKET_fork
706,7 → 740,6
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
 
mov ebx, eax
 
jmp .trim_then_step6
 
 
725,11 → 758,9
cmp eax, [ebx + TCP_SOCKET.ISS]
jle .drop_with_reset
 
DEBUGF 1,"snd_max = %x\n", [ebx + TCP_SOCKET.SND_MAX] ;;; TODO: set this, but where?
 
; mov eax, [edx + TCP_segment.AckNumber]
;; cmp eax, [ebx + TCP_SOCKET.SND_MAX]
;; jg .drop_with_reset
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jg .drop_with_reset
@@:
 
test [edx + TCP_segment.Flags], TH_RST
767,7 → 798,7
push [edx + TCP_segment.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
 
;;; TODO: tcp_rcvseqinit
TCP_rcvseqinit ebx
 
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
781,7 → 812,7
DEBUGF 1,"TCP: active open\n"
 
; TODO: update stats
; TODO: set socket state to connected
; TODO: set general socket state to connected
 
mov [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
 
821,16 → 852,16
 
.trim_then_step6:
 
DEBUGF 1,"Trimming window\n"
 
;----------------------------
; trim any data not in window
 
DEBUGF 1,"Trimming window\n"
 
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_segment.SequenceNumber]
 
test eax, eax
jz .no_drop
jz .no_duplicate
 
test [edx + TCP_segment.Flags], TH_SYN
jz .no_drop
848,10 → 879,10
 
and [edx + TCP_segment.Flags], not (TH_URG)
dec eax
 
jz .no_duplicate
.no_drop:
 
DEBUGF 1,"Going to drop %u bytes of data", eax
DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx
 
; eax holds number of bytes to drop
 
895,7 → 926,7
 
.duplicate:
 
DEBUGF 1,"Duplicate received"
DEBUGF 1,"Duplicate received\n"
 
;----------------------------------------
; Update statistics for duplicate packets
924,7 → 955,7
; Handle data that arrives after process terminates
 
cmp [ebx + SOCKET.PID], 0
jge @f
jg @f
 
cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
jle @f
936,7 → 967,6
;;; update stats
 
jmp .drop_with_reset
 
@@:
 
;----------------------------------------
1039,10 → 1069,14
jg .ack_dup
jl .ack_nodup
 
DEBUGF 1,"TCP state = syn received"
 
;;;;;
 
.ack_dup:
 
DEBUGF 1,"Duplicate ACK"
 
;;;;
 
.ack_nodup:
1049,6 → 1083,8
 
;;;; 887
 
DEBUGF 1,"New ACK"
 
;-------------------------------------------------
; If the congestion window was inflated to account
; for the other side's cached packets, retrace it
1069,7 → 1105,6
mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value
.all_outstanding:
 
 
;-------------------------------------------
; Open congestion window in response to ACKs
 
1079,9 → 1114,9
;------------------------------------------
; Remove acknowledged data from send buffer
 
lea eax, [ebx + snd]
mov ecx, ecx ;;;; 943 - 956
call SOCKET_ring_free
xor ecx, ecx ;;;;;;
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free ;;;; 943 - 956
 
;---------------------------------------
; Wake up process waiting on send buffer
1196,7 → 1231,7
;;; 1040-1050
 
movzx eax, [edx + TCP_segment.UrgentPointer]
add eax, [ebx + rcv.size]
add eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
cmp eax, SOCKET_MAXDATA
jle .not_urgent
 
1216,18 → 1251,36
 
.do_data:
 
DEBUGF 1,"TCP: do data:\n"
DEBUGF 1,"TCP: do data\n"
 
test [edx + TCP_segment.Flags], TH_FIN
jnz .process_fin
 
test [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
jge .dont_do_data
 
test ecx, ecx
jz .final_processing
 
DEBUGF 1,"Processing data in segment\n"
 
;;; NOW, process the data
;; TODO: check if data is in sequence !
 
movzx eax, [edx + TCP_segment.DataOffset] ;;; todo: remember this in.. edi ?
and eax, 0xf0
shr al, 2
 
lea esi, [edx + eax]
 
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
add [ebx + TCP_SOCKET.RCV_NXT], ecx ;;; right ?
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write
 
mov eax, ebx
call SOCKET_notify_owner
 
jmp .final_processing
 
 
1248,26 → 1301,33
dd .no_fin ;TCB_CLOSED
dd .no_fin ;TCB_LISTEN
dd .no_fin ;TCB_SYN_SENT
dd ._1131 ;TCB_SYN_RECEIVED
dd ._1131 ;TCB_ESTABLISHED
dd .fin_syn_est ;TCB_SYN_RECEIVED
dd .fin_syn_est ;TCB_ESTABLISHED
dd .no_fin ;TCB_CLOSE_WAIT
dd ._1139 ;TCB_FIN_WAIT_1
dd .fin_wait1 ;TCB_FIN_WAIT_1
dd .no_fin ;TCB_CLOSING
dd .no_fin ;TCB_LAST_ACK
dd ._1147 ;TCB_FIN_WAIT_2
dd ._1156 ;TCB_TIMED_WAIT
dd .fin_wait2 ;TCB_FIN_WAIT_2
dd .fin_timed ;TCB_TIMED_WAIT
 
 
 
._1131:
.fin_syn_est:
 
._1139:
jmp .final_processing
 
._1147:
.fin_wait1:
 
._1156:
jmp .final_processing
 
.fin_wait2:
 
jmp .final_processing
 
.fin_timed:
 
jmp .final_processing
 
.no_fin:
 
;-----------------
1277,6 → 1337,8
 
DEBUGF 1,"Final processing\n"
 
mov [ebx + SOCKET.lock], 0
 
;;; if debug enabled, output packet
 
;test ;;;needoutput = 1
1285,7 → 1347,6
test [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
jnz .ack_now
 
mov [ebx + SOCKET.lock], 0
call kernel_free
add esp, 4
ret
1299,7 → 1360,6
call TCP_output
pop ebx
 
mov [ebx + SOCKET.lock], 0
call kernel_free
add esp, 4
ret
1322,7 → 1382,6
call TCP_output
pop ebx
 
mov [ebx + SOCKET.lock], 0
call kernel_free
add esp, 4
ret
1347,7 → 1406,6
test [edx + TCP_segment.Flags], TH_SYN
jnz .respond_syn
 
mov [ebx + SOCKET.lock], 0
call kernel_free
add esp, 4
ret
1354,9 → 1412,11
 
.respond_ack:
 
;;;;
mov dl, TH_RST
 
push ebx
call TCP_respond_segment
pop ebx
 
jmp .destroy_new_socket
 
1363,9 → 1423,11
 
.respond_syn:
 
;;;;
mov dl, TH_RST + TH_ACK
 
call TCP_respond_segment
push ebx
call TCP_respond_socket
pop ebx
 
jmp .destroy_new_socket
 
1383,7 → 1445,6
 
;;;; kill the newly created socket
 
mov [ebx + SOCKET.lock], 0
call kernel_free
add esp, 4
ret
1473,7 → 1534,7
test ecx, ecx
jnz .no_zero_window
 
cmp ebx, [eax + snd.size]
cmp ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
jge @f
 
and dl, not (TH_FIN) ; clear the FIN flag ??? how can it be set before?
1491,7 → 1552,7
 
;;;106
 
mov esi, [eax + snd.size]
mov esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
cmp esi, ecx
jl @f
mov esi, ecx
1536,7 → 1597,7
mov edi, [eax + TCP_SOCKET.SND_NXT]
add edi, esi ; len
sub edi, [eax + TCP_SOCKET.SND_UNA]
add edi, [eax + snd.size]
add edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
cmp edi, 0
jle @f
 
1549,7 → 1610,7
; From now on, ecx will be the window we advertise to the other end
 
mov ecx, SOCKET_MAXDATA
sub ecx, [eax + rcv.size]
sub ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
 
;------------------------------
; Sender silly window avoidance
1706,7 → 1767,11
; edi = header size
; esi = snd ring buff ptr
 
xor ecx, ecx ;;;;;
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
 
; Start by pushing all TCP header values in reverse order on stack
1738,8 → 1803,6
; Create the IP packet
mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
; mov ecx, ; data length
; mov dx, ; fragment id
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
jz .fail
1747,25 → 1810,23
;-----------------------------------------
; Move TCP header from stack to TCP packet
 
; pop ecx ; header size
; mov esi, esp
; add esp, ecx
; shr ecx, 2
; rep movsd
 
mov ecx, [esp]
lea esi, [esp+4]
push ecx
mov ecx, [esp+4]
lea esi, [esp+4+4]
shr ecx, 2
rep movsd
pop ecx ; full TCP packet size
 
pop ecx
add esp, ecx
pop esi ; headersize
add esp, esi
 
mov [esp + 4], eax ; packet ptr
mov [esp + 4+4], edx ; packet size
mov [esp + 4], eax ; packet ptr
 
mov edx, edi
sub edx, ecx
mov edx, edi ; begin of data
sub edx, esi ; begin of packet (edi = begin of data)
push ecx
sub ecx, esi ; data size
 
;--------------
; Copy the data
1774,16 → 1835,34
; ecx = buffer size
; edi = ptr to buffer
 
mov eax, [esp] ; socket ptr
push ecx edx
add eax, snd
mov eax, [esp+4] ; socket ptr
push edx
add eax, STREAM_SOCKET.snd
call SOCKET_ring_read
pop esi ecx
pop eax
 
;-------------------------------------------------------------
; Create the checksum (we have already pushed IPs onto stack)
test [esi + TCP_segment.Flags], TH_SYN + TH_FIN
jz @f
inc [eax + TCP_SOCKET.SND_NXT]
;;; TODO: update sentfin flag
@@:
 
;; add [eax + TCP_SOCKET.SND_NXT], ecx
 
mov edx, [eax + TCP_SOCKET.SND_NXT]
cmp edx, [eax + TCP_SOCKET.SND_MAX]
jle @f
mov [eax + TCP_SOCKET.SND_MAX], edx
 
;;;; TODO: time transmission (420)
@@:
 
;;; TODO: set retransmission timer
 
;--------------------
; Create the checksum
 
DEBUGF 1,"checksum: ptr=%x size=%u\n", esi, ecx
 
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
1969,10 → 2048,9
mov ecx, TCP_segment.Data
mov di , IP_PROTO_TCP shl 8 + 128
call IPv4_output
test edi, edi
jz .error
pop esi cx
 
pop esi cx
push edx eax
 
;---------------------------------------------------