kolibrios/kernel/branches/net/network/socket.inc
hidnplayr 7f9d0c6697 Changes in net branch:
Things changed: sockets data organisation, queue macro's are more universal, new checksum routines, changed socket structures, ...
What's new: UDP checksum generation & validation
Rough TCP code has been written, but not debugged yet.

git-svn-id: svn://kolibrios.org@1249 a494cfbc-eb01-0410-851d-a64ba20cac60
2009-11-06 20:45:08 +00:00

1175 lines
24 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; SOCKET.INC ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; based on code by mike.dld ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
struct SOCKET_head
.PrevPtr dd ? ; pointer to previous socket in list
.NextPtr dd ? ; pointer to next socket in list
.Number dd ? ; socket number (unique within single process)
.PID dd ? ; application process id
.Domain dd ? ; INET/UNIX/..
.Type dd ? ; RAW/UDP/TCP/...
.Protocol dd ? ; ICMP/IPv4/ARP/
.lock dd ? ; lock mutex
.end:
ends
struct IPv4_SOCKET
.LocalIP dd ?
.RemoteIP dd ?
.SequenceNumber dd ?
; todo: add options (for func 8 and 9)
.end:
ends
struct TCP_SOCKET
.LocalPort dw ? ; In INET byte order
.RemotePort dw ? ; In INET byte order
.backlog dw ? ; Backlog
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
.TCBState dd ? ; TCB state
.TCBTimer dd ? ; TCB timer (seconds)
.ISS dd ? ; initial send sequence
.IRS dd ? ; initial receive sequence
.SND_UNA dd ? ; sequence number of unack'ed sent Packets
.SND_NXT dd ? ; next send sequence number to use
.SND_WND dd ? ; send window
.RCV_NXT dd ? ; next receive sequence number to use
.RCV_WND dd ? ; receive window
.SEG_LEN dd ? ; segment length
.SEG_WND dd ? ; segment window
.wndsizeTimer dd ? ; window size timer
.flags db ? ; packet flags
.end:
ends
struct UDP_SOCKET
.LocalPort dw ? ; In INET byte order
.RemotePort dw ? ; In INET byte order
.end:
ends
struct ICMP_SOCKET
.Identifier dw ? ;
.end:
ends
struct IPC_SOCKET
.ConnectedTo dd ? ; Socket number of other socket this one is connected to
.end:
ends
MAX_backlog equ 20 ; backlog for stream sockets
SOCKETBUFFSIZE equ 4096 ; in bytes
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
uglobal
net_sockets rd 2
last_UDP_port dw ? ; These values give the number of the last used ephemeral port
last_TCP_port dw ? ;
endg
;-----------------------------------------------
;
; SOCKET_init
;
; -
;
; IN: /
; OUT: /
;
;-----------------------------------------------
align 4
socket_init:
mov [net_sockets], 0
mov [net_sockets + 4], 0
mov [last_UDP_port], MIN_EPHEMERAL_PORT
mov [last_TCP_port], MIN_EPHEMERAL_PORT
ret
;-----------------------------------------------------------------------------
;
; Socket API (function 74)
;
;-----------------------------------------------------------------------------
align 4
sys_socket:
test bl, bl
jz socket_open ; 0
dec bl
jz socket_close ; 1
dec bl
jz socket_bind ; 2
dec bl
jz socket_listen ; 3
dec bl
jz socket_connect ; 4
dec bl
jz socket_accept ; 5
dec bl
jz socket_send ; 6
dec bl
jz socket_recv ; 7
dec bl
; jz socket_get_opt ; 8
dec bl
; jz socket_set_opt ; 9
s_error:
mov dword [esp+32],-1
ret
;-----------------------------------------------
;
; SOCKET_open
;
;
; IN: domain in ecx
; type in edx
; protocol in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------
align 4
socket_open:
DEBUGF 1,"socket_open: domain: %u, type: %u",ecx, edx
call net_socket_alloc
or eax, eax
jz s_error
mov [eax + SOCKET_head.Domain], ecx
mov [eax + SOCKET_head.Type], edx
mov [eax + SOCKET_head.Protocol], esi
stdcall net_socket_addr_to_num, eax
DEBUGF 1,", socketnumber: %u\n", eax
mov [esp+32], eax
ret
;-----------------------------------------------
;
; SOCKET_bind
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------
align 4
socket_bind:
DEBUGF 1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi
stdcall net_socket_num_to_addr, ecx
cmp eax, -1
jz s_error
cmp esi, 2
jl s_error
cmp word [edx], AF_INET4
je .af_inet4
cmp word [edx], AF_UNIX
je .af_unix
jmp s_error
.af_unix:
; TODO: write code here
mov dword [esp+32],0
ret
.af_inet4:
cmp esi, 6
jl s_error
mov ecx, [eax + SOCKET_head.Type]
mov bx, word [edx + 2]
DEBUGF 1,"local port: %x ",bx
test bx, bx
jz .find_free
call socket_check_port
test bx, bx
je s_error
jmp .got_port
.find_free:
call socket_find_port
test bx, bx
je s_error
.got_port:
DEBUGF 1,"using port: %x ",bx
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
mov ebx, dword [edx + 4]
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
mov dword [esp+32],0
ret
;-----------------------------------------------
;
; SOCKET_connect
;
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------
align 4
socket_connect:
DEBUGF 1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi
stdcall net_socket_num_to_addr, ecx
cmp eax, -1
jz s_error
cmp esi, 2
jl s_error
cmp word [edx], AF_INET4
je .af_inet4
jmp s_error
.af_inet4:
cmp esi, 8
jl s_error
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
je .icmp
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
jmp s_error
.udp:
mov bx , word [edx + 2]
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
DEBUGF 1,"remote port: %x ",bx
mov ebx, dword [edx + 4]
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
DEBUGF 1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
mov dword [esp+32],0
ret
.icmp:
; TODO: write code here
ret
.tcp:
;local sockAddr dd ?
; cmp esi, SOCKET_PASSIVE
; jne .skip_port_check
;
; push ebx
; mov eax, ebx
; xchg al, ah
; mov ebx, net_sockets
;
; .next_socket:
; mov ebx, [ebx + SOCKET.NextPtr]
; or ebx, ebx
; jz .last_socket
; cmp [ebx + SOCKET.TCBState], TCB_LISTEN
; jne .next_socket
; cmp [ebx + SOCKET.LocalPort], ax
; jne .next_socket
;
; xchg al, ah
; DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx
; pop ebx
; jmp .error
;
; .last_socket:
; pop ebx
;
; .skip_port_check:
; mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer.
;
; xchg bh, bl
; mov [eax + SOCKET.LocalPort], bx
; xchg ch, cl
; mov [eax + SOCKET.RemotePort], cx
; mov [eax + SOCKET.OrigRemotePort], cx
; mov ebx, [IP_LIST]
; mov [eax + SOCKET.LocalIP], ebx
; mov [eax + SOCKET.RemoteIP], edx
; mov [eax + SOCKET.OrigRemoteIP], edx
; mov ebx, TCB_LISTEN
; cmp esi, SOCKET_PASSIVE
; je @f
; mov ebx, TCB_SYN_SENT
; @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB
; cmp ebx, TCB_LISTEN
; je .exit
; Now, if we are in active mode, then we have to send a SYN to the specified remote port
; mov eax, EMPTY_QUEUE
; call dequeue
; cmp ax, NO_BUFFER
; je .exit
; push eax
; mov bl, TH_SYN
; xor ecx, ecx
; stdcall build_tcp_Packet, [sockAddr]
; mov eax, NET1OUT_QUEUE
; mov edx, [IP_LIST]
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
; .not_local:
; Send it.
; pop ebx
; call queue
.exit:
xor eax, eax
ret
;-----------------------------------------------
;
; SOCKET_listen
;
;
; IN: socket number in ecx
; backlog in edx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------
align 4
socket_listen:
DEBUGF 1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
stdcall net_socket_num_to_addr, ecx
cmp eax, -1
jz s_error
cmp edx, MAX_backlog
jl .ok
mov dx , 20
.ok:
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
; TODO: insert code for active connections like TCP
mov dword [esp+32], 0
ret
;-----------------------------------------------
;
; SOCKET_accept
;
;
; IN: socket number in ecx
; addr in edx
; addrlen in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------
align 4
socket_accept:
DEBUGF 1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
stdcall net_socket_num_to_addr, ecx
or eax, eax
jz s_error
mov esi, eax
cmp word [esi + SOCKET_head.Domain], AF_INET4
je .af_inet4
jmp s_error
.af_inet4:
cmp [esi + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
jmp s_error
.tcp:
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
jz s_error
call net_socket_alloc
or eax, eax
jz s_error
mov edi, eax
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
mov ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
push esi edi
rep movsd
pop edi esi
mov [edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
; TODO: fill in structure in ecx
mov [esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
mov [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
stdcall net_socket_addr_to_num, edi
mov [esp+32], eax
ret
;-----------------------------------------------
;
; SOCKET_close
;
;
; IN: socket number in ecx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------
align 4
socket_close:
DEBUGF 1,"Socket_close: socknum: %u\n",ecx
stdcall net_socket_num_to_addr, ecx
or eax, eax
jz s_error
cmp [eax + SOCKET_head.Domain], AF_INET4
jne s_error
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
je .icmp
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
jmp s_error
.udp:
stdcall net_socket_free, eax
mov dword [esp+32],0
ret
.icmp:
ret
.tcp:
if 1 = 0
;local sockAddr dd ?
; DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx
; first, remove any resend entries
pusha
mov esi, resendQ
mov ecx, 0
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .last_resendq ; None left
cmp [esi + 4], ebx
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
@@: mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
.last_resendq:
popa
mov ebx, eax
; mov [sockAddr], eax
cmp [eax + SOCKET.TCBState], TCB_LISTEN
je .destroy_tcb
cmp [eax + SOCKET.TCBState], TCB_SYN_SENT
je .destroy_tcb
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .error
push eax
mov bl, TH_FIN
xor ecx, ecx
xor esi, esi
stdcall build_tcp_Packet, [sockAddr]
mov ebx, [sockAddr]
; increament SND.NXT in socket
lea esi, [ebx + SOCKET.SND_NXT]
call inc_inet_esi
; Get the socket state
mov eax, [ebx + SOCKET.TCBState]
cmp eax, TCB_SYN_RECEIVED
je .fin_wait_1
cmp eax, TCB_ESTABLISHED
je .fin_wait_1
; assume CLOSE WAIT
; Send a fin, then enter last-ack state
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK
jmp .send
.fin_wait_1:
; Send a fin, then enter finwait2 state
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
.send:
mov eax, NET1OUT_QUEUE
mov edx, [IP_LIST]
; mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
.not_local:
; Send it.
pop ebx
call queue
jmp .exit
.destroy_tcb:
stdcall net_socket_free, eax
end if
.exit:
mov dword [esp+32],0
ret
;-----------------------------------------------
;
; SOCKET_receive
;
;
; IN: socket number in ecx
; addr to buffer in edx
; length of buffer in esi
; flags in edi
; OUT: eax is number of bytes copied, -1 on error
;
;-----------------------------------------------
align 4
socket_recv:
DEBUGF 1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
stdcall net_socket_num_to_addr, ecx ; get real socket address
or eax, eax
jz s_error
DEBUGF 1,"Socket pointer: %x\n", eax
get_from_queue (eax + 2048), SOCKET_QUEUE_SIZE, 4*3, s_error
mov edi, edx
mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF 1,"Got %u bytes of data\n", ecx
cmp ecx, edx
jle .large_enough
DEBUGF 1,"Buffer too small...\n"
jmp s_error
.large_enough:
push [esi + socket_queue_entry.data_ptr]
mov esi, [esi + socket_queue_entry.offset]
add esi, [esp]
DEBUGF 1,"Source buffer: %x, real addr: %x\n", [esp], esi
mov dword[esp+32+4], ecx ; return number of bytes copied
shr ecx, 1
jnc .nb
movsb
.nb: shr ecx, 1
jnc .nw
movsw
.nw: rep movsd
call kernel_free
ret
;-----------------------------------------------
;
; SOCKET_send
;
;
; IN: socket number in ecx
; pointer to data in edx
; datalength in esi
; flags in edi
; OUT: -1 on error
;
;-----------------------------------------------
align 4
socket_send:
DEBUGF 1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
stdcall net_socket_num_to_addr, ecx ; get real socket address
or eax, eax
jz s_error
cmp word [eax + SOCKET_head.Domain], AF_INET4
je .af_inet4
jmp s_error
;---------
.af_inet4:
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp
cmp [eax + SOCKET_head.Type], SOCK_RAW
je .raw
jmp s_error
;--------
.udp:
DEBUGF 1,"type: UDP, "
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
jne @f
push esi
mov ecx, [eax + SOCKET_head.Type]
call socket_find_port
test bx, bx
pop esi
je s_error
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
@@:
mov ecx, esi
mov esi, edx
call UDP_socket_send
mov [esp+32], eax
ret
.tcp:
mov [esp+32], eax
ret
;--------
.raw:
cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP
je .raw_ip
cmp [eax + SOCKET_head.Protocol], IP_PROTO_ICMP
je .raw_icmp
jmp s_error
;--------
.raw_ip:
mov [esp+32], eax
ret
.raw_icmp:
; sub ecx, ICMP_Packet.Data
; mov esi, edx
; push ax
; call IPv4_get_frgmnt_num
; mov dx, ax
; pop ax
; shl edx, 16
; mov dh , [esi + ICMP_Packet.Type]
; mov dl , [esi + ICMP_Packet.Code]
; mov di , [esi + ICMP_Packet.Identifier]
; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's
; shl edi, 16
; mov di , [esi + ICMP_Packet.SequenceNumber]
; add esi, ICMP_Packet.Data
; mov ebx, [eax + SOCKET.LocalIP]
; mov eax, [eax + SOCKET.RemoteIP]
; call ICMP_create_packet
mov [esp+32], eax
ret
;-----------------------------------------------
;
; SOCKET_find_free_port (local port)
;
; works with INET byte order
;
; IN: type in ecx (TCP/UDP)
; OUT: bx = 0 on error, portnumber otherwise
;
;-----------------------------------------------
align 4
socket_find_port:
DEBUGF 1,"Socket_find_free_port\n"
cmp ecx, IP_PROTO_UDP
je .udp
cmp ecx, IP_PROTO_TCP
je .tcp
.udp:
mov bx, [last_UDP_port]
je .continue
.tcp:
mov bx, [last_TCP_port]
.continue:
inc bx
.check_only:
mov esi, net_sockets
.next_socket:
mov esi, [esi + SOCKET_head.NextPtr]
or esi, esi
jz .port_ok
cmp [esi + SOCKET_head.Type], ecx
jne .next_socket
rol bx, 8
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
rol bx, 8 ; this doesnt change the zero flag, does it ?
jne .next_socket
cmp bx, MAX_EPHEMERAL_PORT
jle .continue
; todo: WRAP!
; mov [last_UDP_port], MIN_EPHEMERAL_PORT
.exit:
xor ebx, ebx
.port_ok:
rol bx, 8
ret
;-----------------------------------------------
;
; SOCKET_check_port (local port)
;
; works with INET byte order
;
; IN: type in ecx (TCP/UDP)
; port to check in bx
; OUT: bx = 0 on error, unchanged otherwise
;
;-----------------------------------------------
align 4
socket_check_port:
mov esi, net_sockets
.next_socket:
mov esi, [esi + SOCKET_head.NextPtr]
or esi, esi
jz .port_ok
cmp [esi + SOCKET_head.Type], ecx
jne .next_socket
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
jne .next_socket
xor ebx, ebx
.port_ok:
ret
;-----------------------------------------------
;
; SOCKET_internal_receiver
;
; Updates a socket with received data
;
; Note: the mutex must already be set !
;
; IN: eax = socket ptr
; ecx = size
; esi = pointer to buffer
; edi = offset
;
; OUT: xxx
;
;-----------------------------------------------
align 4
socket_internal_receiver:
DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x\n", esi, edi
push edi ; offset
push ecx ; size
push esi ; data_ptr
mov esi, esp
add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
DEBUGF 1,"Queued packet successfully\n"
add esp, 4*3
mov [eax + SOCKET_head.lock], 0
; flag an event to the application
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
.next_pid:
cmp [esi], edx
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
ret
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
mov [check_idle_semaphore], 200
ret
.full:
DEBUGF 1,"Socket %x is full!\n",eax
mov [eax + SOCKET_head.lock], 0
call kernel_free
add esp, 8
ret
; Allocate memory for socket data and put new socket into the list
; Newly created socket is initialized with calling PID and number and
; put into beginning of list (which is a fastest way).
;
; @return socket structure address in EAX
;
proc net_socket_alloc stdcall uses ebx ecx edx edi
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax
; check if we can allocate needed amount of memory
or eax, eax
jz .exit
; zero-initialize allocated memory
push eax
mov edi, eax
mov ecx, SOCKETBUFFSIZE / 4
; cld
xor eax, eax
rep stosd
pop eax
init_queue (eax + 2048)
; add socket to the list by changing pointers
mov ebx, net_sockets
push [ebx + SOCKET_head.NextPtr]
mov [ebx + SOCKET_head.NextPtr], eax
mov [eax + SOCKET_head.PrevPtr], ebx
pop ebx
mov [eax + SOCKET_head.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET_head.PrevPtr], eax
@@: ; set socket owner PID to the one of calling process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET_head.PID], ebx
; find first free socket number and use it
;mov edx, ebx
mov ebx, net_sockets
xor ecx, ecx
.next_socket_number:
inc ecx
.next_socket:
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .last_socket_number
cmp [ebx + SOCKET_head.Number], ecx
jne .next_socket
;cmp [ebx + SOCKET.PID], edx
;jne .next_socket
mov ebx, net_sockets
jmp .next_socket_number
.last_socket_number:
mov [eax + SOCKET_head.Number], ecx
.exit:
ret
endp
; Free socket data memory and pop socket off the list
;
; @param sockAddr is a socket structure address
;
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
mov eax, [sockAddr]
DEBUGF 1, "K : net_socket_free (0x%x)\n", eax
; check if we got something similar to socket structure address
or eax, eax
jz .error
; make sure sockAddr is one of the socket addresses in the list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
; okay, we found the correct one
; remove it from the list first, changing pointers
mov ebx, [eax + SOCKET_head.NextPtr]
mov eax, [eax + SOCKET_head.PrevPtr]
mov [eax + SOCKET_head.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET_head.PrevPtr], eax
lea ebx, [eax + SOCKET_head.lock]
call wait_mutex
@@: ; and finally free the memory structure used
stdcall kernel_free, [sockAddr]
ret
.error:
DEBUGF 1, "K : failed\n"
ret
endp
; Get socket structure address by its number
; Scan through sockets list to find the socket with specified number.
; This proc uses SOCKET.PID indirectly to check if socket is owned by
; calling process.
;
; @param sockNum is a socket number
; @return socket structure address or 0 (not found) in EAX
;
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
mov eax, [sockNum]
; check if we got something similar to socket number
or eax, eax
jz .error
; scan through sockets list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp [ebx + SOCKET_head.Number], eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
; okay, we found the correct one
mov eax, ebx
ret
.error:
xor eax, eax
ret
endp
; Get socket number by its structure address
; Scan through sockets list to find the socket with specified address.
; This proc uses SOCKET.PID indirectly to check if socket is owned by
; calling process.
;
; @param sockAddr is a socket structure address
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
;
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
mov eax, [sockAddr]
; check if we got something similar to socket structure address
or eax, eax
jz .error
; scan through sockets list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
; okay, we found the correct one
mov eax, [ebx + SOCKET_head.Number]
ret
.error:
xor eax, eax
ret
endp