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
|
||||
|
||||
.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)
|
||||
; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
|
||||
.wndsizeTimer dd ? ; window size timer
|
||||
@ -132,7 +137,7 @@ socket_init:
|
||||
align 4
|
||||
sys_socket:
|
||||
and ebx, 0x000000FF ; should i remove this line ?
|
||||
cmp bl , 7 ; highest possible number
|
||||
cmp bl , 8 ; highest possible number
|
||||
jg s_error
|
||||
lea ebx, [.table + 4*ebx]
|
||||
jmp dword [ebx]
|
||||
@ -146,7 +151,7 @@ sys_socket:
|
||||
dd socket_accept ; 5
|
||||
dd socket_send ; 6
|
||||
dd socket_recv ; 7
|
||||
; dd socket_get_opt ; 8
|
||||
dd socket_get_opt ; 8
|
||||
; dd socket_set_opt ; 9
|
||||
|
||||
|
||||
@ -398,8 +403,8 @@ socket_listen:
|
||||
jne s_error
|
||||
|
||||
cmp edx, MAX_backlog
|
||||
jl .ok
|
||||
mov dx , 20
|
||||
jb .ok
|
||||
mov dx , MAX_backlog
|
||||
.ok:
|
||||
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
|
||||
@ -448,33 +453,20 @@ socket_accept:
|
||||
|
||||
.tcp:
|
||||
|
||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
|
||||
jz s_error
|
||||
|
||||
call net_socket_alloc
|
||||
or eax, eax
|
||||
jz s_error
|
||||
mov edi, eax
|
||||
|
||||
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
|
||||
|
||||
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
|
||||
lea ebx, [esi + SOCKET_head.lock]
|
||||
call wait_mutex
|
||||
movzx eax, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||
test eax, eax
|
||||
jz .unlock_err
|
||||
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
|
||||
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + (eax-1)*4]
|
||||
mov [esi + SOCKET_head.lock], 0
|
||||
stdcall net_socket_addr_to_num, eax
|
||||
mov [esp+32], eax
|
||||
|
||||
ret
|
||||
|
||||
.unlock_err:
|
||||
mov [esi + SOCKET_head.lock], 0
|
||||
jmp s_error
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
@ -753,6 +745,47 @@ socket_send:
|
||||
mov [esp+32], eax
|
||||
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 esi ; data_ptr
|
||||
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"
|
||||
add esp, 4*3
|
||||
|
||||
mov [eax + SOCKET_head.lock], 0
|
||||
|
||||
notify_network_event:
|
||||
; flag an event to the application
|
||||
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
|
||||
mov ecx, 1
|
||||
@ -907,7 +941,6 @@ socket_internal_receiver:
|
||||
|
||||
|
||||
|
||||
|
||||
; Allocate memory for socket data and put new socket into the list
|
||||
; Newly created socket is initialized with calling PID and number and
|
||||
; put into beginning of list (which is a fastest way).
|
||||
|
@ -77,23 +77,23 @@ TH_URG equ 1 shl 5
|
||||
|
||||
macro inc_INET reg {
|
||||
|
||||
inc byte [reg + 3]
|
||||
add byte [reg + 3], 1
|
||||
adc byte [reg + 2], 0
|
||||
adc byte [reg + 1], 0
|
||||
adc byte [reg + 0], 0
|
||||
adc byte [reg], 0
|
||||
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
adc byte [reg + 3], ch
|
||||
adc byte [reg + 2], cl
|
||||
add byte [reg + 1], cl
|
||||
adc byte [reg], ch
|
||||
rol ecx, 16
|
||||
adc byte [reg + 1], ch
|
||||
adc byte [reg + 0], cl
|
||||
|
||||
}
|
||||
|
||||
include "queue.inc"
|
||||
|
@ -360,6 +360,7 @@ TCP_handler :
|
||||
; add eax, ecx ;
|
||||
|
||||
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
|
||||
@ -615,32 +616,58 @@ stateTCB_LISTEN:
|
||||
; Look at control flags
|
||||
test [edx + TCP_Packet.Flags], TH_SYN
|
||||
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,
|
||||
; And send a response
|
||||
|
||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
|
||||
mov ax, [edx + TCP_Packet.SourcePort]
|
||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], ax
|
||||
mov eax, [edx + TCP_Packet.SequenceNumber]
|
||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
|
||||
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]
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
|
||||
mov cx, [edx + TCP_Packet.SourcePort]
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
|
||||
mov ecx, [edx + TCP_Packet.SequenceNumber]
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
|
||||
lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
|
||||
inc_INET esi ; RCV.NXT
|
||||
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 ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
|
||||
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
|
||||
|
||||
push eax
|
||||
; Now construct the response
|
||||
mov bl, TH_SYN + TH_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
|
||||
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
|
||||
ret
|
||||
|
||||
.exit:
|
||||
mov [ebx + SOCKET_head.lock], 0
|
||||
@ -721,6 +748,8 @@ stateTCB_SYN_RECEIVED:
|
||||
jz .exit
|
||||
|
||||
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
|
||||
mov eax, ebx
|
||||
call notify_network_event
|
||||
|
||||
.exit:
|
||||
mov [ebx + SOCKET_head.lock], 0
|
||||
|
Loading…
Reference in New Issue
Block a user