More TCP code updates for net branch, code is still very unstable

git-svn-id: svn://kolibrios.org@1318 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2009-12-13 14:55:42 +00:00
parent ddfdcfa285
commit 0e0b5fb665
6 changed files with 537 additions and 202 deletions

View File

@ -29,10 +29,10 @@ start:
push 1 push 1
call [con_start] call [con_start]
push title push title
push -1 push 25
push -1 push 80
push -1 push 25
push -1 push 80
call [con_init] call [con_init]
; main loop ; main loop
push str1 push str1
@ -102,7 +102,11 @@ main:
mcall 40, 1 shl 7 ; + 7 mcall 40, 1 shl 7 ; + 7
call [con_cls] call [con_cls]
mcall 18, 7
push eax
mcall 51, 1, thread, mem - 2048 mcall 51, 1, thread, mem - 2048
pop ecx
mcall 18, 3
mainloop: mainloop:
mcall 10 mcall 10
@ -115,13 +119,25 @@ mainloop:
mov byte [esi + eax], 0 mov byte [esi + eax], 0
@@: @@:
cmp byte [esi], 0xff ; 'IAC' = Interpret As Command cmp byte [esi], 0xff ; Interpret As Command
jne @f jne @f
; TODO: parse options, for now, we will reply with 'WONT' to everything ; TODO: parse options, for now, we will reply with 'WONT' to everything
mov byte [esi + 1], 252 ; WONT mov byte [esi + 1], 252 ; WONT
add esi, 3 ; a command is always 3 bytes add esi, 3 ; a command is always 3 bytes
jmp @r jmp @r
@@:
cmp byte [esi], 0x1b ; escape character
jne @f
cmp word [esi+1], 0x485b ; move cursor to beginning
jne @f
push 0
push 0
call [con_set_cursor_pos]
add esi, 3
@@: @@:
push esi push esi
@ -160,14 +176,15 @@ exit:
thread: thread:
mcall 40, 0 mcall 40, 0
.loop:
call [con_getch2] call [con_getch2]
mov byte [send_data], al mov byte [send_data], al
mcall send, [socketnum], send_data, 1 mcall send, [socketnum], send_data, 1
jmp thread jmp .loop
; data ; data
title db 'Telnet',0 title db 'Telnet',0
str1 db 'Telnet v0.1',10,' for KolibriOS # 1250 or later. ',10,10,0 str1 db 'Telnet v0.1',10,' for KolibriOS # 1281 or later. ',10,10,'If you dont know where to connect to, try towel.blinkenlights.nl',10,10,0
str2 db '> ',0 str2 db '> ',0
str3 db 'Connecting to: ',0 str3 db 'Connecting to: ',0
str4 db 10,0 str4 db 10,0
@ -199,7 +216,8 @@ import console, \
con_exit, 'con_exit', \ con_exit, 'con_exit', \
con_gets, 'con_gets',\ con_gets, 'con_gets',\
con_cls, 'con_cls',\ con_cls, 'con_cls',\
con_getch2, 'con_getch2' con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
i_end: i_end:
socketnum dd ? socketnum dd ?

View File

@ -212,7 +212,7 @@ endp
align 4 align 4
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -220,13 +220,13 @@ proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
mov bh, byte [devfn] mov bh, byte [devfn]
mov bl, byte [reg] mov bl, byte [reg]
call pci_read_reg call pci_read_reg
pop ebx pop edx ebx
ret ret
endp endp
align 4 align 4
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -234,13 +234,13 @@ proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
mov bh, byte [devfn] mov bh, byte [devfn]
mov bl, byte [reg] mov bl, byte [reg]
call pci_read_reg call pci_read_reg
pop ebx pop edx ebx
ret ret
endp endp
align 4 align 4
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -248,13 +248,13 @@ proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
mov bh, byte [devfn] mov bh, byte [devfn]
mov bl, byte [reg] mov bl, byte [reg]
call pci_read_reg call pci_read_reg
pop ebx pop edx ebx
ret ret
endp endp
align 4 align 4
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -263,13 +263,13 @@ proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
mov bl, byte [reg] mov bl, byte [reg]
mov ecx, [val] mov ecx, [val]
call pci_write_reg call pci_write_reg
pop ebx pop edx ebx
ret ret
endp endp
align 4 align 4
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -278,13 +278,13 @@ proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
mov bl, byte [reg] mov bl, byte [reg]
mov ecx, [val] mov ecx, [val]
call pci_write_reg call pci_write_reg
pop ebx pop edx ebx
ret ret
endp endp
align 4 align 4
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx push ebx edx
xor eax, eax xor eax, eax
xor ebx, ebx xor ebx, ebx
mov ah, byte [bus] mov ah, byte [bus]
@ -293,7 +293,7 @@ proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
mov bl, byte [reg] mov bl, byte [reg]
mov ecx, [val] mov ecx, [val]
call pci_write_reg call pci_write_reg
pop ebx pop edx ebx
ret ret
endp endp

View File

@ -286,8 +286,9 @@ debug_beginf
.l3: ret .l3: ret
debug_endf debug_endf
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF' __fdo_hexdigits db '0123456789ABCDEF'
debug_func fdo_debug_outhex
debug_beginf debug_beginf
mov cl,dl mov cl,dl
neg cl neg cl

View File

@ -24,6 +24,7 @@ struct SOCKET_head
.Type dd ? ; RAW/UDP/TCP/... .Type dd ? ; RAW/UDP/TCP/...
.Protocol dd ? ; ICMP/IPv4/ARP/ .Protocol dd ? ; ICMP/IPv4/ARP/
.lock dd ? ; lock mutex .lock dd ? ; lock mutex
.errorcode dd ?
.end: .end:
ends ends
@ -55,6 +56,7 @@ struct TCP_SOCKET
; Transmission control block ; Transmission control block
.state dd ? ; TCB state .state dd ? ; TCB state
.timer dd ? ; TCB timer (seconds) .timer dd ? ; TCB timer (seconds)
.ISS dd ? ; initial send sequence number .ISS dd ? ; initial send sequence number
.IRS dd ? ; initial receive sequence number .IRS dd ? ; initial receive sequence number
.SND_UNA dd ? ; sequence number of unack'ed sent Packets .SND_UNA dd ? ; sequence number of unack'ed sent Packets
@ -191,11 +193,31 @@ socket_open:
mov [eax + SOCKET_head.Type], edx mov [eax + SOCKET_head.Type], edx
mov [eax + SOCKET_head.Protocol], esi mov [eax + SOCKET_head.Protocol], esi
cmp ecx, AF_INET4
je .af_inet4
jmp .done
.af_inet4:
cmp edx, IP_PROTO_TCP
je .tcp
jmp .done
.tcp:
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
pseudo_random ebx
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS], ebx
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ebx
.done:
stdcall net_socket_addr_to_num, eax stdcall net_socket_addr_to_num, eax
DEBUGF 1,", socketnumber: %u\n", eax DEBUGF 1,", socketnumber: %u\n", eax
; TODO: if it is a tcp socket, set state to TCB_CLOSED
mov [esp+32], eax mov [esp+32], eax
ret ret
@ -513,27 +535,42 @@ socket_close:
ret ret
.tcp: .tcp:
mov dword [esp+32],0
; first, remove all resend entries for this socket ; first, remove all resend entries for this socket
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN call TCP_remove_socket
je .destroy_tcb
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
je .destroy_tcb
; Send a fin, then enter finwait2 state ; cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
; je .destroy_tcb
; cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
; je .destroy_tcb
; cmp [eac + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
; je .destroy_tcb
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
je .fin_wait
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
je .fin_wait
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
je .last_ack
stdcall net_socket_free, ebx
ret
.last_ack:
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK
jmp .send_fin
.fin_wait:
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1 mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1
mov bl, TH_FIN .send_fin:
mov bl, TH_FIN + TH_ACK
xor ecx, ecx xor ecx, ecx
; call TCP_send call TCP_send
;;;;;
.destroy_tcb:
stdcall net_socket_free, eax
mov dword [esp+32],0
ret ret

View File

@ -97,6 +97,23 @@ macro add_INET reg {
rol ecx, 16 rol ecx, 16
} }
macro pseudo_random reg {
add reg, [esp]
rol reg, 5
xor reg, [timer_ticks]
imul reg, 214013
xor reg, 0xdeadbeef
rol reg, 9
pushd reg
mov word [esp], 0x8080 ; kernel heap start addr (os_stack)
xor reg, [esp]
add esp, 4
}
include "queue.inc" include "queue.inc"
include "ARP.inc" include "ARP.inc"
include "IPv4.inc" include "IPv4.inc"
@ -152,7 +169,7 @@ stack_handler:
cmp [ETH_RUNNING], 0 cmp [ETH_RUNNING], 0
je .exit je .exit
; Test for 1/100 s (10ms) tick ; Test for 10ms tick
mov eax, [timer_ticks] mov eax, [timer_ticks]
cmp eax, [last_1hsTick] cmp eax, [last_1hsTick]
je .exit je .exit

View File

@ -8,6 +8,7 @@
;; Part of the tcp/ip network stack for KolibriOS ;; ;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;; ;; ;;
;; Written by hidnplayr@kolibrios.org ;; ;; Written by hidnplayr@kolibrios.org ;;
;; Inspired by the TCP code of Mike Hibbit for MenuetOS ;;
;; ;; ;; ;;
;; GNU GENERAL PUBLIC LICENSE ;; ;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;; ;; Version 2, June 1991 ;;
@ -22,6 +23,8 @@ 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_SOCKET_TTL equ 10 ; # of secs to wait before closing socket
TCP_QUEUE_SIZE equ 16 TCP_QUEUE_SIZE equ 16
TCP_MAX_ACKS equ 16
struct TCP_Packet struct TCP_Packet
.SourcePort dw ? .SourcePort dw ?
@ -63,13 +66,16 @@ uglobal
TCP_PACKETS_RX rd MAX_IP TCP_PACKETS_RX rd MAX_IP
TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4 TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
TCP_OUT_QUEUE dd ? TCP_OUT_QUEUE dd ?, ?
rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4 rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
TCP_ACKS dd ?
TCP_ACK_LIST rd 3*TCP_MAX_ACKS
endg endg
align 4 align 4
iglobal iglobal
stateHandler: TCPstateHandler:
dd stateTCB_LISTEN dd stateTCB_LISTEN
dd stateTCB_SYN_SENT dd stateTCB_SYN_SENT
@ -114,7 +120,7 @@ TCP_init:
xor eax, eax xor eax, eax
mov esi, TCP_OUT_QUEUE mov esi, TCP_OUT_QUEUE
mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1 mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+2+2+3*TCP_MAX_ACKS
rep stosd rep stosd
ret ret
@ -193,9 +199,12 @@ TCP_send_queued:
cmp [TCP_OUT_QUEUE], 0 cmp [TCP_OUT_QUEUE], 0
je .exit je .exit
mov ebx, TCP_OUT_QUEUE+4
call wait_mutex
mov eax, TCP_QUEUE_SIZE mov eax, TCP_QUEUE_SIZE
mov ecx, [TCP_OUT_QUEUE] mov ecx, [TCP_OUT_QUEUE]
mov esi, TCP_OUT_QUEUE+4 mov esi, TCP_OUT_QUEUE+8
.loop: .loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0 cmp [esi + tcp_out_queue_entry.data_ptr], 0
@ -203,30 +212,33 @@ TCP_send_queued:
add esi, tcp_out_queue_entry.size add esi, tcp_out_queue_entry.size
loop .loop loop .loop
.exit: .exit:
mov [TCP_OUT_QUEUE+4], 0
ret ret
.found_one: .found_one:
dec [esi + tcp_out_queue_entry.ttl] dec [esi + tcp_out_queue_entry.ttl]
jz .send_it jz .send_it
cmp [esi + tcp_out_queue_entry.data_ptr], -1
jz .is_ack
.find_next: .find_next:
add esi, tcp_out_queue_entry.size add esi, tcp_out_queue_entry.size
dec eax dec eax
jz .exit jz .exit
test ecx, ecx test ecx, ecx
jnz .loop jnz .loop
mov [TCP_OUT_QUEUE+4], 0
ret ret
.send_it: .send_it:
push eax ecx esi pusha
mov ebx, [esi + tcp_out_queue_entry.owner] mov ebx, [esi + tcp_out_queue_entry.owner]
push [esi + tcp_out_queue_entry.data_size] pushd [esi + tcp_out_queue_entry.data_size]
push [esi + tcp_out_queue_entry.data_ptr] pushd [esi + tcp_out_queue_entry.data_ptr]
DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc] DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
inc [TCP_PACKETS_TX] inc [TCP_PACKETS_TX]
call [esi + tcp_out_queue_entry.sendproc] call [esi + tcp_out_queue_entry.sendproc]
add esp, 8 add esp, 8
pop esi ecx eax popa
dec [esi + tcp_out_queue_entry.retries] dec [esi + tcp_out_queue_entry.retries]
jz .remove_it jz .remove_it
@ -241,6 +253,17 @@ TCP_send_queued:
dec [TCP_OUT_QUEUE] dec [TCP_OUT_QUEUE]
jmp .find_next jmp .find_next
.is_ack:
pusha
mov eax, [esi + tcp_out_queue_entry.socket]
mov ebx, [esi + tcp_out_queue_entry.owner]
mov ecx, [esi + tcp_out_queue_entry.size]
call TCP_send_ack
popa
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
jmp .find_next
;----------------------------------------------------------------- ;-----------------------------------------------------------------
@ -266,9 +289,11 @@ TCP_handler :
; TODO: validate checksum ; TODO: validate checksum
; Find a matching socket for received packet, all following expressions must be valid:
;
; IP Packet TCP Destination Port = local Port ; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP OR = 0 ; (IP Packet SA = Remote IP) OR (Remote IP = 0)
; IP Packet TCP Source Port = remote Port OR = 0 ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
mov ebx, net_sockets mov ebx, net_sockets
@ -318,27 +343,30 @@ TCP_handler :
; ecx is size of tcp data ; ecx is size of tcp data
; as a Packet has been received, update the TCB timer ; as a Packet has been received, update the TCB timer
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 ; 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 test [edx + TCP_Packet.Flags], TH_ACK
jz .no_ack ; No ACK, so no data yet jz .no_ack ; No ACK, so no data yet
; Calculate ACK number ; Calculate ACK number, in intel byte order
mov edi, [edx + TCP_Packet.AckNumber] mov edi, [edx + TCP_Packet.AckNumber]
bswap edi bswap edi
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi
DEBUGF 1,"Setting last_ack_number to %u\n", edi DEBUGF 1,"Setting last_ack_number to %u\n", edi
bswap edi
; Dequeue all acknowledged packets ; Dequeue all acknowledged packets
cmp [TCP_OUT_QUEUE], 0 ; first, check if any packets are queued at all cmp [TCP_OUT_QUEUE], 0 ; first, check if any packets are queued at all
je .no_ack je .no_ack
push ebx
mov ebx, TCP_OUT_QUEUE+4
call wait_mutex
pop ebx
push ecx push ecx
DEBUGF 1,"Removing all queued packets with smaller ACK\n" DEBUGF 1,"Removing all queued packets with smaller ACK\n"
mov ecx, TCP_QUEUE_SIZE mov ecx, TCP_QUEUE_SIZE
mov esi, TCP_OUT_QUEUE+4 mov esi, TCP_OUT_QUEUE+8
.loop: .loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0 cmp [esi + tcp_out_queue_entry.data_ptr], 0
je .maybe_next je .maybe_next
@ -359,8 +387,9 @@ TCP_handler :
.maybe_next: .maybe_next:
add esi, tcp_out_queue_entry.size add esi, tcp_out_queue_entry.size
loop .loop loop .loop
pop ecx
mov [TCP_OUT_QUEUE+4], 0
pop ecx
; Now call the correct handler, depending on the socket state ; Now call the correct handler, depending on the socket state
.no_ack: .no_ack:
@ -371,11 +400,7 @@ TCP_handler :
cmp eax, TCB_CLOSED cmp eax, TCB_CLOSED
ja .dump ja .dump
dec eax call dword [TCPstateHandler+eax*4-4]
shl eax, 2
add eax, stateHandler
call dword[eax]
.dump: .dump:
DEBUGF 1,"Dumping TCP packet\n" DEBUGF 1,"Dumping TCP packet\n"
@ -465,13 +490,11 @@ TCP_send:
xchg cl, ch xchg cl, ch
pushw cx pushw cx
xchg cl, ch xchg cl, ch
;; pushw TCP_Packet.Data shl 8
pushw IP_PROTO_TCP shl 8 pushw IP_PROTO_TCP shl 8
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
pushd [edi-8] ; source address pushd [edi-8] ; source address
xor edx, edx xor edx, edx
; mov ecx, TCP_Packet.Data
mov esi, edi mov esi, edi
call checksum_1 call checksum_1
mov ecx, 12 mov ecx, 12
@ -496,14 +519,13 @@ TCP_send:
and ecx, 0x0000ffff and ecx, 0x0000ffff
xchg cl, ch xchg cl, ch
sub cx, TCP_Packet.Data sub cx, TCP_Packet.Data
add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)
add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) ; todo: this should only happen when packet was queued successful
mov ecx, TCP_RETRIES mov ecx, TCP_RETRIES
jmp .go_for_it jmp .go_for_it
.only_one: .only_one:
; inc_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)
mov ecx, 1 mov ecx, 1
.go_for_it: .go_for_it:
@ -523,37 +545,37 @@ TCP_send:
; IN: [esp] pointer to buffer ; IN: [esp] pointer to buffer
; [esp + 4] size of buffer ; [esp + 4] size of buffer
; ebx = driver struct ; ebx = driver struct
; edx = sequence number of this packet in intel byte order
; esi = sender proc ; esi = sender proc
; edx = sequence number of this packet in normal byte order
; edi = socket number ; edi = socket number
; ecx = retries
; OUT: / ; OUT: /
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
TCP_queue: TCP_queue:
bswap edx
DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx
bswap edx
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full jge .full
push ecx push ebx
mov ecx, TCP_QUEUE_SIZE mov ebx, TCP_OUT_QUEUE+4
mov eax, TCP_OUT_QUEUE+4 call wait_mutex
pop ebx
mov ecx, TCP_QUEUE_SIZE
mov eax, TCP_OUT_QUEUE+8
.loop: .loop:
cmp [eax + tcp_out_queue_entry.data_ptr], 0 cmp [eax + tcp_out_queue_entry.data_ptr], 0
je .found_it je .found_it
add eax, tcp_out_queue_entry.size add eax, tcp_out_queue_entry.size
loop .loop loop .loop
add esp, 4
.full: ; silently discard the packet .full: ; silently discard the packet
DEBUGF 1,"TCP queue is full!\n" DEBUGF 1,"TCP queue is full!\n"
add esp, 4
call kernel_free call kernel_free
add esp, 4 add esp, 4
@ -561,7 +583,7 @@ TCP_queue:
.found_it: ; eax points to empty queue entry .found_it: ; eax points to empty queue entry
pop [eax + tcp_out_queue_entry.retries] mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES
pop [eax + tcp_out_queue_entry.data_ptr] pop [eax + tcp_out_queue_entry.data_ptr]
pop [eax + tcp_out_queue_entry.data_size] pop [eax + tcp_out_queue_entry.data_size]
mov [eax + tcp_out_queue_entry.ttl], 1 ; send immediately mov [eax + tcp_out_queue_entry.ttl], 1 ; send immediately
@ -572,9 +594,179 @@ TCP_queue:
inc [TCP_OUT_QUEUE] inc [TCP_OUT_QUEUE]
sub eax, TCP_OUT_QUEUE+4 sub eax, TCP_OUT_QUEUE+8
DEBUGF 1,"Added to queue in pos %u\n", eax shr eax, 5
DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
mov [TCP_OUT_QUEUE+4], 0
ret
;-----------------------------------------------------------------
;
; IN: ebx = socket
; ecx = ack number
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
TCP_queue_ack:
DEBUGF 1,"Adding ACK to TCP queue, socket: %x, acknum: %u\n", ebx, ecx
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full
push ebx ecx
mov ebx, TCP_OUT_QUEUE+4
call wait_mutex
mov ecx, TCP_QUEUE_SIZE
mov eax, TCP_OUT_QUEUE+8
.loop:
cmp [eax + tcp_out_queue_entry.data_ptr], 0
je .found_it
add eax, tcp_out_queue_entry.size
loop .loop
add esp, 8
.full: ; silently discard the packet
DEBUGF 1,"TCP queue is full!\n"
ret
.found_it: ; eax points to empty queue entry
pop [eax + tcp_out_queue_entry.data_size] ; ACK number
mov [eax + tcp_out_queue_entry.data_ptr], -1 ; ACK packet
pop [eax + tcp_out_queue_entry.socket]
mov [eax + tcp_out_queue_entry.retries], 1
mov [eax + tcp_out_queue_entry.ttl], 20 ; 200 ms
inc [TCP_OUT_QUEUE]
sub eax, TCP_OUT_QUEUE+8
shr eax, 5
DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
mov [TCP_OUT_QUEUE+4], 0
ret
; IN: eax = socket pointer
; ebx = device structure
; ecx = ack number
align 4
TCP_send_ack:
DEBUGF 1,"Creating TCP ACK packet, socket: %x, acknum: %x\n", eax, ecx
push ecx eax
mov di , IP_PROTO_TCP
mov ecx, TCP_Packet.Data
; 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]
call IPv4_create_packet
cmp edi, -1
je .fail
pop ecx
; fill in tcp sequence number
push [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber]
; Fill in local and remote ports
push dword [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
pop dword [edi + TCP_Packet.SourcePort]
; Acknumber
pop [edi + TCP_Packet.AckNumber]
; Fill in other tcp options
mov [edi + TCP_Packet.Flags], TH_ACK
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 pointer to and size of total packet (needed for send procedure)
push edx eax esi
; Now, calculate the checksum
pushw TCP_Packet.Data shl 8
pushw IP_PROTO_TCP shl 8
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
pushd [edi-8] ; source address
xor edx, edx
mov ecx, 12
mov esi, esp
call checksum_1
call checksum_2
mov [edi + TCP_Packet.Checksum], dx
add esp, 12 ; remove the pseudoheader from stack
pop eax
call eax
call kernel_free
add esp, 4 ; pop (balance stack)
ret
.fail:
add esp, 8
ret
;-----------------------------------------------------------------
;
; Remove all queued TCP packets for a specified socket
;
; IN: eax = socket number
; OUT: /
;
; destoys esi and ecx
;
;-----------------------------------------------------------------
align 4
TCP_remove_socket:
cmp [TCP_OUT_QUEUE], 0
je .skip
mov ebx, TCP_OUT_QUEUE+4
call wait_mutex
mov eax, TCP_QUEUE_SIZE
mov ecx, [TCP_OUT_QUEUE]
mov esi, TCP_OUT_QUEUE+8
.loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0
jz .maybenext
cmp [esi + tcp_out_queue_entry.socket], eax
jnz .maybenext
push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
call kernel_free
.maybenext:
add esi, tcp_out_queue_entry.size
loop .loop
mov [TCP_OUT_QUEUE+4], 0
.skip:
ret ret
@ -737,6 +929,90 @@ stateTCB_SYN_RECEIVED:
ret ret
if 0
align 4
stateTCB_ESTABLISHED:
DEBUGF 1,"TCBStateHandler: Established\n"
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
bswap eax
DEBUGF 1,"RCV_NXT is set to:%u\n", eax
bswap eax
cmp eax, [edx + TCP_Packet.SequenceNumber]
jne .exit ;;;;;;
; check if we received an ACK
test [edx + TCP_Packet.Flags], TH_ACK
jz .no_ack
mov ax, [edx + TCP_Packet.Window]
xchg al, ah
cmp ax, 1024
ja @f
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
@@:
.no_ack:
; Now, see if we received any data
test ecx, ecx
jz .nodata
; Calculate next sequencenumber
add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
push edx
DEBUGF 1,"Got %u bytes data!\n", ecx
; calculate header length
movzx eax, [edx + TCP_Packet.DataOffset]
and eax, 11110000b
shr eax, 2
DEBUGF 1,"TCP header size: %u\n", eax
add edx, eax ; now edx points to data
add esp, 4
pop esi ; pointer to buffer
add esp, 4
sub edx, esi
mov edi, edx ; offset
mov eax, ebx ; socket ptr
call socket_internal_receiver ; Place the data from packet into socket
; lea ebx, [eax + SOCKET_head.lock]
; call wait_mutex
mov ebx, eax
pop edx
test [edx + TCP_Packet.Flags], TH_FIN + TH_RST
jz .ack
.nodata:
test [edx + TCP_Packet.Flags], TH_FIN + TH_RST
jz .exit
; Send an ACK to that fin, and enter closewait state
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
; Remove all resend entries from the queue
mov eax, ebx
call TCP_remove_socket
.ack:
push ebx
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
call TCP_queue_ack
pop ebx
.exit:
mov [ebx + SOCKET_head.lock], 0
ret
end if
align 4 align 4
stateTCB_ESTABLISHED: stateTCB_ESTABLISHED:
@ -751,13 +1027,9 @@ stateTCB_ESTABLISHED:
jne .exit jne .exit
; Calculate next sequencenumber ; Calculate next sequencenumber
;; test ecx, ecx
;; jnz @f
;; inc ecx
;; @@:
add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT) add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
test [edx + TCP_Packet.Flags], TH_FIN + TH_RST ;;; test [edx + TCP_Packet.Flags], TH_FIN + TH_RST
jnz .fin jnz .fin
.check_ack: .check_ack:
@ -799,9 +1071,9 @@ stateTCB_ESTABLISHED:
call socket_internal_receiver ; Place the data from packet into socket call socket_internal_receiver ; Place the data from packet into socket
lea ebx, [eax + SOCKET_head.lock] ;;;;; lea ebx, [eax + SOCKET_head.lock]
call wait_mutex ;;;;; call wait_mutex
mov ebx, eax ;;;; mov ebx, eax
.ack: .ack:
mov eax, ebx mov eax, ebx
@ -814,7 +1086,7 @@ stateTCB_ESTABLISHED:
mov [ebx + SOCKET_head.lock], 0 mov [ebx + SOCKET_head.lock], 0
ret ret
.fin: .fin: ; we received a FIN or RESET
; Remove all resend entries from the queue ; Remove all resend entries from the queue
mov ecx, TCP_QUEUE_SIZE mov ecx, TCP_QUEUE_SIZE
mov esi, TCP_OUT_QUEUE+4 mov esi, TCP_OUT_QUEUE+4
@ -837,11 +1109,10 @@ stateTCB_ESTABLISHED:
loop .removeloop loop .removeloop
; Send an ACK to that fin, and enter closewait state ; Send an ACK to that fin, and enter closewait state
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
jmp .check_ack jmp .check_ack
align 4 align 4
stateTCB_FIN_WAIT_1: stateTCB_FIN_WAIT_1:
@ -864,10 +1135,6 @@ stateTCB_FIN_WAIT_1:
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], 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
; Send an ACK ; Send an ACK
mov eax, ebx mov eax, ebx
mov bl, TH_ACK mov bl, TH_ACK
@ -893,11 +1160,6 @@ stateTCB_FIN_WAIT_2:
; Change state, as we have a fin ; Change state, as we have a fin
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], 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 ; Send an ACK
mov eax, ebx mov eax, ebx
mov bl, TH_ACK mov bl, TH_ACK