Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1543 → Rev 1542

/kernel/branches/net/network/socket.inc
28,13 → 28,12
 
.PID dd ? ; application process id
.Domain dd ? ; INET/UNIX/..
.Type dd ? ; RAW/STREAM/DGRAP
.Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
; .errorcode dd ?
.Type dd ? ; RAW/UDP/TCP/...
.Protocol dd ? ; ICMP/IPv4/ARP/
.errorcode dd ?
 
.options dd ?
.state dd ?
.backlog dw ? ; how many incomming connections that can be queued
 
.snd_proc dd ?
.rcv_proc dd ?
62,6 → 61,9
.LocalPort dw ?
.RemotePort dw ?
 
.backlog dw ? ; Backlog
.backlog_cur dw ? ; current size of queue for un-accept-ed connections
 
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
 
188,6 → 190,7
 
end virtual
 
 
struct socket_queue_entry
.data_ptr dd ?
.buf_ptr dd ?
200,11 → 203,10
 
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
SOCKET_QUEUE_LOCATION equ (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*socket_queue_entry.size - queue.data)
SOCKET_QUEUE_LOCATION equ SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*socket_queue_entry.size - queue.data
 
uglobal
net_sockets rd 4
last_socket_num dd ?
last_UDP_port dw ? ; These values give the number of the last used ephemeral port
last_TCP_port dw ? ;
endg
219,7 → 221,7
 
xor eax, eax
mov edi, net_sockets
mov ecx, 5
mov ecx, 4
rep stosd
 
@@:
301,6 → 303,9
cmp ecx, AF_INET4
jne .no_inet4
 
push [IP_LIST]
pop [eax + IP_SOCKET.LocalIP] ; fill in local ip number
 
cmp edx, SOCK_DGRAM
je .udp
 
315,8 → 320,8
 
align 4
.raw:
test esi, esi ; IP_PROTO_IP
jz .ip
; test esi, esi ; IP_PROTO_IP
; jz .ip
 
cmp esi, IP_PROTO_ICMP
je .icmp
332,29 → 337,61
align 4
.udp:
mov [eax + SOCKET.Protocol], IP_PROTO_UDP
 
call SOCKET_find_port ; fill in a local port number, application may change it later, or use this one
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION)
pop eax
 
mov [eax + SOCKET.snd_proc], SOCKET_send_udp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
 
ret
 
align 4
.tcp:
mov [eax + SOCKET.Protocol], IP_PROTO_TCP
mov [eax + SOCKET.snd_proc], SOCKET_send_tcp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_tcp
ret
 
call SOCKET_find_port ; fill in a local port number, application may change it later, or use this one
 
align 4
.ip:
mov [eax + SOCKET.snd_proc], SOCKET_send_ip
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
mov ebx, eax
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
mov [ebx + SOCKET.snd_proc], SOCKET_send_tcp
mov [ebx + SOCKET.rcv_proc], SOCKET_receive_tcp
 
ret
 
 
;align 4
; .ip:
;
; push eax
; init_queue (eax + SOCKET_QUEUE_LOCATION)
; pop eax
;
; mov [eax + SOCKET.snd_proc], SOCKET_send_ip
; mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
;
; ret
 
 
align 4
.icmp:
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION)
pop eax
 
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
 
ret
 
 
389,6 → 426,7
jmp s_error
 
.af_unix:
 
; TODO: write code here
 
mov dword [esp+32], 0
401,12 → 439,18
cmp esi, 6
jl s_error
 
push word [edx + 2]
pop word [eax + UDP_SOCKET.LocalPort]
mov bx, word [edx + 2]
test bx, bx
jz .use_preset_port
 
push dword [edx + 4]
pop [eax + IP_SOCKET.LocalIP]
call SOCKET_check_port
jz s_error
 
DEBUGF 1,"using local port: %u\n", bx
mov word [eax + UDP_SOCKET.LocalPort], bx
 
.use_preset_port:
 
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
444,11 → 488,6
jmp s_error
 
.af_inet4:
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST]
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
466,27 → 505,15
 
align 4
.udp:
lea ebx, [eax + SOCKET.lock]
call wait_mutex
 
push word [edx + 2]
pop [eax + UDP_SOCKET.RemotePort]
 
push dword [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
cmp [eax + UDP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
 
mov bx , word [edx + 2]
mov word [eax + UDP_SOCKET.RemotePort], bx
mov [eax + UDP_SOCKET.firstpacket], 0
DEBUGF 1,"remote port: %u\n",bx
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
mov ebx, dword [edx + 4]
mov dword [eax + IP_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 [eax + SOCKET.lock], 0
mov dword [esp+32], 0
ret
 
495,17 → 522,16
lea ebx, [eax + SOCKET.lock]
call wait_mutex
 
push word [edx + 2]
pop [eax + TCP_SOCKET.RemotePort]
; fill in remote port and IP
 
push dword [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
mov bx , word [edx + 2]
mov [eax + TCP_SOCKET.RemotePort], bx
DEBUGF 1,"remote port: %u\n", bx
 
cmp [eax + TCP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
mov ebx, dword [edx + 4]
mov [eax + IP_SOCKET.RemoteIP], ebx
 
;;;;;
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_state], TCB_SYN_SENT
mov ebx, [TCP_sequence_num]
515,38 → 541,23
 
TCP_sendseqinit eax
 
; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
;;;; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
 
push eax
call TCP_output
pop eax
 
mov ebx, eax
mov [eax + SOCKET.lock], 0
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
mov [ebx + SOCKET.lock], 0
mov dword [esp+32], 0
mov dword [esp+32], 0 ; success!
ret
 
align 4
.ip:
lea ebx, [eax + SOCKET.lock]
call wait_mutex
 
push dword [edx + 4]
pop dword [eax + IP_SOCKET.RemoteIP]
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
mov [eax + SOCKET.lock], 0
mov dword [esp+32], 0
mov dword [esp+32], 0 ; success!
ret
 
 
573,28 → 584,17
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
 
cmp [eax + TCP_SOCKET.LocalPort], 0
je s_error
; TODO: check local port number
 
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST]
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp edx, MAX_backlog
jle @f
jle .ok
mov edx, MAX_backlog
@@:
.ok:
 
mov [eax + SOCKET.backlog], dx
or [eax + SOCKET.options], SO_ACCEPTCON
mov [eax + TCP_SOCKET.backlog], dx
mov [eax + TCP_SOCKET.t_state], TCB_LISTEN
or [eax + SOCKET.options], SO_ACCEPTCON ;;;; TODO: set socket state to listen
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up sockets queue
pop eax
 
mov dword [esp+32], 0
 
ret
618,24 → 618,41
call SOCKET_num_to_ptr
jz s_error
 
test [eax + SOCKET.options], SO_ACCEPTCON
jz s_error
 
cmp word [eax + SOCKET.Domain], AF_INET4
jne s_error
je .af_inet4
 
jmp s_error
 
.af_inet4:
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
je .tcp
 
get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, s_error
jmp s_error
 
mov eax, [esi]
call SOCKET_ptr_to_num
jz s_error
mov dword [esp+32], eax
.tcp:
 
lea ebx, [eax + SOCKET.lock]
call wait_mutex
 
movzx ebx, [eax + TCP_SOCKET.backlog_cur]
test ebx, ebx
jz .unlock_err
 
dec [eax + TCP_SOCKET.backlog_cur] ;;;;
mov eax, [eax + TCP_SOCKET.end + (ebx-1)*4] ;;;;;
mov [eax + SOCKET.lock], 0 ;;;;
mov dword [esp+32], 0 ;;;;
 
call TCP_output ;;;;;
 
ret
 
.unlock_err:
mov [eax + SOCKET.lock], 0
jmp s_error
 
 
;-----------------------------------------------------------------
;
; SOCKET_close
821,19 → 838,19
ret
 
 
align 4
SOCKET_send_ip:
;align 4
;SOCKET_send_ip:
;
; DEBUGF 1,"type: IP\n"
;
; mov ecx, esi
; mov esi, edx
;
; call IPv4_output_raw
;
; mov dword [esp+32], eax
; ret
 
DEBUGF 1,"type: IP\n"
 
mov ecx, esi
mov esi, edx
 
call IPv4_output_raw
 
mov dword [esp+32], eax
ret
 
align 4
SOCKET_send_icmp:
 
1092,12 → 1109,8
align 4
SOCKET_ring_create:
 
push esi
mov esi, eax
 
push edx
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
 
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
mov [esi + RING_BUFFER.start_ptr], eax
1106,8 → 1119,6
mov [esi + RING_BUFFER.size], 0
add eax, SOCKET_MAXDATA
mov [esi + RING_BUFFER.end_ptr], eax
mov eax, esi
pop esi
 
ret
 
1280,7 → 1291,7
call SOCKET_check
jz .error
 
push eax ecx esi
push ecx esi
 
; socket exists, now try to flag an event to the application
 
1308,7 → 1319,7
DEBUGF 1,"SOCKET_notify_owner: succes!\n"
 
.error2:
pop esi ecx eax
pop esi ecx
 
.error:
 
1352,12 → 1363,9
mov [eax + SOCKET.rcv_proc], s_error
 
; find first free socket number and use it
mov ecx, [last_socket_num]
xor ecx, ecx
.next_socket_number:
inc ecx
jz .next_socket_number ; avoid socket nr 0
cmp ecx, -1
je .next_socket_number ; avoid socket nr -1
mov ebx, net_sockets
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
1369,7 → 1377,6
jmp .next_socket_number
 
.last_socket:
mov [last_socket_num], ecx
mov [eax + SOCKET.Number], ecx
DEBUGF 1, "SOCKET_alloc: number=%u\n", ecx
mov edi, ecx
1462,58 → 1469,40
.error:
ret
 
;------------------------------------
;
; SOCKET_fork
;
; Create a child socket
;
 
; IN: socket nr in ebx
; OUT: child socket nr in eax
;
;-----------------------------------
; OUT: socket nr in eax
; preserves edx
 
align 4
SOCKET_fork:
 
DEBUGF 1,"SOCKET_fork: %x\n", ebx
;; Exit if backlog queue is full
; mov ax, [ebx + TCP_SOCKET.backlog_cur]
; cmp ax, [ebx + TCP_SOCKET.backlog]
; jae .exit
 
; Exit if backlog queue is full
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
cmp ax, [ebx + SOCKET.backlog]
jge .fail
 
; Allocate new socket
call SOCKET_alloc
jz .fail
;;; jz .fail
 
push esi ecx edi
push eax
mov esi, esp
add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
pop eax
 
; Copy structure from current socket to new
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
lea esi, [ebx + SOCKET.PID]
; Copy structure from current socket to new, (including lock!)
; We start at PID to reserve the socket num, and the 2 pointers at beginning of socket
lea esi, [edx + SOCKET.PID]
lea edi, [eax + SOCKET.PID]
mov ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
mov ecx, (TCP_SOCKET.end - SOCKET.PID + 3)/4
rep movsd
 
and [eax + SOCKET.options], not SO_ACCEPTCON
;; Push pointer to new socket to queue
; movzx ecx, [ebx + TCP_SOCKET.backlog_cur]
; inc [ebx + TCP_SOCKET.backlog_cur]
; mov [ebx + TCP_SOCKET.end + ecx*4], eax
 
call SOCKET_notify_owner
pop edi ecx esi
;;;; mov [eax + IP_SOCKET.RemoteIP], esi ; IP source address
 
ret
 
.fail2:
add esp, 4+4+4
.fail:
DEBUGF 1,"SOCKET_fork: failed\n"
xor eax, eax
ret
 
 
;---------------------------------------------------
;
; SOCKET_num_to_ptr