diff --git a/kernel/trunk/network/IPv4.inc b/kernel/trunk/network/IPv4.inc index ad17b19026..fd770848ef 100644 --- a/kernel/trunk/network/IPv4.inc +++ b/kernel/trunk/network/IPv4.inc @@ -910,6 +910,44 @@ IPv4_get_frgmnt_num: ret +;----------------------------------------------------------------- +; +; IPv4_connect +; +; IN: eax = socket pointer +; OUT: eax = 0 ok / -1 error +; ebx = error code +; +;------------------------- +align 4 +IPv4_connect: + + pusha + lea ecx, [eax + SOCKET.mutex] + call mutex_lock + popa + +; Fill in local IP + cmp [eax + IP_SOCKET.LocalIP], 0 + jne @f + push [IP_LIST + 4] ; FIXME: use correct local IP + pop [eax + IP_SOCKET.LocalIP] + +; Fill in remote IP + pushd [edx + 4] + pop [eax + IP_SOCKET.RemoteIP] + + push eax + init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue + pop eax + + lea ecx, [eax + SOCKET.mutex] + call mutex_unlock + + xor eax, eax + ret + + ;--------------------------------------------------------------------------- ; ; IPv4_API diff --git a/kernel/trunk/network/socket.inc b/kernel/trunk/network/socket.inc index d9c5a055ce..ddebcaa1b0 100644 --- a/kernel/trunk/network/socket.inc +++ b/kernel/trunk/network/socket.inc @@ -39,6 +39,7 @@ struct SOCKET snd_proc dd ? rcv_proc dd ? + connect_proc dd ? ends @@ -150,7 +151,6 @@ struct UDP_SOCKET IP_SOCKET LocalPort dw ? ; network byte order RemotePort dw ? ; network byte order - firstpacket db ? ends @@ -311,6 +311,7 @@ SOCKET_open: mov [eax + SOCKET.Domain], ecx mov [eax + SOCKET.Type], edx mov [eax + SOCKET.Protocol], esi + mov [eax + SOCKET.connect_proc], connect_notsupp cmp ecx, AF_INET4 jne .no_inet4 @@ -359,6 +360,7 @@ align 4 mov [eax + SOCKET.Protocol], IP_PROTO_UDP mov [eax + SOCKET.snd_proc], SOCKET_send_udp mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram + mov [eax + SOCKET.connect_proc], UDP_connect ret align 4 @@ -366,6 +368,7 @@ align 4 mov [eax + SOCKET.Protocol], IP_PROTO_TCP mov [eax + SOCKET.snd_proc], SOCKET_send_tcp mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream + mov [eax + SOCKET.connect_proc], TCP_connect TCP_init_socket eax ret @@ -375,6 +378,7 @@ align 4 .raw_ip: mov [eax + SOCKET.snd_proc], SOCKET_send_ip mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram + mov [eax + SOCKET.connect_proc], IPv4_connect ret @@ -382,6 +386,7 @@ align 4 .raw_icmp: mov [eax + SOCKET.snd_proc], SOCKET_send_icmp mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram + mov [eax + SOCKET.connect_proc], IPv4_connect ret align 4 @@ -504,8 +509,12 @@ SOCKET_connect: test [eax + SOCKET.options], SO_ACCEPTCON jnz .notsupp - cmp word [edx], AF_INET4 - je .af_inet4 + call [eax + SOCKET.connect_proc] + + mov dword[esp+20], ebx + mov dword[esp+32], eax + ret + .notsupp: mov dword[esp+20], EOPNOTSUPP @@ -522,177 +531,11 @@ SOCKET_connect: mov dword[esp+32], -1 ret - .eisconn: - mov dword[esp+20], EISCONN - mov dword[esp+32], -1 - ret - .af_inet4: - cmp [eax + IP_SOCKET.LocalIP], 0 - jne @f - push [IP_LIST + 4] ; FIXME: use correct local IP - pop [eax + IP_SOCKET.LocalIP] - @@: - - cmp [eax + SOCKET.Protocol], IP_PROTO_UDP - je .udp - - cmp [eax + SOCKET.Protocol], IP_PROTO_TCP - je .tcp - - cmp [eax + SOCKET.Protocol], IP_PROTO_IP - je .ip - - cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP - je .ip - - jmp .notsupp - -align 4 - .udp: - pusha - lea ecx, [eax + SOCKET.mutex] - call mutex_lock - popa - -; Fill in remote port and IP, overwriting eventually previous values - pushw [edx + 2] - pop [eax + UDP_SOCKET.RemotePort] - - pushd [edx + 4] - pop [eax + IP_SOCKET.RemoteIP] - - cmp [eax + UDP_SOCKET.LocalPort], 0 - jne @f - call SOCKET_find_port - @@: - - mov [eax + UDP_SOCKET.firstpacket], 0 - - push eax - init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue - pop eax - - lea ecx, [eax + SOCKET.mutex] - call mutex_unlock - - call SOCKET_is_connected - - mov dword[esp+32], 0 - ret - -align 4 - .tcp: - test [eax + SOCKET.state], SS_ISCONNECTED - jnz .eisconn - - pusha - lea ecx, [eax + SOCKET.mutex] - call mutex_lock - popa - - pushw [edx + 2] - pop [eax + TCP_SOCKET.RemotePort] - - pushd [edx + 4] - pop [eax + IP_SOCKET.RemoteIP] - - cmp [eax + TCP_SOCKET.LocalPort], 0 - jne @f - call SOCKET_find_port - @@: - - mov [eax + TCP_SOCKET.timer_persist], 0 - mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT - - push [TCP_sequence_num] - add [TCP_sequence_num], 6400 - pop [eax + TCP_SOCKET.ISS] - mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init - - TCP_sendseqinit eax - - mov ebx, eax - lea eax, [ebx + STREAM_SOCKET.snd] - call SOCKET_ring_create ; TODO: check if memory was available or not - - lea eax, [ebx + STREAM_SOCKET.rcv] - call SOCKET_ring_create ; TODO: same here - - push ebx - lea ecx, [ebx + SOCKET.mutex] - call mutex_unlock - pop eax - - call SOCKET_is_connecting - - push eax - call TCP_output - pop eax - - .block: - test [eax + SOCKET.options], SO_NONBLOCK - jz .waitforit - - mov dword[esp+32], -1 - mov dword[esp+20], EINPROGRESS - ret - - .waitforit: - push eax - stdcall timer_hs, 300, 0, .timeout, eax ; FIXME: make timeout a constant - pop ebx - mov [ebx + TCP_SOCKET.timer_connect], eax - mov eax, ebx - - .loop: - cmp [eax + SOCKET.errorcode], 0 - jne .fail - cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED - je .established - - call SOCKET_block - jmp .loop - - .timeout: - mov eax, [esp+4] - mov [eax + SOCKET.errorcode], ETIMEDOUT - and [eax + SOCKET.state], not SS_ISCONNECTING - call SOCKET_notify.unblock - ret 4 - - .fail: - mov eax, [eax + SOCKET.errorcode] - mov [eax + SOCKET.errorcode], 0 ; Clear the error, we only need to send it to the caller once - mov [esp+20], eax - mov dword[esp+32], -1 - ret - - .established: - stdcall cancel_timer_hs, [eax + TCP_SOCKET.timer_connect] - mov dword[esp+20], EISCONN - mov dword[esp+32], 0 - ret - - -align 4 - .ip: - pusha - lea ecx, [eax + SOCKET.mutex] - call mutex_lock - popa - - pushd [edx + 4] - pop [eax + IP_SOCKET.RemoteIP] - - push eax - init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue - pop eax - - lea ecx, [eax + SOCKET.mutex] - call mutex_unlock - - mov dword[esp+32], 0 +connect_notsupp: + xor eax, eax + dec eax + mov ebx, EOPNOTSUPP ret diff --git a/kernel/trunk/network/tcp.inc b/kernel/trunk/network/tcp.inc index 55028a652f..f174f3b3a6 100644 --- a/kernel/trunk/network/tcp.inc +++ b/kernel/trunk/network/tcp.inc @@ -71,6 +71,8 @@ TCP_time_rtt_default = 5 ; default Round Trip Time (3,2s) TCP_time_srtt_default = 0 ; TCP_time_max_idle = 8*TCP_time_keep_interval ; FIXME +TCP_time_connect = 300 ; in 1/100s (default=3s) + ; timer constants TCP_max_rxtshift = 12 ; max retransmissions waiting for ACK TCP_max_keepcnt = 8 ; max keepalive probes diff --git a/kernel/trunk/network/tcp_usreq.inc b/kernel/trunk/network/tcp_usreq.inc index 3ed7b32d28..be947e710c 100644 --- a/kernel/trunk/network/tcp_usreq.inc +++ b/kernel/trunk/network/tcp_usreq.inc @@ -74,6 +74,137 @@ TCP_usrclosed: ret +;------------------------- +; +; TCP_connect +; +; IN: eax = socket ptr +; OUT: eax = 0 ok / -1 error +; ebx = error code +; +;------------------------- +align 4 +TCP_connect: + + test [eax + SOCKET.state], SS_ISCONNECTED + jnz .eisconn + + push eax + lea ecx, [eax + SOCKET.mutex] + call mutex_lock + pop eax + +; Fill in local IP + cmp [eax + IP_SOCKET.LocalIP], 0 + jne @f + push [IP_LIST + 4] ; FIXME: use correct local IP + pop [eax + IP_SOCKET.LocalIP] + +; Fill in remote port and IP + pushw [edx + 2] + pop [eax + TCP_SOCKET.RemotePort] + + pushd [edx + 4] + pop [eax + IP_SOCKET.RemoteIP] + +; Find a local port, if user didnt define one + cmp [eax + TCP_SOCKET.LocalPort], 0 + jne @f + call SOCKET_find_port + @@: + +; Start the TCP sequence + mov [eax + TCP_SOCKET.timer_persist], 0 + mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT + + push [TCP_sequence_num] + add [TCP_sequence_num], 6400 + pop [eax + TCP_SOCKET.ISS] + mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init + + TCP_sendseqinit eax + + mov ebx, eax + lea eax, [ebx + STREAM_SOCKET.snd] + call SOCKET_ring_create + test eax, eax + jz .nomem + + lea eax, [ebx + STREAM_SOCKET.rcv] + call SOCKET_ring_create + test eax, eax + jz .nomem + + push ebx + lea ecx, [ebx + SOCKET.mutex] + call mutex_unlock + pop eax + + call SOCKET_is_connecting + +; Now send the SYN packet to remote end + push eax + call TCP_output + pop eax + + .block: + test [eax + SOCKET.options], SO_NONBLOCK + jz .waitforit + + xor eax, eax + dec eax + mov ebx, EINPROGRESS + ret + + .nomem: + xor eax, eax + dec eax + mov ebx, ENOMEM + ret + + .eisconn: + xor eax, eax + dec eax + mov ebx, EISCONN + ret + + .waitforit: + push eax + stdcall timer_hs, TCP_time_connect, 0, .timeout, eax + pop ebx + mov [ebx + TCP_SOCKET.timer_connect], eax + mov eax, ebx + + .loop: + cmp [eax + SOCKET.errorcode], 0 + jne .fail + cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED + je .established + + call SOCKET_block + jmp .loop + + .timeout: + mov eax, [esp+4] + mov [eax + SOCKET.errorcode], ETIMEDOUT + and [eax + SOCKET.state], not SS_ISCONNECTING + call SOCKET_notify.unblock + ret 4 + + .fail: + mov ebx, [eax + SOCKET.errorcode] + mov [eax + SOCKET.errorcode], 0 ; Clear the error, we only need to send it to the caller once + xor eax, eax + dec eax + ret + + .established: + stdcall cancel_timer_hs, [eax + TCP_SOCKET.timer_connect] + + xor eax, eax + ret + + ;------------------------- diff --git a/kernel/trunk/network/udp.inc b/kernel/trunk/network/udp.inc index cafc5f1e7f..93874473ca 100644 --- a/kernel/trunk/network/udp.inc +++ b/kernel/trunk/network/udp.inc @@ -182,7 +182,7 @@ UDP_input: ; ; FIXME: UDP should check remote IP, but not under all circumstances! - cmp [eax + UDP_SOCKET.firstpacket], 0 + cmp [eax + UDP_SOCKET.RemotePort], 0 je .updateport cmp [eax + UDP_SOCKET.RemotePort], cx @@ -211,8 +211,6 @@ UDP_input: DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf mov [eax + UDP_SOCKET.RemotePort], cx - inc [eax + UDP_SOCKET.firstpacket] - jmp .updatesock .dump_: @@ -311,6 +309,84 @@ UDP_output: + +;----------------------------------------------------------------- +; +; UDP_connect +; +; IN: eax = socket pointer +; OUT: eax = 0 ok / -1 error +; ebx = error code +; +;------------------------- +align 4 +UDP_connect: + + test [eax + SOCKET.state], SS_ISCONNECTED + jz @f + call UDP_disconnect + @@: + + push eax + lea ecx, [eax + SOCKET.mutex] + call mutex_lock + pop eax + +; Fill in local IP + cmp [eax + IP_SOCKET.LocalIP], 0 + jne @f + push [IP_LIST + 4] ; FIXME: use correct local IP + pop [eax + IP_SOCKET.LocalIP] + +; Fill in remote port and IP, overwriting eventually previous values + pushw [edx + 2] + pop [eax + UDP_SOCKET.RemotePort] + + pushd [edx + 4] + pop [eax + IP_SOCKET.RemoteIP] + +; Find a local port, if user didnt define one + cmp [eax + UDP_SOCKET.LocalPort], 0 + jne @f + call SOCKET_find_port + @@: + + push eax + init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue + pop eax + + push eax + lea ecx, [eax + SOCKET.mutex] + call mutex_unlock + pop eax + + call SOCKET_is_connected + + xor eax, eax + ret + + +;----------------------------------------------------------------- +; +; UDP_disconnect +; +; IN: eax = socket pointer +; OUT: eax = socket pointer +; +;------------------------- +align 4 +UDP_disconnect: + + ; TODO: remove the pending received data + + call SOCKET_is_disconnected + + ret + + + + + ;--------------------------------------------------------------------------- ; ; UDP_API