Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1253 → Rev 1254

/kernel/branches/net/network/tcp.inc
17,30 → 17,9
 
$Revision$
 
 
TCB_LISTEN equ 1
TCB_SYN_SENT equ 2
TCB_SYN_RECEIVED equ 3
TCB_ESTABLISHED equ 4
TCB_FIN_WAIT_1 equ 5
TCB_FIN_WAIT_2 equ 6
TCB_CLOSE_WAIT equ 7
TCB_CLOSING equ 8
TCB_LAST_ACK equ 9
TCB_TIMED_WAIT equ 10
TCB_CLOSED equ 11
 
TH_FIN equ 1 shl 0
TH_SYN equ 1 shl 1
TH_RST equ 1 shl 2
TH_PUSH equ 1 shl 3
TH_ACK equ 1 shl 4
TH_URG equ 1 shl 5
 
TWOMSL equ 10 ; # of secs to wait before closing socket
 
TCP_RETRIES equ 5 ; Number of times to resend a Packet
TCP_TIMEOUT equ 10 ; resend if not replied to in 1/100 s
TCP_PACKET_TTL equ 50 ; resend if not replied to in 1/100 s
TCP_SOCKET_TTL equ 10 ; # of secs to wait before closing socket
 
TCP_QUEUE_SIZE equ 16
 
73,7 → 52,7
align 4
iglobal
 
TCBStateHandler:
stateHandler:
 
dd stateTCB_LISTEN
dd stateTCB_SYN_SENT
90,30 → 69,6
endg
 
 
macro inc_INET reg {
 
inc byte [reg + 0]
adc byte [reg + 1], 0
adc byte [reg + 2], 0
adc byte [reg + 3], 0
 
}
 
 
macro add_INET reg {
 
rol ecx, 16
adc byte [reg + 0], ch
adc byte [reg + 1], cl
rol ecx, 16
adc byte [reg + 2], ch
adc byte [reg + 3], cl
 
}
 
 
 
 
;-----------------------------------------------------------------
;
; TCP_init
134,8 → 89,13
rep stosd
 
init_queue TCP_IN_QUEUE
init_queue TCP_OUT_QUEUE
 
; tcp_out_queue is a special type of queue
xor eax, eax
mov esi, TCP_OUT_QUEUE
mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1
rep stosd
 
ret
 
 
165,9 → 125,9
cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP
jne .next_socket
 
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState]
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state]
 
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], 0
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
jne .decrement_tcb
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd
175,10 → 135,10
 
.decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer]
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
jnz .next_socket
 
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
jne .next_socket
 
push [ebx + SOCKET_head.PrevPtr]
231,30 → 191,33
dec [esi + tcp_out_queue_entry.ttl]
jz .send_it
.find_next:
add esi, tcp_out_queue_entry.size
dec eax
jz .exit
jmp .loop
test ecx, ecx
jnz .loop
ret
 
.send_it:
push eax ecx esi
 
mov ebx, [esi + tcp_out_queue_entry.owner]
push [esi + tcp_out_queue_entry.data_size]
push [esi + tcp_out_queue_entry.data_ptr]
mov ebx, [esi + tcp_out_queue_entry.owner]
 
DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
call [esi + tcp_out_queue_entry.sendproc]
 
add esp, 8
pop esi ecx eax
 
dec [esi + tcp_out_queue_entry.retries]
jz .remove_it
mov [esi + tcp_out_queue_entry.ttl], TCP_TIMEOUT
 
mov [esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
jmp .find_next
 
.remove_it:
push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
call kernel_free
jmp .find_next
 
278,6 → 241,8
align 4
TCP_add_to_queue:
 
DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %x\n", [esp], [esp+4], ebx, edx
 
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full
 
291,6 → 256,9
loop .loop
 
.full: ; silently discard the packet
 
DEBUGF 1,"TCP queue is full!\n"
 
call kernel_free
add esp, 4
 
304,9 → 272,13
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES
mov [eax + tcp_out_queue_entry.owner], ebx
mov [eax + tcp_out_queue_entry.sendproc], esi
mov [eax + tcp_out_queue_entry.ack_num], edx
mov [eax + tcp_out_queue_entry.seq_num], edx
 
inc [TCP_OUT_QUEUE]
 
sub eax, TCP_OUT_QUEUE+4
DEBUGF 1,"Added to queue in pos %u\n", eax
 
ret
 
 
332,6 → 304,8
 
DEBUGF 1,"TCP_Handler\n"
 
; TODO: validate checksum
 
; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP OR = 0
; IP Packet TCP Source Port = remote Port OR = 0
358,10 → 332,12
cmp [edx + TCP_Packet.SourcePort] , ax
je .change_state
test ax, ax
jne .socket_loop
jnz .socket_loop
 
.change_state:
 
DEBUGF 1,"Found valid socket for packet\n"
 
push ebx
lea ebx, [ebx + SOCKET_head.lock]
call wait_mutex
373,29 → 349,37
; edx is pointer to tcp packet
 
; as a Packet has been received, update the TCB timer
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], TWOMSL
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL
 
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
test [edx + TCP_Packet.Flags], TH_ACK
jz .call_handler ; No ACK, so no data yet
 
mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax
bswap eax ;
add eax, ecx ;
; mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax
; bswap eax ;
; add eax, ecx ;
 
mov eax, [edx + TCP_Packet.AckNumber]
;---------
 
cmp [TCP_OUT_QUEUE], 0
je .call_handler
push ecx
 
push ecx
DEBUGF 1,"Removing all queued packets with smaller ACK\n"
 
mov ecx, TCP_QUEUE_SIZE
mov esi, TCP_OUT_QUEUE+4
 
.loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0
jne .maybe_next
cmp [esi + tcp_out_queue_entry.ack_num], eax
je .maybe_next
cmp [esi + tcp_out_queue_entry.seq_num], eax
jg .maybe_next
; TODO: check if the packets belong to the same tcp connection !
 
DEBUGF 1,"Removing a queued packet\n"
 
push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
404,25 → 388,24
.maybe_next:
add esi, tcp_out_queue_entry.size
loop .loop
 
pop ecx
 
.call_handler:
; Call handler for given TCB state
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState]
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
DEBUGF 1,"Socket state: %u\n", eax
 
cmp eax, TCB_LISTEN
jb .exit
jb .dump
cmp eax, TCB_CLOSED
ja .exit
ja .dump
 
dec eax
shl eax, 2
add eax, TCBStateHandler - 4
add eax, stateHandler
 
push .exit
jmp eax
call dword[eax]
 
.exit:
mov [ebx + SOCKET_head.lock], 0
 
.dump:
DEBUGF 1,"Dumping TCP packet\n"
call kernel_free
463,7 → 446,7
 
 
push ecx esi eax ; save some variables for later
add ecx, TCP_Packet.Data
add ecx, TCP_Packet.Options
call IPv4_create_packet
cmp edi, -1
je .fail
485,7 → 468,7
mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags]
mov [edi + TCP_Packet.Flags], al
 
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes ;;; TODO: read RFC !
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes
mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0
493,7 → 476,7
; Copy the data
mov esi, [esp]
mov ecx, [esp+4]
add edi, TCP_Packet.Data
add edi, TCP_Packet.Options
 
shr ecx, 1
jnc .nb
519,12 → 502,12
 
; And now, send it!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender
lea esi, [ebx+ETH_DEVICE.transmit]
mov edx, [edi + TCP_Packet.AckNumber]
jmp TCP_add_to_queue
 
.fail:
add esp, 12+4
add esp, 12+12+4
ret
 
 
543,14 → 526,15
align 4
TCP_send_ack:
 
DEBUGF 1,"Creating TCP ACK\n"
DEBUGF 1,"Creating TCP ACK, socket: %x, flags: %x\n",eax, bl
 
mov di , IP_PROTO_TCP
mov cx , TCP_Packet.Data
mov ecx, TCP_Packet.Options
 
push bx eax
 
; Create an IPv4 Packet of the correct size
 
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
564,10 → 548,10
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber]
 
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] ; both ports at once
pop dword [edi + TCP_Packet.SourcePort]
 
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
pop [edi + TCP_Packet.AckNumber]
 
pop cx
575,32 → 559,39
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes
mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0
 
push eax edx
push edx eax
 
push word TCP_Packet.Data shl 8
push IP_PROTO_TCP
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.LocalIP]
lea esi, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
inc_INET esi
 
; Now, calculate the checksum for pseudoheader
; Now, calculate the checksum
pushw TCP_Packet.Options shl 8
pushw IP_PROTO_TCP shl 8
pushd [edi-4] ; destination address
pushd [edi-8] ; source address
 
xor edx, edx
mov ecx, TCP_Packet.Options
mov esi, edi
call checksum_1
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; Now create the final checksum and store it in TCP header
; and store it in TCP header
call checksum_2
mov [edi + TCP_Packet.Checksum], dx
 
; And now, send it!
; And now, send the packet!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender
mov edx, [edi + TCP_Packet.AckNumber]
mov esi, [ebx + ETH_DEVICE.transmit]
mov edx, [edi + TCP_Packet.SequenceNumber]
jmp TCP_add_to_queue
 
.fail:
add esp, 12+4
add esp, 2+4
ret
 
 
609,6 → 600,9
 
align 4
stateTCB_LISTEN:
 
DEBUGF 1,"TCBStateHandler: Listen\n"
 
; In this case, we are expecting a SYN Packet
; For now, if the Packet is a SYN, process it, and send a response
; If not, ignore it
631,11 → 625,13
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax
 
mov [ebx + SOCKET_head.lock], 0
 
; Now construct the response
mov bl, TH_SYN + TH_ACK
call TCP_send_ack
 
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
 
; increment SND.NXT in socket
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
642,11 → 638,15
inc_INET esi
 
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
 
 
align 4
stateTCB_SYN_SENT:
 
DEBUGF 1,"TCBStateHandler: Syn_Sent\n"
 
; We are awaiting an ACK to our SYN, with a SYM
; Look at control flags - expecting an ACK
 
658,28 → 658,31
test al, TH_SYN
jz .exit
 
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED
push TH_SYN + TH_ACK
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
pushd TH_SYN + TH_ACK
jmp .send
 
.syn_ack:
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED
push TH_ACK
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
pushd TH_ACK
 
.send:
; Store the recv.nxt field
mov eax, [edx + TCP_Packet.SequenceNumber]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
bswap eax
inc eax
bswap eax
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax ; Update our recv.nxt field
mov [ebx + SOCKET_head.lock], 0
 
; Update our recv.nxt field
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
 
; Send an ACK
mov eax, ebx
pop ebx
call TCP_send_ack
 
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
 
 
686,6 → 689,9
 
align 4
stateTCB_SYN_RECEIVED:
 
DEBUGF 1,"TCBStateHandler: Syn_received\n"
 
; In this case, we are expecting an ACK Packet
; For now, if the Packet is an ACK, process it,
; If not, ignore it
693,12 → 699,12
test [edx + TCP_Packet.Flags], TH_RST
jz .check_ack
 
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_LISTEN
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
jmp .exit
 
.check_ack:
706,9 → 712,10
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
 
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
 
 
715,6 → 722,10
 
align 4
stateTCB_ESTABLISHED:
 
 
DEBUGF 1,"TCBStateHandler: Established\n"
 
; Here we are expecting data, or a request to close
; OR both...
 
724,6 → 735,7
 
; It was a fin or reset.
 
;;; TODO: write following code:
; Remove resend entries from the queue - I dont want to send any more data
; Send an ACK to that fin, and enter closewait state
 
732,6 → 744,8
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
DEBUGF 1,"Received ACK\n"
 
; First, look at the incoming window. If this is less than or equal to 1024,
; Set the socket window timer to 1. This will stop an additional Packets being queued.
; ** I may need to tweak this value, since I do not know how many Packets are already queued
752,7 → 766,7
; recv seq is in [sktAddr]+56, in inet format
; just do a comparision
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
jne @f
mov ecx, eax
 
763,11 → 777,12
jnz .data
 
; If we had received a fin, we need to ACK it.
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
je .ack
jmp .exit
 
.data:
DEBUGF 1,"Got data!\n"
mov esi, [esp + 4]
sub edx, esi
mov edi, edx
774,10 → 789,14
call socket_internal_receiver
 
.ack:
mov [ebx + SOCKET_head.lock], 0
; Send an ACK
mov eax, ebx
mov bl, TH_ACK
call TCP_send_ack
.exit:
 
mov [ebx + SOCKET_head.lock], 0
ret
 
 
784,6 → 803,9
 
align 4
stateTCB_FIN_WAIT_1:
 
DEBUGF 1,"TCBStateHandler: Fin_wait_1\n"
 
; We can either receive an ACK of a fin, or a fin
mov al, [edx + TCP_Packet.Flags]
and al, TH_FIN + TH_ACK
792,21 → 814,25
jne @f
 
; It was an ACK
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_FIN_WAIT_2
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
jmp .exit
 
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSING
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
cmp al, TH_FIN
je @f
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
 
@@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
 
mov [ebx + SOCKET_head.lock], 0
; Send an ACK
mov eax, ebx
mov bl, TH_ACK
call TCP_send_ack
 
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
 
 
813,20 → 839,27
 
align 4
stateTCB_FIN_WAIT_2:
 
DEBUGF 1,"TCBStateHandler: Fin_wait_2\n"
 
test [edx + TCP_Packet.Flags], TH_FIN
jz .exit
 
; Change state, as we have a fin
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
 
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi
 
mov [ebx + SOCKET_head.lock], 0
 
; Send an ACK
mov eax, ebx
mov bl, TH_ACK
call TCP_send_ack
 
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
 
 
833,8 → 866,12
 
align 4
stateTCB_CLOSE_WAIT:
 
DEBUGF 1,"TCBStateHandler: close_wait\n"
; Intentionally left empty
; socket_close_tcp handles this
 
mov [ebx + SOCKET_head.lock], 0
ret
 
 
841,22 → 878,32
 
align 4
stateTCB_CLOSING:
 
DEBUGF 1,"TCBStateHandler: closingn\n"
 
; We can either receive an ACK of a fin, or a fin
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
 
.exit:
 
mov [ebx + SOCKET_head.lock], 0
ret
 
 
align 4
stateTCB_LAST_ACK:
 
DEBUGF 1,"TCBStateHandler: last_ackn\n"
 
; Look at control flags - expecting an ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET_head.lock], 0
 
; delete the socket
stdcall net_socket_free, ebx
 
866,13 → 913,60
 
align 4
stateTCB_TIME_WAIT:
 
DEBUGF 1,"TCBStateHandler: time_wait\n"
 
mov [ebx + SOCKET_head.lock], 0
 
ret
 
 
align 4
stateTCB_CLOSED:
 
DEBUGF 1,"TCBStateHandler: closed\n"
 
mov [ebx + SOCKET_head.lock], 0
 
ret
 
 
 
;---------------------------------------------------------------------------
;
; TCP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
 
align 4
TCP_API:
 
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
add eax, TCP_PACKETS_TX
mov eax, [eax]
ret
 
.packets_rx:
add eax, TCP_PACKETS_RX
mov eax, [eax]
ret