27,15 → 27,15 |
|
PID dd ? ; process ID |
TID dd ? ; thread ID |
Domain dd ? ; INET4/INET6/LOCAL/.. |
Domain dd ? ; INET/LOCAL/.. |
Type dd ? ; RAW/STREAM/DGRAM |
Protocol dd ? ; UDP/TCP/ARP/ICMP |
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP |
errorcode dd ? |
device dd ? ; device pointer, paired socket pointer if it's a local socket |
device dd ? ; driver pointer, socket pointer if it's an LOCAL socket |
|
options dd ? |
state dd ? |
backlog dw ? ; number of incoming connections that can be queued |
backlog dw ? ; how many incoming connections that can be queued |
|
snd_proc dd ? |
rcv_proc dd ? |
47,8 → 47,6 |
|
LocalIP rd 4 ; network byte order |
RemoteIP rd 4 ; network byte order |
ttl db ? |
rb 3 ; align |
|
ends |
|
147,11 → 145,19 |
|
struct UDP_SOCKET IP_SOCKET |
|
LocalPort dw ? ; in network byte order |
RemotePort dw ? ; in network byte order |
LocalPort dw ? ; network byte order |
RemotePort dw ? ; network byte order |
|
ends |
|
|
struct ICMP_SOCKET IP_SOCKET |
|
Identifier dw ? |
|
ends |
|
|
struct RING_BUFFER |
|
mutex MUTEX |
178,15 → 184,7 |
|
ends |
|
struct socket_options |
|
level dd ? |
optname dd ? |
optlen dd ? |
optval dd ? |
|
ends |
|
SOCKETBUFFSIZE = 4096 ; in bytes |
|
SOCKET_QUEUE_SIZE = 10 ; maximum number of incoming packets queued for 1 socket |
198,7 → 196,7 |
|
net_sockets rd 4 |
last_socket_num dd ? |
last_UDP_port dw ? ; last used ephemeral port |
last_UDP_port dw ? ; These values give the number of the last used ephemeral port |
last_TCP_port dw ? ; |
socket_mutex MUTEX |
|
205,11 → 203,11 |
endg |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_init ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_init |
; |
;----------------------------------------------------------------- |
macro SOCKET_init { |
|
xor eax, eax |
240,11 → 238,11 |
|
} |
|
;-----------------------------------------------------------------; |
; ; |
; Sockets API (system function 75) ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; Socket API (function 74) |
; |
;----------------------------------------------------------------- |
align 4 |
sys_socket: |
|
277,19 → 275,16 |
|
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_open: Create a new socket. ; |
; ; |
; IN: ecx = domain ; |
; edx = type ; |
; esi = protocol ; |
; ; |
; OUT: eax = socket number ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_open |
; |
; IN: domain in ecx |
; type in edx |
; protocol in esi |
; OUT: eax is socket num, -1 on error |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_open: |
|
318,8 → 313,6 |
cmp ecx, AF_INET4 |
jne .no_inet4 |
|
mov [eax + IP_SOCKET.ttl], 128 |
|
cmp edx, SOCK_DGRAM |
je .udp |
|
361,10 → 354,6 |
|
align 4 |
.udp: |
push eax |
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
pop eax |
|
mov [eax + SOCKET.Protocol], IP_PROTO_UDP |
mov [eax + SOCKET.snd_proc], SOCKET_send_udp |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
384,10 → 373,6 |
|
align 4 |
.raw_ip: |
push eax |
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
pop eax |
|
mov [eax + SOCKET.snd_proc], SOCKET_send_ip |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
mov [eax + SOCKET.connect_proc], IPv4_connect |
396,10 → 381,6 |
|
align 4 |
.raw_icmp: |
push eax |
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
pop eax |
|
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp |
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
mov [eax + SOCKET.connect_proc], IPv4_connect |
416,19 → 397,16 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_bind: Bind to a local port. ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to sockaddr struct ; |
; esi = length of sockaddr struct ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; 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: |
|
435,7 → 413,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
cmp esi, 2 |
509,19 → 486,16 |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_connect: Connect to the remote host. ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to sockaddr struct ; |
; esi = length of sockaddr struct ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; 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: |
|
528,7 → 502,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
cmp esi, 8 |
570,18 → 543,15 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_listen: Listen for incoming connections. ; |
; ; |
; IN: ecx = socket number ; |
; edx = backlog in edx ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_listen |
; |
; IN: socket number in ecx |
; backlog in edx |
; OUT: eax is socket num, -1 on error |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_listen: |
|
588,7 → 558,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
cmp [eax + SOCKET.Domain], AF_INET4 |
639,19 → 608,16 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_accept: Accept an incoming connection. ; |
; ; |
; IN: ecx = socket number (of listening socket) ; |
; edx = ptr to sockaddr struct ; |
; esi = length of sockaddr struct ; |
; ; |
; OUT: eax = newly created socket num ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; 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: |
|
658,7 → 624,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
test [eax + SOCKET.options], SO_ACCEPTCON |
676,17 → 641,16 |
; Ok, we got a socket ptr |
mov eax, [esi] |
|
; Verify that it is (still) a valid socket |
call SOCKET_check |
jz .invalid |
|
; Change sockets thread owner ID to that of the current thread |
; Change thread ID to that of the current thread |
mov ebx, [TASK_BASE] |
mov ebx, [ebx + TASKDATA.pid] |
mov [eax + SOCKET.TID], ebx |
|
; Return socket number to caller |
mov eax, [eax + SOCKET.Number] |
; Convert it to a socket number |
call SOCKET_ptr_to_num |
jz .invalid ; FIXME ? |
|
; and return it to caller |
mov [esp+32], eax |
ret |
|
712,17 → 676,14 |
mov dword[esp+32], -1 |
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_close: Close the socket (and connection). ; |
; ; |
; IN: ecx = socket number ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_close |
; |
; IN: socket number in ecx |
; OUT: eax is socket num, -1 on error |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_close: |
|
729,7 → 690,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
mov dword[esp+32], 0 ; The socket exists, so we will succeed in closing it. |
752,6 → 712,7 |
ret |
|
.tcp: |
|
call TCP_usrclosed |
|
test eax, eax |
758,6 → 719,7 |
jz @f |
call TCP_output ; If connection is not closed yet, send the FIN |
@@: |
|
ret |
|
|
767,21 → 729,17 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_receive: Receive some data from the remote end. ; |
; ; |
; IN: ecx = socket number ; |
; edx = addr to application buffer ; |
; edx = length of application buffer ; |
; edi = flags ; |
; ; |
; OUT: eax = number of bytes copied ; |
; eax = -1 on error ; |
; eax = 0 when socket has been closed by the remote end ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; 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_receive: |
|
788,7 → 746,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
.loop: |
805,8 → 762,8 |
test edi, MSG_DONTWAIT |
jnz .return_err |
|
test [eax + SOCKET.options], SO_NONBLOCK |
jnz .return_err |
; test [eax + SOCKET.options], SO_NONBLOCK |
; jnz .return_err |
|
call SOCKET_block |
jmp .loop |
825,7 → 782,7 |
.last_data: |
test ecx, ecx |
jz .return |
call SOCKET_notify ; Call me again! |
call SOCKET_notify |
jmp .return |
|
|
836,9 → 793,6 |
|
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n" |
|
test edi, MSG_PEEK |
jnz .peek |
|
mov ebx, esi ; buffer length |
|
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success. |
870,11 → 824,7 |
|
call NET_BUFF_free |
pop ecx eax ; return number of bytes copied to application |
cmp [eax + SOCKET_QUEUE_LOCATION + queue.size], 0 |
je @f |
call SOCKET_notify ; Queue another network event |
@@: |
xor ebx, ebx ; errorcode = 0 (no error) |
xor ebx, ebx |
ret |
|
.too_small: |
888,15 → 838,6 |
pop ebx |
ret |
|
.peek: |
xor ebx, ebx |
xor ecx, ecx |
cmp [eax + SOCKET_QUEUE_LOCATION + queue.size], 0 |
je @f |
mov esi, [eax + SOCKET_QUEUE_LOCATION + queue.r_ptr] |
mov ecx, [esi + socket_queue_entry.data_size] |
@@: |
ret |
|
|
align 4 |
960,20 → 901,18 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_send: Send some data to the remote end. ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to data ; |
; esi = data length ; |
; edi = flags ; |
; ; |
; OUT: eax = number of bytes sent ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; 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: |
|
980,7 → 919,6 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
mov ecx, esi |
1037,14 → 975,14 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n" |
|
mov [esp+32], ecx |
call IPv4_output_raw |
call IPv4_output_raw ; FIXME: IPv4_output_raw should return error codes! |
cmp eax, -1 |
je .error |
ret |
|
.error: |
mov dword[esp+32], eax |
mov dword[esp+20], ebx |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE |
ret |
|
|
1054,14 → 992,14 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n" |
|
mov [esp+32], ecx |
call ICMP_output_raw |
call ICMP_output_raw ; FIXME: errorcodes |
cmp eax, -1 |
je .error |
ret |
|
.error: |
mov dword[esp+32], eax |
mov dword[esp+20], ebx |
mov dword[esp+32], -1 |
mov dword[esp+20], EMSGSIZE |
ret |
|
|
1130,30 → 1068,26 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_get_options: Read a socket option ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to socket options struct ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
align 4 |
SOCKET_get_opt: |
|
; FIXME: |
;----------------------------------------------------------------- |
; |
; SOCKET_get_options |
; |
; IN: ecx = socket number |
; edx = pointer to the options: |
; dd level, optname, optval, optlen |
; OUT: -1 on error |
; |
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP. |
; TODO: find best way to notify that send()'ed data were acknowledged |
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*. |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_get_opt: |
|
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n" |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
cmp dword [edx], IP_PROTO_TCP |
1192,18 → 1126,17 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_set_options: Set a socket option. ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to socket options struct ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
|
;----------------------------------------------------------------- |
; |
; SOCKET_set_options |
; |
; IN: ecx = socket number |
; edx = pointer to the options: |
; dd level, optname, optlen, optval |
; OUT: -1 on error |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_set_opt: |
|
1210,23 → 1143,24 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n" |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
cmp [edx + socket_options.level], IP_PROTO_IP |
je .ip |
cmp [edx + socket_options.level], SOL_SOCKET |
cmp dword [edx], SOL_SOCKET |
jne .invalid |
|
.socket: |
cmp [edx + socket_options.optname], SO_BINDTODEVICE |
jne .invalid |
cmp dword [edx+4], SO_BINDTODEVICE |
je .bind |
|
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+20], EINVAL |
ret |
|
.bind: |
cmp [edx + socket_options.optlen], 0 |
cmp dword[edx+8], 0 |
je .unbind |
|
movzx edx, byte[edx + socket_options.optval] |
movzx edx, byte[edx + 12] |
cmp edx, NET_DEVICES_MAX |
ja .invalid |
|
1246,42 → 1180,25 |
mov dword[esp+32], 0 ; success! |
ret |
|
.ip: |
cmp [edx + socket_options.optname], IP_TTL |
jne .invalid |
|
.ttl: |
mov bl, byte[edx + socket_options.optval] |
mov [eax + IP_SOCKET.ttl], bl |
|
mov dword[esp+32], 0 ; success! |
ret |
|
.already: |
mov dword[esp+20], EALREADY |
mov dword[esp+32], -1 |
ret |
|
.invalid: |
mov dword[esp+20], EINVAL |
mov dword[esp+32], -1 |
ret |
|
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_pair: Allocate a pair of linked local sockets. ; |
; ; |
; IN: / ; |
; ; |
; OUT: eax = socket1 num on success ; |
; eax = -1 on error ; |
; ebx = socket2 num on success ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_pair |
; |
; Allocates a pair of linked LOCAL domain sockets |
; |
; IN: / |
; OUT: eax is socket1 num, -1 on error |
; ebx is socket2 num |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_pair: |
|
1319,7 → 1236,7 |
lea eax, [eax + STREAM_SOCKET.rcv] |
call SOCKET_ring_create |
test eax, eax |
jz .nomem2 |
jz .nomem1 |
|
lea eax, [ebx + STREAM_SOCKET.rcv] |
call SOCKET_ring_create |
1329,31 → 1246,26 |
ret |
|
.nomem2: |
mov eax, [esp+20] |
mov eax, ebx |
call SOCKET_free |
|
.nomem1: |
mov eax, [esp+32] |
call SOCKET_free |
|
mov dword[esp+32], -1 |
mov dword[esp+20], ENOMEM |
mov dword[esp+28], ENOMEM |
ret |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_debug: Copy socket variables to application buffer. ; |
; ; |
; IN: ecx = socket number ; |
; edx = pointer to application buffer ; |
; ; |
; OUT: eax = 0 on success ; |
; eax = -1 on error ; |
; ebx = errorcode on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_debug |
; |
; Copies socket variables to application buffer |
; |
; IN: ecx = socket number |
; edx = pointer to buffer |
; |
; OUT: -1 on error |
;----------------------------------------------------------------- |
align 4 |
SOCKET_debug: |
|
1365,7 → 1277,6 |
jz .returnall |
|
call SOCKET_num_to_ptr |
test eax, eax |
jz .invalid |
|
mov esi, eax |
1392,31 → 1303,22 |
|
.invalid: |
mov dword[esp+32], -1 |
mov dword[esp+20], EINVAL |
mov dword[esp+28], EINVAL |
ret |
|
|
;-----------------------------------------------------------------; |
; ____ ____ ; |
; \ / End of sockets API \ / ; |
; \/ \/ ; |
; () Internally used functions follow () ; |
; ; |
;-----------------------------------------------------------------; |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_find_port: ; |
; Fill in the local port number for TCP and UDP sockets ; |
; This procedure always works because the number of sockets is ; |
; limited to a smaller number then the number of possible ports ; |
; ; |
; IN: eax = socket pointer ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_find_port |
; |
; Fills in the local port number for TCP and UDP sockets |
; This procedure always works because the number of sockets is |
; limited to a smaller number then the number of possible ports |
; |
; IN: eax = socket pointer |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_find_port: |
|
1465,20 → 1367,19 |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_check_port (to be used with AF_INET only!) ; |
; ; |
; Checks if a local port number is unused ; |
; If the proposed port number is unused, it is filled in in the ; |
; socket structure ; |
; ; |
; IN: eax = socket ptr ; |
; bx = proposed socket number (network byte order) ; |
; ; |
; OUT: ZF = set on error ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_check_port (to be used with AF_INET only!) |
; |
; Checks if a local port number is unused |
; If the proposed port number is unused, it is filled in in the socket structure |
; |
; IN: eax = socket ptr (to find out if its a TCP/UDP socket) |
; bx = proposed socket number (network byte order) |
; |
; OUT: ZF = set on error |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_check_port: |
|
1528,20 → 1429,22 |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_input: Update a (stateless) socket with received data. ; |
; ; |
; Note: The socket's mutex should already be set ! ; |
; ; |
; IN: eax = socket ptr ; |
; ecx = data size ; |
; esi = ptr to data ; |
; [esp] = ptr to buf ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_input |
; |
; Updates a (stateless) socket with received data |
; |
; Note: the mutex should already be set ! |
; |
; IN: eax = socket ptr |
; ecx = data size |
; esi = ptr to data |
; [esp] = ptr to buf |
; |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_input: |
|
1571,21 → 1474,14 |
call mutex_unlock |
popa |
|
add esp, 8 |
call NET_BUFF_free |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_ring_create: Create a ringbuffer for sockets. ; |
; ; |
; IN: eax = ptr to ring struct ; |
; ; |
; OUT: eax = 0 on error ; |
; eax = start ptr ; |
; ; |
;-----------------------------------------------------------------; |
;-------------------------- |
; |
; eax = ptr to ring struct (just a buffer of the right size) |
; |
align 4 |
SOCKET_ring_create: |
|
1598,7 → 1494,7 |
test eax, eax |
jz .fail |
|
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_create: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax |
|
pusha |
lea ecx, [esi + RING_BUFFER.mutex] |
1613,25 → 1509,23 |
mov [esi + RING_BUFFER.end_ptr], eax |
mov eax, esi |
|
pop esi |
ret |
|
.fail: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_ring_create: Out of memory!\n" |
pop esi |
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_ring_write: Write data to ring buffer. ; |
; ; |
; IN: eax = ptr to ring struct ; |
; ecx = data size ; |
; esi = ptr to data ; |
; ; |
; OUT: ecx = number of bytes stored ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_ring_write |
; |
; Adds data to a stream socket, and updates write pointer and size |
; |
; IN: eax = ptr to ring struct |
; ecx = data size |
; esi = ptr to data |
; |
; OUT: ecx = number of bytes stored |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_ring_write: |
|
1691,22 → 1585,22 |
|
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_ring_read: Read from ring buffer ; |
; ; |
; IN: eax = ring struct ptr ; |
; ecx = bytes to read ; |
; edx = offset ; |
; edi = ptr to buffer start ; |
; ; |
; OUT: eax = unchanged ; |
; ecx = number of bytes read (0 on error) ; |
; edx = destroyed ; |
; esi = destroyed ; |
; edi = ptr to buffer end ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_ring_read |
; |
; IN: eax = ring struct ptr |
; ecx = bytes to read |
; edx = offset |
; edi = ptr to buffer start |
; |
; OUT: eax = unchanged |
; ecx = number of bytes read (0 on error) |
; edx = destroyed |
; esi = destroyed |
; edi = ptr to buffer end |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_ring_read: |
|
1765,16 → 1659,18 |
jmp .copy |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_ring_free: Free data from a ringbuffer ; |
; ; |
; IN: eax = ptr to ring struct ; |
; ecx = data size ; |
; ; |
; OUT: ecx = number of freed bytes ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_ring_free |
; |
; Free's some bytes from the ringbuffer |
; |
; IN: eax = ptr to ring struct |
; ecx = data size |
; |
; OUT: ecx = number of bytes free-ed |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_ring_free: |
|
1815,15 → 1711,16 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_block: Suspend the thread attached to a socket. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: eax = unchanged ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_block |
; |
; Suspends the thread attached to a socket |
; |
; IN: eax = socket ptr |
; OUT: eax = unchanged |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_block: |
|
1857,15 → 1754,16 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_notify: Wake up socket owner thread. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: eax = unchanged ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_notify |
; |
; notify's the owner of a socket that something happened |
; |
; IN: eax = socket ptr |
; OUT: eax = unchanged |
; |
;----------------------------------------------------------------- |
align 4 |
SOCKET_notify: |
|
1904,7 → 1802,7 |
test [eax + SOCKET.state], SS_BLOCKED |
jnz .un_block |
|
; Socket and thread exists and socket is of non blocking type. |
; socket and thread exists and socket is of non blocking type. |
; We'll try to flag an event to the thread. |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK |
1915,7 → 1813,7 |
|
|
.un_block: |
; Socket and thread exists and socket is of blocking type |
; socket and thread exists and socket is of blocking type |
; We'll try to unblock it. |
and [eax + SOCKET.state], not SS_BLOCKED ; Clear the 'socket is blocked' flag |
mov [esi + TASKDATA.state], 0 ; Run the thread |
1925,20 → 1823,19 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_alloc: ; |
; Allocate memory for socket and put new socket into the list. ; |
; Newly created socket is initialized with calling PID and socket ; |
; number. ; |
; ; |
; IN: / ; |
; ; |
; OUT: eax = socket ptr on success ; |
; eax = 0 on error ; |
; edi = socket number on success ; |
; ; |
;-----------------------------------------------------------------; |
;-------------------------------------------------------------------- |
; |
; SOCKET_alloc |
; |
; 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). |
; |
; IN: / |
; OUT: eax = 0 on error, socket ptr otherwise |
; edi = socket number |
; |
;-------------------------------------------------------------------- |
align 4 |
SOCKET_alloc: |
|
1945,9 → 1842,9 |
push ebx |
|
stdcall kernel_alloc, SOCKETBUFFSIZE |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax |
or eax, eax |
jz .nomem |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax |
jz .exit |
|
; zero-initialize allocated memory |
push eax |
2028,15 → 1925,12 |
mov ecx, socket_mutex |
call mutex_unlock |
popa |
|
.exit: |
pop ebx |
|
ret |
|
.nomem: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_alloc: Out of memory!\n" |
pop ebx |
ret |
|
.not_yet: |
mov dword[esp+20], ENOTCONN |
mov dword[esp+32], -1 |
2043,17 → 1937,17 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_free: ; |
; Free socket data memory and remove socket from the list. ; |
; Caller should lock and unlock socket_mutex. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;---------------------------------------------------- |
; |
; SOCKET_free |
; |
; Free socket data memory and remove socket from the list |
; Caller should lock and unlock socket_mutex |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;---------------------------------------------------- |
align 4 |
SOCKET_free: |
|
2069,20 → 1963,17 |
call mutex_lock |
popa |
|
cmp [eax + SOCKET.Type], SOCK_STREAM |
jne .no_stream |
cmp [eax + SOCKET.Domain], AF_INET4 |
jnz .no_tcp |
|
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
jnz .no_tcp |
|
mov ebx, eax |
cmp [eax + STREAM_SOCKET.rcv.start_ptr], 0 |
je @f |
stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr] |
@@: |
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0 |
je @f |
stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr] |
@@: |
stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr] |
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr] |
mov eax, ebx |
.no_stream: |
.no_tcp: |
|
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax |
push eax ; this will be passed to kernel_free |
2109,22 → 2000,16 |
.error: |
ret |
|
.error1: |
pop ebx |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_free: error!\n" |
DEBUGF DEBUG_NETWORK_ERROR, "socket ptr=0x%x caller=0x%x\n", eax, [esp] |
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_fork: Create a child socket. ; |
; ; |
; IN: ebx = socket number ; |
; ; |
; OUT: eax = child socket number on success ; |
; eax = 0 on error ; |
; ; |
;-----------------------------------------------------------------; |
;------------------------------------ |
; |
; SOCKET_fork |
; |
; Create a child socket |
; |
; IN: socket nr in ebx |
; OUT: child socket nr in eax |
; |
;----------------------------------- |
align 4 |
SOCKET_fork: |
|
2173,16 → 2058,17 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_num_to_ptr: Get socket structure address by its number. ; |
; ; |
; IN: ecx = socket number ; |
; ; |
; OUT: eax = socket ptr ; |
; eax = 0 on error ; |
; ; |
;-----------------------------------------------------------------; |
;--------------------------------------------------- |
; |
; SOCKET_num_to_ptr |
; |
; Get socket structure address by its number |
; |
; IN: ecx = socket number |
; OUT: eax = 0 on error, socket ptr otherwise |
; ZF = set on error |
; |
;--------------------------------------------------- |
align 4 |
SOCKET_num_to_ptr: |
|
2194,13 → 2080,16 |
popa |
|
mov eax, net_sockets |
|
.next_socket: |
mov eax, [eax + SOCKET.NextPtr] |
test eax, eax |
or eax, eax |
jz .error |
cmp [eax + SOCKET.Number], ecx |
jne .next_socket |
|
test eax, eax |
|
pusha |
mov ecx, socket_mutex |
call mutex_unlock |
2220,17 → 2109,17 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_ptr_to_num: Get socket number by its address. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: eax = socket number ; |
; eax = 0 on error ; |
; ZF = set on error ; |
; ; |
;-----------------------------------------------------------------; |
;--------------------------------------------------- |
; |
; SOCKET_ptr_to_num |
; |
; Get socket number by its address |
; |
; IN: eax = socket ptr |
; OUT: eax = 0 on error, socket num otherwise |
; ZF = set on error |
; |
;--------------------------------------------------- |
align 4 |
SOCKET_ptr_to_num: |
|
2249,23 → 2138,22 |
ret |
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_check: Checks if the given ptr is really a socket ptr. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: eax = 0 on error ; |
; ZF = set on error ; |
; ; |
;-----------------------------------------------------------------; |
;--------------------------------------------------- |
; |
; SOCKET_check |
; |
; checks if the given value is really a socket ptr |
; |
; IN: eax = socket ptr |
; OUT: eax = 0 on error, unchanged otherwise |
; ZF = set on error |
; |
;--------------------------------------------------- |
align 4 |
SOCKET_check: |
|
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax |
|
test eax, eax |
jz .error |
push ebx |
mov ebx, net_sockets |
|
2280,24 → 2168,21 |
mov eax, ebx |
test eax, eax |
pop ebx |
ret |
|
.error: |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_check: called with argument 0\n" |
DEBUGF DEBUG_NETWORK_ERROR, "stack: 0x%x, 0x%x, 0x%x\n", [esp], [esp+4], [esp+8] |
ret |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_check_owner: Check if the caller app owns the socket. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: ZF = true/false ; |
; ; |
;-----------------------------------------------------------------; |
;--------------------------------------------------- |
; |
; SOCKET_check_owner |
; |
; checks if the caller application owns the socket |
; |
; IN: eax = socket ptr |
; OUT: ZF = true/false |
; |
;--------------------------------------------------- |
align 4 |
SOCKET_check_owner: |
|
2314,18 → 2199,18 |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_process_end: ; |
; Kernel calls this function when a certain process ends. ; |
; This function will check if the process had any open sockets, ; |
; and update them accordingly (clean up). ; |
; ; |
; IN: edx = pid ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;------------------------------------------------------ |
; |
; SOCKET_process_end |
; |
; Kernel calls this function when a certain process ends |
; This function will check if the process had any open sockets |
; And update them accordingly (clean up) |
; |
; IN: edx = pid |
; OUT: / |
; |
;------------------------------------------------------ |
align 4 |
SOCKET_process_end: |
|
2392,15 → 2277,15 |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_is_connecting: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_is_connecting |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_is_connecting: |
|
2408,19 → 2293,20 |
|
and [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.state], SS_ISCONNECTING |
|
ret |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_is_connected: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_is_connected |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_is_connected: |
|
2428,20 → 2314,21 |
|
and [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.state], SS_ISCONNECTED |
|
jmp SOCKET_notify |
|
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_is_disconnecting: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_is_disconnecting |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_is_disconnecting: |
|
2449,19 → 2336,20 |
|
and [eax + SOCKET.state], not (SS_ISCONNECTING) |
or [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE |
|
jmp SOCKET_notify |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_is_disconnected: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_is_disconnected |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_is_disconnected: |
|
2469,19 → 2357,21 |
|
and [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING) |
or [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE |
|
|
jmp SOCKET_notify |
|
|
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_cant_recv_more: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
;----------------------------------------------------------------- |
; |
; SOCKET_cant_recv_more |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_cant_recv_more: |
|
2488,19 → 2378,22 |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax |
|
or [eax + SOCKET.state], SS_CANTRCVMORE |
jmp SOCKET_notify |
|
call SOCKET_notify |
|
ret |
|
;-----------------------------------------------------------------; |
; ; |
; SOCKET_cant_send_more: Update socket state. ; |
; ; |
; IN: eax = socket ptr ; |
; ; |
; OUT: / ; |
; ; |
;-----------------------------------------------------------------; |
|
|
;----------------------------------------------------------------- |
; |
; SOCKET_cant_send_more |
; |
; IN: eax = socket ptr |
; OUT: / |
; |
;----------------------------------------------------------------- |
|
align 4 |
SOCKET_cant_send_more: |
|
2508,8 → 2401,11 |
|
or [eax + SOCKET.state], SS_CANTSENDMORE |
mov [eax + SOCKET.snd_proc], .notconn |
jmp SOCKET_notify |
|
call SOCKET_notify |
|
ret |
|
.notconn: |
mov dword[esp+20], ENOTCONN |
mov dword[esp+32], -1 |