From 89bfe5f5d63246001e37821d04a3dc7040722380 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Tue, 19 Feb 2013 16:56:54 +0000 Subject: [PATCH] Better blocking sockets, preparing for some API changes. git-svn-id: svn://kolibrios.org@3257 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/branches/net/network/IPv4.inc | 2 +- kernel/branches/net/network/socket.inc | 188 ++++++++++++++-------- kernel/branches/net/network/stack.inc | 31 ++-- kernel/branches/net/network/tcp_input.inc | 6 +- 4 files changed, 138 insertions(+), 89 deletions(-) diff --git a/kernel/branches/net/network/IPv4.inc b/kernel/branches/net/network/IPv4.inc index 2a4a06c559..98e774e10f 100644 --- a/kernel/branches/net/network/IPv4.inc +++ b/kernel/branches/net/network/IPv4.inc @@ -225,7 +225,7 @@ IPv4_input: ; TODO: add IPv4 call NET_ptr_to_num shl edi, 2 - ; check if it matches local ip + ; check if it matches local ip (Using RFC1122 strong end system model) mov eax, [edx + IPv4_header.DestinationAddress] cmp eax, [IP_LIST+edi] diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index 74bf4b3769..7b28f82a6d 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -227,28 +227,6 @@ macro SOCKET_init { } - -;----------------------------------------------------------------- -; -; SOCKET_block -; -;----------------------------------------------------------------- -macro SOCKET_block socket, loop, done { - - test [socket + SOCKET.options], SO_BLOCK ; Is this a blocking socket? - jz done ; No, return immediately - - pusha - mov eax, EVENT_NETWORK - mov ebx, 1337 ; UID: ???? - call wait_event - popa - - jmp loop - -} - - ;----------------------------------------------------------------- ; ; Socket API (function 74) @@ -307,6 +285,12 @@ SOCKET_open: mov [esp+32], edi ; return socketnumber DEBUGF 2,"socknum=%u\n", edi +; push edx +; and edx, SO_NONBLOCK + or [eax + SOCKET.options], SO_NONBLOCK ;edx +; pop edx +; and edx, not SO_NONBLOCK + mov [eax + SOCKET.Domain], ecx mov [eax + SOCKET.Type], edx mov [eax + SOCKET.Protocol], esi @@ -711,7 +695,11 @@ SOCKET_accept: ret .block: - SOCKET_block eax, .loop, s_error + test [eax + SOCKET.options], SO_NONBLOCK + jnz s_error + + call SOCKET_block + jmp .loop ;----------------------------------------------------------------- ; @@ -832,22 +820,12 @@ SOCKET_receive_dgram: jmp s_error .block: - SOCKET_block eax, .loop, s_error + test [eax + SOCKET.options], SO_NONBLOCK + jnz s_error -align 4 -SOCKET_receive_local: + call SOCKET_block + jmp .loop - ; does this socket have a PID yet? - cmp [eax + SOCKET.PID], 0 - jne @f - - ; Change PID to that of current process - mov ebx, [TASK_BASE] - mov ebx, [ebx + TASKDATA.pid] - mov [eax + SOCKET.PID], ebx - @@: - - mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream align 4 SOCKET_receive_stream: @@ -857,10 +835,10 @@ SOCKET_receive_stream: mov ecx, esi mov edi, edx xor edx, edx - add eax, STREAM_SOCKET.rcv .loop: - cmp [eax + RING_BUFFER.size], 0 + cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0 je .block + add eax, STREAM_SOCKET.rcv call SOCKET_ring_read call SOCKET_ring_free @@ -868,7 +846,11 @@ SOCKET_receive_stream: ret .block: - SOCKET_block (eax - STREAM_SOCKET.rcv), .loop, s_error + test [eax + SOCKET.options], SO_NONBLOCK + jnz s_error + + call SOCKET_block + jmp .loop ;----------------------------------------------------------------- @@ -967,6 +949,8 @@ SOCKET_send_pppoe: align 4 SOCKET_send_local: + DEBUGF 1,"SOCKET_send: LOCAL\n" + ; does this socket have a PID yet? cmp [eax + SOCKET.PID], 0 jne @f @@ -976,12 +960,6 @@ SOCKET_send_local: mov ebx, [ebx + TASKDATA.pid] mov [eax + SOCKET.PID], ebx @@: - mov [eax + SOCKET.snd_proc], SOCKET_send_local_ - -align 4 -SOCKET_send_local_: - - DEBUGF 1,"SOCKET_send: LOCAL\n" ; get the other side's socket and check if it still exists mov eax, [eax + SOCKET.device] @@ -998,7 +976,7 @@ SOCKET_send_local_: mov [esp+32], ecx ; and notify the other end - call SOCKET_notify_owner + call SOCKET_notify ret @@ -1114,13 +1092,13 @@ SOCKET_set_opt: cmp dword [edx+8], 0 je .unblock - or [eax + SOCKET.options], SO_BLOCK + and [eax + SOCKET.options], not SO_NONBLOCK mov dword [esp+32], 0 ; success! ret .unblock: - and [eax + SOCKET.options], not SO_BLOCK + or [eax + SOCKET.options], SO_NONBLOCK mov dword [esp+32], 0 ; success! ret @@ -1151,7 +1129,7 @@ SOCKET_pair: mov [eax + SOCKET.Type], SOCK_STREAM mov [eax + SOCKET.Protocol], 0 ;;; CHECKME mov [eax + SOCKET.snd_proc], SOCKET_send_local - mov [eax + SOCKET.rcv_proc], SOCKET_receive_local + mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream mov ebx, eax call SOCKET_alloc @@ -1162,7 +1140,7 @@ SOCKET_pair: mov [eax + SOCKET.Type], SOCK_STREAM mov [eax + SOCKET.Protocol], 0 ;;; CHECKME mov [eax + SOCKET.snd_proc], SOCKET_send_local - mov [eax + SOCKET.rcv_proc], SOCKET_receive_local + mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream ; Link the two sockets to eachother mov [eax + SOCKET.device], ebx @@ -1375,7 +1353,7 @@ SOCKET_input: call mutex_unlock popa - jmp SOCKET_notify_owner + jmp SOCKET_notify .full: DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax @@ -1587,7 +1565,43 @@ SOCKET_ring_free: ;----------------------------------------------------------------- ; -; SOCKET_notify_owner +; SOCKET_block +; +; Suspends the thread attached to a socket +; +; IN: eax = socket ptr +; OUT: / +; +;----------------------------------------------------------------- +align 4 +SOCKET_block: + + DEBUGF 1,"SOCKET_block: %x\n", eax + + pushf + cli + + ; Set the 'socket is blocked' flag + or [eax + SOCKET.state], SS_BLOCKED + + ; Suspend the thread + push edx + mov edx, [TASK_BASE] + DEBUGF 1,"SOCKET_block: suspending PID: %u\n", [edx + TASKDATA.pid] + mov [edx + TASKDATA.state], 1 ; Suspended + pop edx + + call change_task + popf + + DEBUGF 1,"SOCKET_block: continueing\n" + + ret + + +;----------------------------------------------------------------- +; +; SOCKET_notify ; ; notify's the owner of a socket that something happened ; @@ -1596,47 +1610,79 @@ SOCKET_ring_free: ; ;----------------------------------------------------------------- align 4 -SOCKET_notify_owner: +SOCKET_notify: - DEBUGF 1,"SOCKET_notify_owner: %x\n", eax + DEBUGF 1,"SOCKET_notify: %x\n", eax call SOCKET_check jz .error + test [eax + SOCKET.state], SS_BLOCKED + jnz .unblock + + test [eax + SOCKET.options], SO_NONBLOCK + jz .error + push eax ecx esi -; socket exists, now try to flag an event to the application +; socket exists and is of non blocking type. +; We'll try to flag an event to the thread mov eax, [eax + SOCKET.PID] test eax, eax - jz .error2 + jz .done mov ecx, 1 mov esi, TASK_DATA + TASKDATA.pid - .next_pid: + .next_pid: cmp [esi], eax je .found_pid inc ecx add esi, 0x20 cmp ecx, [TASK_COUNT] jbe .next_pid - ; PID not found, TODO: close socket! + jmp .done - jmp .error2 - - .found_pid: + .found_pid: shl ecx, 8 or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK - mov [check_idle_semaphore], 200 + mov [check_idle_semaphore], 200 ; What does this mean?? - DEBUGF 1,"SOCKET_notify_owner: succes!\n" + DEBUGF 1,"SOCKET_notify: Raised a network event!\n" - .error2: + jmp .done + + .unblock: + push eax ecx esi + ; Clear the 'socket is blocked' flag + and [eax + SOCKET.state], not SS_BLOCKED + + ; Find the thread's TASK_DATA + mov eax, [eax + SOCKET.PID] + test eax, eax + jz .error + xor ecx, ecx + inc ecx + mov esi, TASK_DATA + .next: + cmp [esi + TASKDATA.pid], eax + je .found + inc ecx + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next + jmp .error + .found: + + ; Run the thread + mov [esi + TASKDATA.state], 0 ; Running + DEBUGF 1,"SOCKET_notify: Unblocked socket!\n" + + .done: pop esi ecx eax .error: - ret @@ -1966,7 +2012,7 @@ SOCKET_check_owner: push ebx mov ebx, [TASK_BASE] - mov ebx, [ecx + TASKDATA.pid] + mov ebx, [ebx + TASKDATA.pid] cmp [eax + SOCKET.PID], ebx pop ebx @@ -2050,7 +2096,7 @@ SOCKET_is_connecting: and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING) or [eax + SOCKET.options], SS_ISCONNECTING - jmp SOCKET_notify_owner + jmp SOCKET_notify @@ -2071,7 +2117,7 @@ SOCKET_is_connected: and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING) or [eax + SOCKET.options], SS_ISCONNECTED - jmp SOCKET_notify_owner + jmp SOCKET_notify @@ -2093,7 +2139,7 @@ SOCKET_is_disconnecting: and [eax + SOCKET.options], not (SS_ISCONNECTING) or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE - jmp SOCKET_notify_owner + jmp SOCKET_notify @@ -2114,7 +2160,7 @@ SOCKET_is_disconnected: and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING) or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE - jmp SOCKET_notify_owner + jmp SOCKET_notify ;----------------------------------------------------------------- diff --git a/kernel/branches/net/network/stack.inc b/kernel/branches/net/network/stack.inc index 38a70440ed..75f277066f 100644 --- a/kernel/branches/net/network/stack.inc +++ b/kernel/branches/net/network/stack.inc @@ -79,27 +79,30 @@ SO_REUSEPORT = 1 shl 7 SO_USELOOPBACK = 1 shl 8 SO_BINDTODEVICE = 1 shl 9 -SO_BLOCK = 1 shl 10 +SO_BLOCK = 1 shl 10 ; TO BE REMOVED +SO_NONBLOCK = 1 shl 31 ; Socket level SOL_SOCKET = 0 ; Socket States -SS_NOFDREF = 0x001 ; no file table ref any more -SS_ISCONNECTED = 0x002 ; socket connected to a peer -SS_ISCONNECTING = 0x004 ; in process of connecting to peer -SS_ISDISCONNECTING = 0x008 ; in process of disconnecting -SS_CANTSENDMORE = 0x010 ; can't send more data to peer -SS_CANTRCVMORE = 0x020 ; can't receive more data from peer -SS_RCVATMARK = 0x040 ; at mark on input -SS_ISABORTING = 0x080 ; aborting fd references - close() -SS_RESTARTSYS = 0x100 ; restart blocked system calls -SS_ISDISCONNECTED = 0x800 ; socket disconnected from peer +SS_NOFDREF = 0x0001 ; no file table ref any more +SS_ISCONNECTED = 0x0002 ; socket connected to a peer +SS_ISCONNECTING = 0x0004 ; in process of connecting to peer +SS_ISDISCONNECTING = 0x0008 ; in process of disconnecting +SS_CANTSENDMORE = 0x0010 ; can't send more data to peer +SS_CANTRCVMORE = 0x0020 ; can't receive more data from peer +SS_RCVATMARK = 0x0040 ; at mark on input +SS_ISABORTING = 0x0080 ; aborting fd references - close() +SS_RESTARTSYS = 0x0100 ; restart blocked system calls +SS_ISDISCONNECTED = 0x0800 ; socket disconnected from peer -SS_ASYNC = 0x100 ; async i/o notify -SS_ISCONFIRMING = 0x200 ; deciding to accept connection req -SS_MORETOCOME = 0x400 +SS_ASYNC = 0x0100 ; async i/o notify +SS_ISCONFIRMING = 0x0200 ; deciding to accept connection req +SS_MORETOCOME = 0x0400 + +SS_BLOCKED = 0x8000 SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8 diff --git a/kernel/branches/net/network/tcp_input.inc b/kernel/branches/net/network/tcp_input.inc index 9c44a94feb..914ec93d24 100644 --- a/kernel/branches/net/network/tcp_input.inc +++ b/kernel/branches/net/network/tcp_input.inc @@ -485,7 +485,7 @@ TCP_process_input: popa mov eax, ebx - call SOCKET_notify_owner + call SOCKET_notify ; Generate more output call TCP_output @@ -521,7 +521,7 @@ TCP_process_input: call SOCKET_ring_write ; Add the data to the socket buffer mov eax, ebx - call SOCKET_notify_owner + call SOCKET_notify or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag @@ -1079,7 +1079,7 @@ TCP_process_input: pushf ; Why? mov eax, ebx - call SOCKET_notify_owner + call SOCKET_notify ; Update TCPS