forked from KolibriOS/kolibrios
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:
parent
d75cb497f8
commit
c14545104d
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user