;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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