diff --git a/client.s b/client.s new file mode 100644 index 0000000..073f42c --- /dev/null +++ b/client.s @@ -0,0 +1,104 @@ +; Errors (in rax): +; 0 - EOF +; -1024 - line too long +; other negative - from read(2) +; Arguments: +; rdi - fd +; rsi - address of client within clients array +; rdx - pollfds index +client__pollin: + push rdi + push rsi + push rdx + + mov r10, 0 + mov r10b, [rsi + 4 + 2] ; buffer_len + + mov rdx, 0 + mov dl, 255 + sub dl, r10b ; rdx = 255 - buffer_len + add rsi, 8 + add rsi, r10 + call readline + + mov r10, rdi + + pop rdx + pop rsi + pop rdi + + cmp rax, 0 + jle return + + add [rsi + 4 + 2], al ; buffer_len += rax + + cmp r10, 0 + jg client__pollin__complete_line + + add [rsi + 4 + 1], al ; line_len += rax + ret + +client__pollin__complete_line: + add [rsi + 4 + 1], r10b ; line_len += r10 + mov word [pollfds + rdx * pollfd_size + 4], POLLOUT + ret + +; rdi - fd +; rsi - address of client within clients array +; rdx - pollfds index +client__pollout: + push rdi + push rsi + push rdx + + mov rax, SYS_WRITE + mov rdx, 0 + mov dl, [rsi + 4 + 1] + add rsi, 8 + syscall + + pop rdx + pop rsi + pop rdi + + cmp rax, 0 + jl return + + mov r10, rsi + add r10, 8 + mov r11, 0 + mov r11b, [rsi + 4 + 2] + sub r11, rax + add r11, r10 + +client__pollout__shunt: + cmp r10, r11 + jge client__pollout__shunt__finished + mov r8b, [r10 + rax] + mov [r10], r8b + add r10, 1 + jmp client__pollout__shunt + +client__pollout__shunt__finished: + sub [rsi + 4 + 2], al ; buffer_len -= rax + sub [rsi + 4 + 1], al ; line_len -= rax + cmp byte [rsi + 4 + 1], 0 + je client__pollout__wrote_line + ret + +client__pollout__wrote_line: + mov word [pollfds + rdx * pollfd_size + 4], POLLIN + ret + +; rdi - fd +client__shutdown_close: + mov rax, SYS_SHUTDOWN + push rdi + mov rsi, SHUT_RDWR + syscall + + mov rax, SYS_CLOSE + pop rdi + syscall + + ret diff --git a/clients.s b/clients.s new file mode 100644 index 0000000..1af458b --- /dev/null +++ b/clients.s @@ -0,0 +1,69 @@ +; edi - fd +clients__append: + ; TODO check against client_capacity + mov r10, [clients_len] + imul r10, client_size + add r10, clients + mov [r10], edi + + add qword [clients_len], 1 + + mov r11, 4 + +clients__append__write_zeros: + cmp r11, 8 + jge return + mov byte [r10 + r11], 0 + add r11, 1 + jmp clients__append__write_zeros + +; edi - fd +clients__search: + mov r11, [clients_len] + imul r11, client_size + add r11, clients + mov r10, clients + +clients__search__loop: + cmp r10, r11 + jge clients__search__fail + mov r8d, [r10] + cmp r8d, edi + je clients__search__succ + add r10, client_size + jmp clients__search__loop + +clients__search__fail: + mov r10, -1 + +clients__search__succ: + mov rax, r10 + ret + +; rdi - address of client within clients array +clients__remove: + mov r10, [clients_len] + cmp r10, 1 + jle clients__clear + + add r10, -1 + mov [clients_len], r10 + + mov r10, 0 + mov r11, r10 + imul r11, client_size + add r11, clients + +clients__remove__loop: + cmp r10, client_size + jge return + mov r8b, [r11 + r10] + mov [rdi + r10], r8b + add r10, 1 + jmp clients__remove__loop + +; rdi - address of client within clients array +clients__clear: + mov r10, 0 + mov [clients_len], r10 + ret diff --git a/constants.c b/constants.c index 2e7aab3..8239355 100644 --- a/constants.c +++ b/constants.c @@ -14,5 +14,7 @@ void main() { printf("sizeof(short) %d\n", sizeof(short)); printf("POLLIN %d\n", POLLIN); printf("POLLOUT %d\n", POLLOUT); + printf("POLLERR %d\n", POLLERR); + printf("POLLNVAL %d\n", POLLNVAL); printf("SHUT_RDWR %d\n", SHUT_RDWR); } diff --git a/main.s b/main.s index 8905309..190f240 100644 --- a/main.s +++ b/main.s @@ -22,11 +22,19 @@ 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 + pollfd_size equ 4 + 2 + 2 ; $ man 2 poll pollfds_capacity equ 100 -client_size equ 1 + 256 + 256 ; state, line buffer, uri + +; fd, state, line_len, buffer_len, uri_len, buffer, uri +client_size equ 4 + 4 + 255 + 255 clients_capacity equ pollfds_capacity - 1 SECTION .data @@ -47,11 +55,14 @@ 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, rax + mov rdi, rbx mov rsi, POLLIN call pollfds__append @@ -63,144 +74,113 @@ poll: syscall cmp rax, 0 je poll - jl exit ; TODO handle this gracefully - mov rdi, rbx + jl exit ; poll(2) returned error TODO -; rdi - server fd -pollfds__scan: +scan: mov r15, 0 -pollfds__scan__loop: +; Variables: +; r15 - pollfds index +; r14w - poll(2) revents +; r13d - fd +; r12 - client memory address +scan__loop: cmp r15, [pollfds_len] jge poll - mov r10w, [pollfds + r15 * pollfd_size + 6] - cmp r10w, 0 - jne pollfds__scan__found + mov r14w, [pollfds + r15 * pollfd_size + 6] + cmp r14w, 0 + jne scan__found add r15, 1 - jmp pollfds__scan__loop + jmp scan__loop -pollfds__scan__found: - mov r14, 0 - mov r14d, [pollfds + r15 * pollfd_size] - cmp r14d, edi - je pollfds__scan__found__server +scan__found: + mov r13, 0 + mov r13d, [pollfds + r15 * pollfd_size] + cmp r13d, ebx + je scan__found__server -pollfds__scan__found__client: - ; TODO check r10w, incl for POLLNVAL & POLLERR - push rdi +scan__found__client: + mov rdi, r13 + call clients__search + mov r12, rax + cmp r12, 0 + jl _client__not_stored - mov rdi, r14 - call clients__append + mov r10w, r14w + and r10w, POLLERR | POLLNVAL + cmp r10w, 0 + jne _client__error - mov r12, [clients_len] - add r12, -1 - imul r12, client_size - add r12, clients - add r12, 4 + mov r10w, r14w + and r10w, POLLIN + cmp r10w, 0 + jne _client__pollin - mov rdi, r14 - mov rsi, r12 - mov rdx, 256 - call readline - cmp rax, 0 ; TODO - jl exit - ;push rax ; TODO + mov r10w, r14w + and r10w, POLLOUT + cmp r10w, 0 + jne _client__pollout - mov rdx, rax - mov rax, SYS_WRITE - mov rdi, r14 - mov rsi, r12 - syscall - cmp rax, 0 - jl exit ; TODO handle this gracefully + ; TODO what did poll(2) detect in this case? + add r15, 1 + jmp scan__loop - mov rax, SYS_SHUTDOWN - mov rdi, 0 - mov edi, r14d - mov rsi, SHUT_RDWR - syscall - - mov rax, SYS_CLOSE - mov rdi, 0 - mov edi, r14d - syscall +_client__error: + 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 - pop rdi - jmp pollfds__scan__loop +_client__pollin: + mov rdi, r13 + mov rsi, r12 + mov rdx, r15 + call client__pollin + cmp rax, 0 + jle _client__error + add r15, rax + jmp scan__loop -pollfds__scan__found__server: - ; TODO check r10w, incl for POLLNVAL & POLLERR - push rdi +_client__pollout: + mov rdi, r13 + mov rsi, r12 + mov rdx, r15 + call client__pollout + 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 ; TODO handle this gracefully + jl exit ; accept(2) returned error TODO mov rdi, rax - mov si, POLLIN | POLLOUT + push rdi + mov si, POLLIN call pollfds__append pop rdi + call clients__append + add r15, 1 - jmp pollfds__scan__loop - -; edi - fd -; si - events -pollfds__append: - ; TODO check against pollfds_capacity - mov r10, [pollfds_len] - mov [pollfds + r10 * pollfd_size], edi - mov [pollfds + r10 * pollfd_size + 4], si - add r10, 1 - mov [pollfds_len], r10 - ret - -; rdi - pollfds array index to remove -pollfds__remove: - mov r11, [pollfds_len] - cmp rdi, r10 - jge return ; XXX index out of bounds, do some other error? - cmp r11, 1 - jle pollfds__clear - mov r10, [pollfds + (r11 - 1) * pollfd_size] - mov [pollfds + rdi * pollfd_size], r10 - sub r11, 1 - mov [pollfds_len], r11 - ret - -pollfds__clear: - mov r10, 0 - mov [pollfds_len], r10 - ret - -; esi - fd -clients__append: - ; TODO check against client_capacity - mov r10, [clients_len] - imul r10, client_size - add r10, clients - mov [r10], esi - add r10, 4 - mov r8b, 0 - mov r11, 0 - -clients__append__init: - cmp r11, client_size - jge return - mov [r10 + r11], r8b - add r11, 1 - jmp clients__append__init + jmp scan__loop return: ret exit: mov rax, SYS_EXIT - mov rdi, 0 + mov rdi, 255 syscall diff --git a/pollfds.s b/pollfds.s new file mode 100644 index 0000000..4eed357 --- /dev/null +++ b/pollfds.s @@ -0,0 +1,30 @@ +; edi - fd +; si - events +pollfds__append: + ; TODO check against pollfds_capacity + mov r10, [pollfds_len] + mov [pollfds + r10 * pollfd_size], edi + mov [pollfds + r10 * pollfd_size + 4], si + mov r11w, 0 + mov [pollfds + r10 * pollfd_size + 6], r11w + add r10, 1 + mov [pollfds_len], r10 + ret + +; rdi - pollfds array index to remove +pollfds__remove: + mov r11, [pollfds_len] + cmp rdi, r11 + jge return ; XXX index out of bounds, do some other error? + cmp r11, 1 + jle pollfds__clear + mov r10, [pollfds + (r11 - 1) * pollfd_size] + mov [pollfds + rdi * pollfd_size], r10 + sub r11, 1 + mov [pollfds_len], r11 + ret + +pollfds__clear: + mov r10, 0 + mov [pollfds_len], r10 + ret diff --git a/readline.s b/readline.s index aba4769..35e30dd 100644 --- a/readline.s +++ b/readline.s @@ -1,34 +1,41 @@ -; Returns length in rax +; Returns: +; rax - read(2) length +; rdi - if line is complete, line length; +; if line was incomplete, 0; +; if EOF or read(2) returned an error, undefined ; Errors (in rax): ; -1024 - line too long ; other negative - error from read(2) +; 0 - EOF from read(2) ; Arguments: ; rdi - fd ; rsi - buffer ; rdx - max length readline: - push rdi push rsi push rdx mov rax, SYS_READ syscall pop rdx pop rsi - pop rdi cmp rax, 0 jl return mov r10, 0 readline__scan: - cmp r10, rax + cmp r10, rdx jge readline__overflow + cmp r10, rax + jge readline__incomplete_line mov r11b, [rsi + r10] add r10, 1 cmp r11b, 0x0a ; '\n' jne readline__scan + mov rdi, r10 + ret -readline__return: - mov rax, r10 +readline__incomplete_line: + mov rdi, 0 ret readline__overflow: