global _start ; constants SYS_READ equ 0 SYS_WRITE equ 1 SYS_CLOSE equ 3 SYS_POLL equ 7 SYS_SENDFILE equ 40 SYS_SOCKET equ 41 SYS_ACCEPT equ 43 SYS_SHUTDOWN equ 48 SYS_BIND equ 49 SYS_LISTEN equ 50 SYS_EXIT equ 60 SYS_FCNTL equ 72 SYS_UNLINK equ 87 STDOUT equ 1 AF_UNIX equ 1 SOCK_STREAM equ 1 F_GETFL equ 3 F_SETFL equ 4 O_NONBLOCK equ 2048 POLLIN equ 1 POLLOUT equ 4 POLLERR equ 8 POLLNVAL equ 32 ; TODO(?) POLLPRI: see poll(2), tcp(7) SHUT_RDWR equ 2 ;STATE_READING equ 0 ;STATE_WRITING equ 1 ; offsets into client struct OFFSET_CLIENT_FD equ 0 OFFSET_CLIENT_STATE equ 4 OFFSET_CLIENT_BUFFER_LEN equ 5 OFFSET_CLIENT_BUFFER equ 6 pollfd_size equ 4 + 2 + 2 ; $ man 2 poll pollfds_capacity equ 100 client_buffer_size equ 255 ; fd, state, buffer_len, buffer client_size equ 4 + 2 + client_buffer_size clients_capacity equ pollfds_capacity - 1 SECTION .data server_path db "server.sock", 0x00 server_path_len equ $ - server_path sockaddr_size equ 2 + 108 ; $ man 7 unix goodbye db "goodbye", 0x0a goodbye_len equ $ - goodbye pollfds_len dq 0 clients_len dq 0 SECTION .bss sockaddr resb sockaddr_size pollfds resb pollfd_size * pollfds_capacity clients resb (4 + client_size) * clients_capacity SECTION .text %include "server.s" %include "readline.s" %include "clients.s" %include "pollfds.s" %include "client.s" _start: call make_server mov rbx, rax ; server fd mov rdi, rbx mov rsi, POLLIN call pollfds__append poll: mov rax, SYS_POLL mov rdi, pollfds mov rsi, [pollfds_len] mov rdx, 5000 syscall cmp rax, 0 je poll jl exit ; poll(2) returned error TODO scan: mov r15, 0 ; Variables: ; r15 - pollfds index ; r14w - poll(2) revents ; r13d - fd ; r12 - client memory address scan__loop: cmp r15, [pollfds_len] jge poll mov r14w, [pollfds + r15 * pollfd_size + 6] cmp r14w, 0 jne scan__found add r15, 1 jmp scan__loop scan__found: mov r13, 0 mov r13d, [pollfds + r15 * pollfd_size] cmp r13d, ebx je scan__found__server scan__found__client: mov rdi, r13 call clients__search mov r12, rax cmp r12, 0 jl _client__not_stored mov r10w, r14w and r10w, POLLERR | POLLNVAL cmp r10w, 0 jne _client__error_or_eof mov r10w, r14w and r10w, POLLIN cmp r10w, 0 jne _client__pollin mov r10w, r14w and r10w, POLLOUT cmp r10w, 0 jne _client__pollout ; TODO what did poll(2) detect in this case? add r15, 1 jmp scan__loop _client__error_or_eof: mov rdi, r12 call clients__remove _client__not_stored: mov rdi, r13 call client__shutdown_close mov rdi, r15 call pollfds__remove jmp scan__loop _client__pollin: mov rdi, r13 mov rsi, r12 mov rdx, r15 call client__pollin cmp rax, 0 jle _client__error_or_eof add r15, rax jmp scan__loop _client__pollout: mov rdi, r13 mov rsi, r12 mov rdx, r15 call client__pollout cmp rax, 0 jle _client__error_or_eof add r15, 1 jmp scan__loop scan__found__server: cmp r14w, POLLIN jne exit mov rax, SYS_ACCEPT mov rdi, r13 mov rsi, 0 mov rdx, 0 syscall cmp rax, 0 jl exit ; accept(2) returned error TODO mov rdi, rax push rdi mov si, POLLIN call pollfds__append pop rdi call clients__append add r15, 1 jmp scan__loop return: ret exit: mov rax, SYS_EXIT mov rdi, 255 syscall