forked from KolibriOS/kolibrios
zero local port for socket open means choosing by the kernel
git-svn-id: svn://kolibrios.org@1154 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
d867ba0459
commit
257b31bb6d
@ -2587,7 +2587,8 @@ dword-
|
|||||||
<EFBFBD> à ¬¥âàë:
|
<EFBFBD> à ¬¥âàë:
|
||||||
* eax = 53 - ®¬¥à äãªæ¨¨
|
* eax = 53 - ®¬¥à äãªæ¨¨
|
||||||
* ebx = 0 - ®¬¥à ¯®¤äãªæ¨¨
|
* ebx = 0 - ®¬¥à ¯®¤äãªæ¨¨
|
||||||
* ecx = «®Є «мл© Ї®ав (гзЁвлў Ґвбп в®«мЄ® ¬« ¤иҐҐ б«®ў®)
|
* ecx = «®ª «ìë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®),
|
||||||
|
ecx = 0 - ¯à¥¤®áâ ¢¨âì á¨á⥬¥ ¢ë¡®à «®ª «ì®£® ¯®àâ
|
||||||
* edx = 㤠«ñë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®)
|
* edx = 㤠«ñë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®)
|
||||||
* esi = 㤠«ñë© IP
|
* esi = 㤠«ñë© IP
|
||||||
‚®§¢à é ¥¬®¥ § 票¥:
|
‚®§¢à é ¥¬®¥ § 票¥:
|
||||||
@ -2659,7 +2660,8 @@ dword-
|
|||||||
<EFBFBD> à ¬¥âàë:
|
<EFBFBD> à ¬¥âàë:
|
||||||
* eax = 53 - ®¬¥à äãªæ¨¨
|
* eax = 53 - ®¬¥à äãªæ¨¨
|
||||||
* ebx = 5 - ®¬¥à ¯®¤äãªæ¨¨
|
* ebx = 5 - ®¬¥à ¯®¤äãªæ¨¨
|
||||||
* ecx = «®Є «мл© Ї®ав (гзЁвлў Ґвбп в®«мЄ® ¬« ¤иҐҐ б«®ў®)
|
* ecx = «®ª «ìë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®),
|
||||||
|
ecx = 0 - ¯à¥¤®áâ ¢¨âì á¨á⥬¥ ¢ë¡®à «®ª «ì®£® ¯®àâ
|
||||||
* edx = 㤠«ñë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®)
|
* edx = 㤠«ñë© ¯®àâ (ãç¨âë¢ ¥âáï ⮫쪮 ¬« ¤è¥¥ á«®¢®)
|
||||||
* esi = 㤠«ñë© IP
|
* esi = 㤠«ñë© IP
|
||||||
* edi = ०¨¬ ®âªàëâ¨ï: SOCKET_PASSIVE=0 ¨«¨ SOCKET_ACTIVE=1
|
* edi = ०¨¬ ®âªàëâ¨ï: SOCKET_PASSIVE=0 ¨«¨ SOCKET_ACTIVE=1
|
||||||
|
@ -2564,7 +2564,8 @@ Returned value:
|
|||||||
Parameters:
|
Parameters:
|
||||||
* eax = 53 - function number
|
* eax = 53 - function number
|
||||||
* ebx = 0 - subfunction number
|
* ebx = 0 - subfunction number
|
||||||
* ecx = local port (only low word is taken into account)
|
* ecx = local port (only low word is taken into account),
|
||||||
|
ecx = 0 - let the system choose a port
|
||||||
* edx = remote port (only low word is taken into account)
|
* edx = remote port (only low word is taken into account)
|
||||||
* esi = remote IP
|
* esi = remote IP
|
||||||
Returned value:
|
Returned value:
|
||||||
@ -2637,7 +2638,8 @@ Remarks:
|
|||||||
Parameters:
|
Parameters:
|
||||||
* eax = 53 - function number
|
* eax = 53 - function number
|
||||||
* ebx = 5 - subfunction number
|
* ebx = 5 - subfunction number
|
||||||
* ecx = local port (only low word is taken into account)
|
* ecx = local port (only low word is taken into account),
|
||||||
|
ecx = 0 - let the system choose a port
|
||||||
* edx = remote port (only low word is taken into account)
|
* edx = remote port (only low word is taken into account)
|
||||||
* esi = remote IP
|
* esi = remote IP
|
||||||
* edi = open mode: SOCKET_PASSIVE=0 or SOCKET_ACTIVE=1
|
* edi = open mode: SOCKET_PASSIVE=0 or SOCKET_ACTIVE=1
|
||||||
|
@ -554,6 +554,13 @@ high_code:
|
|||||||
|
|
||||||
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE
|
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE
|
||||||
|
|
||||||
|
stdcall kernel_alloc, 0x10000/8
|
||||||
|
mov edi, eax
|
||||||
|
mov [network_free_ports], eax
|
||||||
|
or eax, -1
|
||||||
|
mov ecx, 0x10000/32
|
||||||
|
rep stosd
|
||||||
|
|
||||||
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
|
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
|
||||||
|
|
||||||
call rerouteirqs
|
call rerouteirqs
|
||||||
|
@ -66,6 +66,17 @@ SOCKET_ACTIVE = 1
|
|||||||
SOCK_STREAM = 1
|
SOCK_STREAM = 1
|
||||||
SOCK_DGRAM = 2
|
SOCK_DGRAM = 2
|
||||||
|
|
||||||
|
; pointer to bitmap of free ports (1=free, 0=used)
|
||||||
|
uglobal
|
||||||
|
align 4
|
||||||
|
network_free_ports dd ?
|
||||||
|
endg
|
||||||
|
|
||||||
|
iglobal
|
||||||
|
align 4
|
||||||
|
network_free_hint dd 1024/8
|
||||||
|
endg
|
||||||
|
|
||||||
;; Allocate memory for socket data and put new socket into the list
|
;; Allocate memory for socket data and put new socket into the list
|
||||||
; Newly created socket is initialized with calling PID and number and
|
; Newly created socket is initialized with calling PID and number and
|
||||||
; put into beginning of list (which is a fastest way).
|
; put into beginning of list (which is a fastest way).
|
||||||
@ -153,6 +164,13 @@ proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
|
|||||||
;jne .next_socket
|
;jne .next_socket
|
||||||
|
|
||||||
; okay, we found the correct one
|
; okay, we found the correct one
|
||||||
|
; mark local port as unused
|
||||||
|
movzx ebx, [eax + SOCKET.LocalPort]
|
||||||
|
push eax
|
||||||
|
mov eax, [network_free_ports]
|
||||||
|
xchg bl, bh
|
||||||
|
lock bts [eax], ebx
|
||||||
|
pop eax
|
||||||
; remove it from the list first, changing pointers
|
; remove it from the list first, changing pointers
|
||||||
mov ebx, [eax + SOCKET.NextPtr]
|
mov ebx, [eax + SOCKET.NextPtr]
|
||||||
mov eax, [eax + SOCKET.PrevPtr]
|
mov eax, [eax + SOCKET.PrevPtr]
|
||||||
@ -253,28 +271,104 @@ endp
|
|||||||
; @return 1 (port is free) or 0 (port is in use) in EAX
|
; @return 1 (port is free) or 0 (port is in use) in EAX
|
||||||
;;
|
;;
|
||||||
proc is_localport_unused stdcall
|
proc is_localport_unused stdcall
|
||||||
xchg bl, bh
|
movzx ebx, bx
|
||||||
|
mov eax, [network_free_ports]
|
||||||
; assume the return value is 'free'
|
bt [eax], ebx
|
||||||
xor eax, eax
|
setc al
|
||||||
inc al
|
movzx eax, al
|
||||||
|
|
||||||
mov edx, net_sockets
|
|
||||||
|
|
||||||
.next_socket:
|
|
||||||
mov edx, [edx + SOCKET.NextPtr]
|
|
||||||
or edx, edx
|
|
||||||
jz .exit
|
|
||||||
cmp [edx + SOCKET.LocalPort], bx
|
|
||||||
jne .next_socket
|
|
||||||
|
|
||||||
; return 'in use'
|
|
||||||
dec al
|
|
||||||
|
|
||||||
.exit:
|
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
;======================================
|
||||||
|
set_local_port:
|
||||||
|
;--------------------------------------
|
||||||
|
;? Set local port in socket structure.
|
||||||
|
;--------------------------------------
|
||||||
|
;> eax -> struct SOCKET
|
||||||
|
;> bx = local port, or 0 if the kernel must select it itself
|
||||||
|
;--------------------------------------
|
||||||
|
;< CF set on error / cleared on success
|
||||||
|
;< [eax+SOCKET.LocalPort] filled on success
|
||||||
|
;======================================
|
||||||
|
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx.
|
||||||
|
push eax ecx
|
||||||
|
mov eax, [network_free_ports]
|
||||||
|
movzx ebx, bx
|
||||||
|
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5.
|
||||||
|
test ebx, ebx
|
||||||
|
jnz .given
|
||||||
|
; 2. Yes, it should. Set ecx = limit of table, eax = start value
|
||||||
|
lea ecx, [eax+0x10000/8]
|
||||||
|
add eax, [network_free_hint]
|
||||||
|
; 3. First scan loop: from free hint to end of table.
|
||||||
|
.scan1:
|
||||||
|
; 3a. For each dword, find bit set to 1
|
||||||
|
bsf ebx, [eax]
|
||||||
|
jz .next1
|
||||||
|
; 3b. If such bit has been found, atomically test again and clear it.
|
||||||
|
lock btr [eax], ebx
|
||||||
|
; 3c. If the bit was still set (usual case), we have found and reserved one port.
|
||||||
|
; Proceed to 6.
|
||||||
|
jc .found
|
||||||
|
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search.
|
||||||
|
jmp .scan1
|
||||||
|
.next1:
|
||||||
|
; 3e. All bits are cleared, so advance to next dword.
|
||||||
|
add eax, 4
|
||||||
|
; 3f. Check limit and continue loop.
|
||||||
|
cmp eax, ecx
|
||||||
|
jb .scan1
|
||||||
|
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint.
|
||||||
|
mov eax, [network_free_ports]
|
||||||
|
mov ecx, eax
|
||||||
|
add ecx, [network_free_hint]
|
||||||
|
add eax, 1024/8
|
||||||
|
; 4a. Test whether there is something to scan.
|
||||||
|
cmp eax, ecx
|
||||||
|
jae .fail
|
||||||
|
; 4b. Enter the loop, the process is same as for 3.
|
||||||
|
.scan2:
|
||||||
|
bsf ebx, [eax]
|
||||||
|
jz .next2
|
||||||
|
lock btr [eax], ebx
|
||||||
|
jc .found
|
||||||
|
jmp .scan2
|
||||||
|
.next2:
|
||||||
|
add eax, 4
|
||||||
|
cmp eax, ecx
|
||||||
|
jb .scan2
|
||||||
|
; 4c. None found. Fail.
|
||||||
|
.fail:
|
||||||
|
pop ecx eax
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
; 5. No, the kernel should reserve selected port.
|
||||||
|
.given:
|
||||||
|
; 5a. Atomically test old value and clear bit.
|
||||||
|
lock btr [eax], ebx
|
||||||
|
; 5b. If the bit was set, reservation is successful. Proceed to 8.
|
||||||
|
jc .set
|
||||||
|
; 5c. Otherwise, fail.
|
||||||
|
jmp .fail
|
||||||
|
.found:
|
||||||
|
; 6. We have found the bit set to 1, convert the position to port number.
|
||||||
|
sub eax, [network_free_ports]
|
||||||
|
lea ebx, [ebx+eax*8]
|
||||||
|
; 7. Update free hint.
|
||||||
|
add eax, 4
|
||||||
|
cmp eax, 65536/8
|
||||||
|
jb @f
|
||||||
|
mov eax, 1024/8
|
||||||
|
@@:
|
||||||
|
mov [network_free_hint], eax
|
||||||
|
.set:
|
||||||
|
; 8. Restore eax, set SOCKET.LocalPort and return.
|
||||||
|
pop ecx eax
|
||||||
|
xchg bl, bh ; Intel -> network byte order
|
||||||
|
mov [eax + SOCKET.LocalPort], bx
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
;; [53.0] Open DGRAM socket (connectionless, unreliable)
|
;; [53.0] Open DGRAM socket (connectionless, unreliable)
|
||||||
;
|
;
|
||||||
; @param BX is local port number
|
; @param BX is local port number
|
||||||
@ -291,8 +385,8 @@ proc socket_open stdcall
|
|||||||
|
|
||||||
push eax
|
push eax
|
||||||
|
|
||||||
xchg bh, bl
|
call set_local_port
|
||||||
mov [eax + SOCKET.LocalPort], bx
|
jc .error.free
|
||||||
xchg ch, cl
|
xchg ch, cl
|
||||||
mov [eax + SOCKET.RemotePort], cx
|
mov [eax + SOCKET.RemotePort], cx
|
||||||
mov ebx, [stack_ip]
|
mov ebx, [stack_ip]
|
||||||
@ -303,6 +397,9 @@ proc socket_open stdcall
|
|||||||
stdcall net_socket_addr_to_num
|
stdcall net_socket_addr_to_num
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.error.free:
|
||||||
|
stdcall net_socket_free;, eax
|
||||||
|
|
||||||
.error:
|
.error:
|
||||||
DEBUGF 1, "K : socket_open (fail)\n"
|
DEBUGF 1, "K : socket_open (fail)\n"
|
||||||
or eax, -1
|
or eax, -1
|
||||||
@ -357,8 +454,8 @@ local sockAddr dd ?
|
|||||||
; TODO - check this works!
|
; TODO - check this works!
|
||||||
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer.
|
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer.
|
||||||
|
|
||||||
xchg bh, bl
|
call set_local_port
|
||||||
mov [eax + SOCKET.LocalPort], bx
|
jc .error.free
|
||||||
xchg ch, cl
|
xchg ch, cl
|
||||||
mov [eax + SOCKET.RemotePort], cx
|
mov [eax + SOCKET.RemotePort], cx
|
||||||
mov [eax + SOCKET.OrigRemotePort], cx
|
mov [eax + SOCKET.OrigRemotePort], cx
|
||||||
@ -411,6 +508,9 @@ local sockAddr dd ?
|
|||||||
stdcall net_socket_addr_to_num, [sockAddr]
|
stdcall net_socket_addr_to_num, [sockAddr]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.error.free:
|
||||||
|
stdcall net_socket_free, eax
|
||||||
|
|
||||||
.error:
|
.error:
|
||||||
DEBUGF 1, "K : socket_open_tcp (fail)\n"
|
DEBUGF 1, "K : socket_open_tcp (fail)\n"
|
||||||
or eax, -1
|
or eax, -1
|
||||||
|
Loading…
Reference in New Issue
Block a user