forked from KolibriOS/kolibrios
237 lines
7.3 KiB
PHP
237 lines
7.3 KiB
PHP
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;; ;;
|
||
|
;; Copyright (C) KolibriOS team 2004-2019. All rights reserved. ;;
|
||
|
;; Distributed under terms of the GNU General Public License ;;
|
||
|
;; ;;
|
||
|
;; Part of the TCP/IP network stack for KolibriOS ;;
|
||
|
;; ;;
|
||
|
;; Written by hidnplayr@kolibrios.org ;;
|
||
|
;; ;;
|
||
|
;; Based on the code of 4.4BSD ;;
|
||
|
;; ;;
|
||
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
||
|
;; Version 2, June 1991 ;;
|
||
|
;; ;;
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
$Revision$
|
||
|
|
||
|
|
||
|
;-----------------------------------------------------------------;
|
||
|
; ;
|
||
|
; tcp_usrclosed ;
|
||
|
; ;
|
||
|
; IN: eax = socket ptr ;
|
||
|
; ;
|
||
|
; OUT: / ;
|
||
|
; ;
|
||
|
;-----------------------------------------------------------------;
|
||
|
align 4
|
||
|
tcp_usrclosed:
|
||
|
|
||
|
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_usrclosed: %x\n", eax
|
||
|
|
||
|
push ebx
|
||
|
mov ebx, [eax + TCP_SOCKET.t_state]
|
||
|
mov ebx, dword [.switch + ebx*4]
|
||
|
jmp ebx
|
||
|
|
||
|
.switch:
|
||
|
dd .close ; TCPS_CLOSED
|
||
|
dd .close ; TCPS_LISTEN
|
||
|
dd .close ; TCPS_SYN_SENT
|
||
|
dd .wait1 ; TCPS_SYN_RECEIVED
|
||
|
dd .wait1 ; TCPS_ESTABLISHED
|
||
|
dd .last_ack ; TCPS_CLOSE_WAIT
|
||
|
dd .ret ; TCPS_FIN_WAIT_1
|
||
|
dd .ret ; TCPS_CLOSING
|
||
|
dd .ret ; TCPS_LAST_ACK
|
||
|
dd .disc ; TCPS_FIN_WAIT_2
|
||
|
dd .disc ; TCPS_TIMED_WAIT
|
||
|
|
||
|
.close:
|
||
|
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
|
||
|
call tcp_close
|
||
|
pop ebx
|
||
|
ret
|
||
|
|
||
|
.wait1:
|
||
|
mov [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
|
||
|
pop ebx
|
||
|
ret
|
||
|
|
||
|
.last_ack:
|
||
|
mov [eax + TCP_SOCKET.t_state], TCPS_LAST_ACK
|
||
|
pop ebx
|
||
|
ret
|
||
|
|
||
|
.disc:
|
||
|
call socket_is_disconnected
|
||
|
.ret:
|
||
|
pop ebx
|
||
|
ret
|
||
|
|
||
|
|
||
|
;-----------------------------------------------------------------;
|
||
|
; ;
|
||
|
; tcp_connect ;
|
||
|
; ;
|
||
|
; IN: eax = socket ptr ;
|
||
|
; ;
|
||
|
; OUT: eax = 0 on success ;
|
||
|
; eax = -1 on error ;
|
||
|
; ebx = error code on error ;
|
||
|
; ;
|
||
|
;-----------------------------------------------------------------;
|
||
|
align 4
|
||
|
tcp_connect:
|
||
|
|
||
|
test [eax + SOCKET.state], SS_ISCONNECTED
|
||
|
jnz .eisconn
|
||
|
|
||
|
push eax edx
|
||
|
lea ecx, [eax + SOCKET.mutex]
|
||
|
call mutex_lock
|
||
|
|
||
|
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
|
||
|
pop edx eax
|
||
|
|
||
|
; Fill in remote port and IP
|
||
|
pushw [edx + 2]
|
||
|
pop [eax + TCP_SOCKET.RemotePort]
|
||
|
|
||
|
pushd [edx + 4]
|
||
|
pop [eax + TCP_SOCKET.RemoteIP]
|
||
|
|
||
|
; Find route to host
|
||
|
pusha
|
||
|
push eax
|
||
|
mov ebx, [eax + TCP_SOCKET.device]
|
||
|
mov edx, [eax + TCP_SOCKET.LocalIP]
|
||
|
mov eax, [eax + TCP_SOCKET.RemoteIP]
|
||
|
call ipv4_route
|
||
|
test eax, eax
|
||
|
jz .enoroute
|
||
|
pop eax
|
||
|
mov ebx, [net_device_list + edi]
|
||
|
mov [eax + TCP_SOCKET.device], ebx
|
||
|
mov [eax + TCP_SOCKET.LocalIP], edx
|
||
|
popa
|
||
|
|
||
|
; Find a local port, if user didnt define one
|
||
|
cmp [eax + TCP_SOCKET.LocalPort], 0
|
||
|
jne @f
|
||
|
call socket_find_port
|
||
|
@@:
|
||
|
|
||
|
; Compute window scaling factor
|
||
|
push ecx
|
||
|
xor ecx, ecx
|
||
|
mov ebx, TCP_max_win
|
||
|
@@:
|
||
|
cmp ebx, SOCKET_BUFFER_SIZE
|
||
|
ja @f
|
||
|
shl ebx, 1
|
||
|
inc ecx
|
||
|
cmp ecx, TCP_max_winshift
|
||
|
jb @r
|
||
|
@@:
|
||
|
mov [eax + TCP_SOCKET.request_r_scale], cl
|
||
|
pop ecx
|
||
|
|
||
|
call socket_is_connecting
|
||
|
inc [TCPS_connattempt]
|
||
|
|
||
|
mov [eax + TCP_SOCKET.timer_persist], 0
|
||
|
mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
|
||
|
|
||
|
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
|
||
|
|
||
|
push [TCP_sequence_num]
|
||
|
add [TCP_sequence_num], TCP_ISSINCR/2
|
||
|
pop [eax + TCP_SOCKET.ISS]
|
||
|
|
||
|
tcp_sendseqinit eax
|
||
|
|
||
|
push eax
|
||
|
lea ecx, [eax + SOCKET.mutex]
|
||
|
call mutex_unlock
|
||
|
pop eax
|
||
|
|
||
|
; Now send the SYN packet to remote end
|
||
|
push eax
|
||
|
call tcp_output
|
||
|
pop eax
|
||
|
|
||
|
test [eax + SOCKET.options], SO_NONBLOCK
|
||
|
jz .waitforit
|
||
|
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
mov ebx, EINPROGRESS
|
||
|
ret
|
||
|
|
||
|
.nomem:
|
||
|
pop edx eax
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
mov ebx, ENOMEM
|
||
|
ret
|
||
|
|
||
|
.eisconn:
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
mov ebx, EISCONN
|
||
|
ret
|
||
|
|
||
|
.enoroute:
|
||
|
pop eax
|
||
|
popa
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
mov ebx, EADDRNOTAVAIL
|
||
|
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
|
||
|
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
|