forked from KolibriOS/kolibrios
Some changes in TCP for net branch:
* listening sockets have now a queue of incoming connections * a mechanism which allows an application to know when sent packet is ACKed * some fixes git-svn-id: svn://kolibrios.org@1256 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
30373c2ee1
commit
1f42f20b6f
@ -43,6 +43,11 @@ struct TCP_SOCKET
|
|||||||
.RemotePort dw ? ; In INET byte order
|
.RemotePort dw ? ; In INET byte order
|
||||||
|
|
||||||
.backlog dw ? ; Backlog
|
.backlog dw ? ; Backlog
|
||||||
|
.backlog_cur dw ? ; current size of queue for un-accept-ed connections
|
||||||
|
.last_ack_number dd ? ; used only to let application know that ACK has been received
|
||||||
|
; todo: may be use SND_UNA instead
|
||||||
|
; todo: may be use events which allow additional information instead
|
||||||
|
; todo: may be count acknowledged bytes (at least it has obvious sense)
|
||||||
; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
|
; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
|
||||||
; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
|
; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
|
||||||
.wndsizeTimer dd ? ; window size timer
|
.wndsizeTimer dd ? ; window size timer
|
||||||
@ -132,7 +137,7 @@ socket_init:
|
|||||||
align 4
|
align 4
|
||||||
sys_socket:
|
sys_socket:
|
||||||
and ebx, 0x000000FF ; should i remove this line ?
|
and ebx, 0x000000FF ; should i remove this line ?
|
||||||
cmp bl , 7 ; highest possible number
|
cmp bl , 8 ; highest possible number
|
||||||
jg s_error
|
jg s_error
|
||||||
lea ebx, [.table + 4*ebx]
|
lea ebx, [.table + 4*ebx]
|
||||||
jmp dword [ebx]
|
jmp dword [ebx]
|
||||||
@ -146,7 +151,7 @@ sys_socket:
|
|||||||
dd socket_accept ; 5
|
dd socket_accept ; 5
|
||||||
dd socket_send ; 6
|
dd socket_send ; 6
|
||||||
dd socket_recv ; 7
|
dd socket_recv ; 7
|
||||||
; dd socket_get_opt ; 8
|
dd socket_get_opt ; 8
|
||||||
; dd socket_set_opt ; 9
|
; dd socket_set_opt ; 9
|
||||||
|
|
||||||
|
|
||||||
@ -398,8 +403,8 @@ socket_listen:
|
|||||||
jne s_error
|
jne s_error
|
||||||
|
|
||||||
cmp edx, MAX_backlog
|
cmp edx, MAX_backlog
|
||||||
jl .ok
|
jb .ok
|
||||||
mov dx , 20
|
mov dx , MAX_backlog
|
||||||
.ok:
|
.ok:
|
||||||
|
|
||||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
|
||||||
@ -448,33 +453,20 @@ socket_accept:
|
|||||||
|
|
||||||
.tcp:
|
.tcp:
|
||||||
|
|
||||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
|
lea ebx, [esi + SOCKET_head.lock]
|
||||||
jz s_error
|
call wait_mutex
|
||||||
|
movzx eax, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||||
call net_socket_alloc
|
test eax, eax
|
||||||
or eax, eax
|
jz .unlock_err
|
||||||
jz s_error
|
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||||
mov edi, eax
|
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + (eax-1)*4]
|
||||||
|
mov [esi + SOCKET_head.lock], 0
|
||||||
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
|
stdcall net_socket_addr_to_num, eax
|
||||||
|
|
||||||
mov ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
|
|
||||||
push esi edi
|
|
||||||
rep movsd
|
|
||||||
pop edi esi
|
|
||||||
|
|
||||||
mov [edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
|
|
||||||
|
|
||||||
; TODO: fill in structure in ecx
|
|
||||||
|
|
||||||
mov [esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
|
|
||||||
mov [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
|
|
||||||
|
|
||||||
stdcall net_socket_addr_to_num, edi
|
|
||||||
mov [esp+32], eax
|
mov [esp+32], eax
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
.unlock_err:
|
||||||
|
mov [esi + SOCKET_head.lock], 0
|
||||||
|
jmp s_error
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------
|
;-----------------------------------------------
|
||||||
@ -753,6 +745,47 @@ socket_send:
|
|||||||
mov [esp+32], eax
|
mov [esp+32], eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;-----------------------------------------------
|
||||||
|
;
|
||||||
|
; SOCKET_send
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; IN: socket number in ecx
|
||||||
|
; edx points to the options:
|
||||||
|
; dd level, optname, optval, optlen
|
||||||
|
; OUT: -1 on error
|
||||||
|
;
|
||||||
|
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
|
||||||
|
; TODO: find best way to notify that send()'ed data were acknowledged
|
||||||
|
;
|
||||||
|
;-----------------------------------------------
|
||||||
|
socket_get_opt:
|
||||||
|
cmp dword [edx], IP_PROTO_TCP
|
||||||
|
jnz .unknown
|
||||||
|
cmp dword [edx+4], -2
|
||||||
|
jnz .unknown
|
||||||
|
mov eax, [edx+12]
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
cmp dword [eax], 4
|
||||||
|
mov dword [eax], 4
|
||||||
|
jb .fail
|
||||||
|
stdcall net_socket_num_to_addr, ecx
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
; todo: check that eax is really TCP socket
|
||||||
|
mov ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number]
|
||||||
|
mov eax, [edx+8]
|
||||||
|
test eax, eax
|
||||||
|
jz @f
|
||||||
|
mov [eax], ecx
|
||||||
|
@@:
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
.fail:
|
||||||
|
.unknown:
|
||||||
|
or eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------
|
;-----------------------------------------------
|
||||||
@ -872,12 +905,13 @@ socket_internal_receiver:
|
|||||||
push ecx ; size
|
push ecx ; size
|
||||||
push esi ; data_ptr
|
push esi ; data_ptr
|
||||||
mov esi, esp
|
mov esi, esp
|
||||||
add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
|
add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, notify_network_event.full
|
||||||
DEBUGF 1,"Queued packet successfully\n"
|
DEBUGF 1,"Queued packet successfully\n"
|
||||||
add esp, 4*3
|
add esp, 4*3
|
||||||
|
|
||||||
mov [eax + SOCKET_head.lock], 0
|
mov [eax + SOCKET_head.lock], 0
|
||||||
|
|
||||||
|
notify_network_event:
|
||||||
; flag an event to the application
|
; flag an event to the application
|
||||||
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
|
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
|
||||||
mov ecx, 1
|
mov ecx, 1
|
||||||
@ -907,7 +941,6 @@ socket_internal_receiver:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; Allocate memory for socket data and put new socket into the list
|
; Allocate memory for socket data and put new socket into the list
|
||||||
; Newly created socket is initialized with calling PID and number and
|
; Newly created socket is initialized with calling PID and number and
|
||||||
; put into beginning of list (which is a fastest way).
|
; put into beginning of list (which is a fastest way).
|
||||||
|
@ -77,23 +77,23 @@ TH_URG equ 1 shl 5
|
|||||||
|
|
||||||
macro inc_INET reg {
|
macro inc_INET reg {
|
||||||
|
|
||||||
inc byte [reg + 3]
|
add byte [reg + 3], 1
|
||||||
adc byte [reg + 2], 0
|
adc byte [reg + 2], 0
|
||||||
adc byte [reg + 1], 0
|
adc byte [reg + 1], 0
|
||||||
adc byte [reg + 0], 0
|
adc byte [reg], 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro add_INET reg {
|
macro add_INET reg {
|
||||||
|
add byte [reg + 3], cl
|
||||||
|
adc byte [reg + 2], ch
|
||||||
|
adc byte [reg + 1], 0
|
||||||
|
adc byte [reg], 0
|
||||||
rol ecx, 16
|
rol ecx, 16
|
||||||
adc byte [reg + 3], ch
|
add byte [reg + 1], cl
|
||||||
adc byte [reg + 2], cl
|
adc byte [reg], ch
|
||||||
rol ecx, 16
|
rol ecx, 16
|
||||||
adc byte [reg + 1], ch
|
|
||||||
adc byte [reg + 0], cl
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
include "queue.inc"
|
include "queue.inc"
|
||||||
|
@ -360,6 +360,7 @@ TCP_handler :
|
|||||||
; add eax, ecx ;
|
; add eax, ecx ;
|
||||||
|
|
||||||
mov eax, [edx + TCP_Packet.AckNumber]
|
mov eax, [edx + TCP_Packet.AckNumber]
|
||||||
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], eax
|
||||||
;---------
|
;---------
|
||||||
|
|
||||||
cmp [TCP_OUT_QUEUE], 0
|
cmp [TCP_OUT_QUEUE], 0
|
||||||
@ -615,32 +616,58 @@ stateTCB_LISTEN:
|
|||||||
; Look at control flags
|
; Look at control flags
|
||||||
test [edx + TCP_Packet.Flags], TH_SYN
|
test [edx + TCP_Packet.Flags], TH_SYN
|
||||||
jz .exit
|
jz .exit
|
||||||
|
; Exit if backlog queue is full
|
||||||
|
mov ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||||
|
cmp ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
|
||||||
|
jae .exit
|
||||||
|
; Allocate new socket
|
||||||
|
push esi
|
||||||
|
call net_socket_alloc
|
||||||
|
pop esi
|
||||||
|
test eax, eax
|
||||||
|
jz .exit
|
||||||
|
; Copy structure from current socket to new, including lock
|
||||||
|
push esi edi
|
||||||
|
lea esi, [ebx + SOCKET_head.PID] ; yes, PID must also be copied
|
||||||
|
lea edi, [eax + SOCKET_head.PID]
|
||||||
|
mov ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
|
||||||
|
rep movsd
|
||||||
|
pop edi esi
|
||||||
|
; Push pointer to new socket to queue
|
||||||
|
movzx ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||||
|
inc [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||||
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
|
||||||
|
|
||||||
; We have a SYN. update the socket with this IP Packets details,
|
; We have a SYN. update the socket with this IP Packets details,
|
||||||
; And send a response
|
; And send a response
|
||||||
|
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
|
||||||
mov ax, [edx + TCP_Packet.SourcePort]
|
mov cx, [edx + TCP_Packet.SourcePort]
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], ax
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
|
||||||
mov eax, [edx + TCP_Packet.SequenceNumber]
|
mov ecx, [edx + TCP_Packet.SequenceNumber]
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
|
||||||
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
|
lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
|
||||||
inc_INET esi ; RCV.NXT
|
inc_INET esi ; RCV.NXT
|
||||||
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
|
mov ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
|
||||||
|
|
||||||
|
mov [eax + SOCKET_head.lock], 0
|
||||||
mov [ebx + SOCKET_head.lock], 0
|
mov [ebx + SOCKET_head.lock], 0
|
||||||
|
|
||||||
|
push eax
|
||||||
; Now construct the response
|
; Now construct the response
|
||||||
mov bl, TH_SYN + TH_ACK
|
mov bl, TH_SYN + TH_ACK
|
||||||
call TCP_send_ack
|
call TCP_send_ack
|
||||||
|
pop eax
|
||||||
|
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
|
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
|
||||||
|
call notify_network_event
|
||||||
|
|
||||||
; increment SND.NXT in socket
|
; increment SND.NXT in socket
|
||||||
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
|
lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
|
||||||
inc_INET esi
|
inc_INET esi
|
||||||
|
ret
|
||||||
|
|
||||||
.exit:
|
.exit:
|
||||||
mov [ebx + SOCKET_head.lock], 0
|
mov [ebx + SOCKET_head.lock], 0
|
||||||
@ -721,6 +748,8 @@ stateTCB_SYN_RECEIVED:
|
|||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
|
||||||
|
mov eax, ebx
|
||||||
|
call notify_network_event
|
||||||
|
|
||||||
.exit:
|
.exit:
|
||||||
mov [ebx + SOCKET_head.lock], 0
|
mov [ebx + SOCKET_head.lock], 0
|
||||||
|
Loading…
Reference in New Issue
Block a user