changes in Net Branch: further development of TCP code

git-svn-id: svn://kolibrios.org@1281 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2009-11-22 17:25:31 +00:00
parent d75cb497f8
commit c14545104d
2 changed files with 74 additions and 55 deletions

View File

@ -334,6 +334,8 @@ socket_connect:
.tcp: .tcp:
; TODO: set sequence number to random value ; TODO: set sequence number to random value
lea ebx, [eax + SOCKET_head.lock]
call wait_mutex
; fill in remote port and IP ; fill in remote port and IP
@ -518,35 +520,16 @@ socket_close:
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
je .destroy_tcb je .destroy_tcb
; Now construct the response, and queue for sending by IP
mov bl, TH_FIN
xor ecx, ecx
call TCP_send
; increament SND.NXT in socket
lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
inc_INET esi
; Get the socket state
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
je .fin_wait_1
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
je .fin_wait_1
; assume CLOSE WAIT
; Send a fin, then enter last-ack state
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK
jmp .send
.fin_wait_1:
; Send a fin, then enter finwait2 state ; Send a fin, then enter finwait2 state
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
.send: mov bl, TH_FIN
xor ecx, ecx
; call TCP_send
;;;;; ;;;;;
.destroy_tcb: .destroy_tcb:
stdcall net_socket_free, eax stdcall net_socket_free, eax
@ -571,32 +554,34 @@ socket_close:
align 4 align 4
socket_recv: socket_recv:
DEBUGF 1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi DEBUGF 1,"Socket_receive: socknum: %u bufaddr: %x, buflength: %u, flags: %x\n",ecx,edx,esi,edi
stdcall net_socket_num_to_addr, ecx ; get real socket address stdcall net_socket_num_to_addr, ecx ; get real socket address
or eax, eax or eax, eax
jz s_error jz s_error
mov ebx, esi
DEBUGF 1,"Socket pointer: %x\n", eax DEBUGF 1,"Socket pointer: %x\n", eax
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error ; destroys esi and ecx
mov edi, edx mov edi, edx ; addr to buffer
mov ecx, [esi + socket_queue_entry.data_size] mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF 1,"Got %u bytes of data\n", ecx DEBUGF 1,"Got %u bytes of data\n", ecx
cmp ecx, edx cmp ecx, ebx
jle .large_enough jle .large_enough
DEBUGF 1,"Buffer too small...\n" DEBUGF 1,"Buffer too small...\n"
jmp s_error jmp s_error
.large_enough: .large_enough:
push [esi + socket_queue_entry.data_ptr] push [esi + socket_queue_entry.data_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.offset] mov esi, [esi + socket_queue_entry.offset]
add esi, [esp] add esi, [esp] ; calculate the real data offset
DEBUGF 1,"Source buffer: %x, real addr: %x\n", [esp], esi DEBUGF 1,"Source buffer: %x, real addr: %x\n", [esp], esi
mov dword[esp+32+4], ecx ; return number of bytes copied mov dword[esp+32+4], ecx ; return number of bytes copied
shr ecx, 1 shr ecx, 1
jnc .nb jnc .nb
@ -609,7 +594,7 @@ socket_recv:
rep movsd rep movsd
.nd: .nd:
call kernel_free call kernel_free ; todo: check if ALL applications had the chance to receive data
ret ret
@ -696,7 +681,7 @@ socket_send:
mov ecx, esi mov ecx, esi
mov esi, edx mov esi, edx
xor bl , bl mov bl, TH_PUSH + TH_ACK
call TCP_send call TCP_send

View File

@ -41,7 +41,7 @@ ends
struct tcp_in_queue_entry struct tcp_in_queue_entry
.data_ptr dd ? .data_ptr dd ?
.data_size dd ? .data_size dd ?
.offset dd ? .offset dd ? ; TODO: replace this in code by absolute address isntead of relative offset
.size: .size:
ends ends
@ -238,6 +238,7 @@ TCP_send_queued:
push [esi + tcp_out_queue_entry.data_ptr] push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0 mov [esi + tcp_out_queue_entry.data_ptr], 0
call kernel_free call kernel_free
dec [TCP_OUT_QUEUE]
jmp .find_next jmp .find_next
@ -391,7 +392,7 @@ TCP_handler :
; ;
; IN: eax = socket pointer ; IN: eax = socket pointer
; bl = flags ; bl = flags
; ecx = number of bytes to send, may be set to 0 ; ecx = number of bytes to send, may be set to 0 (single ACK)
; esi = pointer to data ; esi = pointer to data
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
@ -403,7 +404,7 @@ TCP_send:
mov di , IP_PROTO_TCP mov di , IP_PROTO_TCP
add ecx, TCP_Packet.Data add ecx, TCP_Packet.Data
push bx eax esi push ecx bx eax esi
; Create an IPv4 Packet of the correct size ; Create an IPv4 Packet of the correct size
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
@ -436,7 +437,6 @@ TCP_send:
; fill in tcp sequence number ; fill in tcp sequence number
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber] pop [edi + TCP_Packet.SequenceNumber]
inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) ;;;;;;;;
; Fill in local and remote ports ; Fill in local and remote ports
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
@ -454,37 +454,61 @@ TCP_send:
mov [edi + TCP_Packet.DataOffset], 0x50 mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0 mov [edi + TCP_Packet.Checksum], 0
; Get size of total packet back in ecx
pop ecx
; Push pointer to and size of total packet (needed for send procedure) ; Push pointer to and size of total packet (needed for send procedure)
push edx eax push edx eax
; push socket number (for TCP_add_to_queue) ; push socket number (for TCP_add_to_queue)
push esi push esi
; Now, calculate the checksum ; TODO: calculate correct checksum for packets with data ; Now, calculate the checksum
pushw TCP_Packet.Data shl 8 xchg cl, ch
pushw cx
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 ecx, TCP_Packet.Data
mov esi, edi mov esi, edi
call checksum_1 call checksum_1
mov ecx, 12 mov ecx, 12
mov esi, esp mov esi, esp
call checksum_1 call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; and store it in TCP header ; and store it in TCP header
call checksum_2 call checksum_2
mov [edi + TCP_Packet.Checksum], dx mov [edi + TCP_Packet.Checksum], dx
add esp, 10 ; remove the pseudoheader from stack
; At last send the packet!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov edx, [edi + TCP_Packet.SequenceNumber] mov edx, [edi + TCP_Packet.SequenceNumber]
bswap edx bswap edx
mov esi, [ebx + ETH_DEVICE.transmit] mov esi, [ebx + ETH_DEVICE.transmit]
pop cx ; get the length from packet, back from pseudoheader
pop edi pop edi
jmp TCP_queue
cmp cx, TCP_Packet.Data shl 8 ; if the packet has no data
je .only_one ; send it only once
and ecx, 0x0000ffff
xchg cl, ch
sub cx, TCP_Packet.Data
add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)
mov ecx, TCP_RETRIES
jmp .go_for_it
.only_one:
; inc_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)
mov ecx, 1
.go_for_it:
mov [edi + SOCKET_head.lock], 0
jmp TCP_queue ; At last send the packet!
.fail: .fail:
add esp, 2+4 add esp, 2+4
@ -502,6 +526,7 @@ TCP_send:
; esi = sender proc ; esi = sender proc
; edx = sequence number of this packet in normal byte order ; edx = sequence number of this packet in normal byte order
; edi = socket number ; edi = socket number
; ecx = retries
; OUT: / ; OUT: /
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
@ -515,6 +540,7 @@ TCP_queue:
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full jge .full
push ecx
mov ecx, TCP_QUEUE_SIZE mov ecx, TCP_QUEUE_SIZE
mov eax, TCP_OUT_QUEUE+4 mov eax, TCP_OUT_QUEUE+4
@ -527,6 +553,7 @@ TCP_queue:
.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
@ -534,10 +561,10 @@ 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]
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
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES
mov [eax + tcp_out_queue_entry.owner], ebx mov [eax + tcp_out_queue_entry.owner], ebx
mov [eax + tcp_out_queue_entry.sendproc], esi mov [eax + tcp_out_queue_entry.sendproc], esi
mov [eax + tcp_out_queue_entry.seq_num], edx mov [eax + tcp_out_queue_entry.seq_num], edx
@ -724,13 +751,13 @@ stateTCB_ESTABLISHED:
jne .exit jne .exit
; Calculate next sequencenumber ; Calculate next sequencenumber
test ecx, ecx ;; test ecx, ecx
jnz @f ;; jnz @f
inc ecx ;; 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 test [edx + TCP_Packet.Flags], TH_FIN + TH_RST ;;;
jnz .fin jnz .fin
.check_ack: .check_ack:
@ -752,7 +779,7 @@ stateTCB_ESTABLISHED:
; Now, see if we received any data ; Now, see if we received any data
test ecx, ecx test ecx, ecx
jz .ack jz .exit
DEBUGF 1,"Got %u bytes data!\n", ecx DEBUGF 1,"Got %u bytes data!\n", ecx
; calculate header length ; calculate header length
@ -760,14 +787,21 @@ stateTCB_ESTABLISHED:
and eax, 11110000b and eax, 11110000b
shr eax, 2 shr eax, 2
DEBUGF 1,"TCP header size: %u\n", eax DEBUGF 1,"TCP header size: %u\n", eax
add edx, eax add edx, eax ; now edx points to data
add esp, 4 add esp, 4
pop esi pop esi ; pointer to buffer
add esp, 4 add esp, 4
sub edx, esi sub edx, esi
mov edi, edx mov edi, edx ; offset
mov eax, ebx mov eax, ebx ; socket ptr
jmp 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] ;;;;;
call wait_mutex ;;;;;
mov ebx, eax ;;;;
.ack: .ack:
mov eax, ebx mov eax, ebx