diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index 81c1384e80..992c3b83ad 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -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). diff --git a/kernel/branches/net/network/stack.inc b/kernel/branches/net/network/stack.inc index e26fbaa4a3..a71241ada0 100644 --- a/kernel/branches/net/network/stack.inc +++ b/kernel/branches/net/network/stack.inc @@ -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" @@ -389,4 +389,4 @@ sys_protocols: .return: mov [esp+28+4], eax - ret \ No newline at end of file + ret diff --git a/kernel/branches/net/network/tcp.inc b/kernel/branches/net/network/tcp.inc index a80615d7ca..3fd8d16958 100644 --- a/kernel/branches/net/network/tcp.inc +++ b/kernel/branches/net/network/tcp.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