diff --git a/client.s b/client.s index d3a1e7a..9946311 100644 --- a/client.s +++ b/client.s @@ -70,83 +70,226 @@ client__pollin__line_too_long: jmp client__pollin__return -; Returns: -; rax - non-negative from write(2) ; Errors: -; rax - -1024 - no line was buffered -; rax - other negative - from write(2) +; rax - negative or zero - from write(2) ; Arguments: ; rdi - fd ; rsi - address of client within clients array ; rdx - pollfds index ; Variables: +; rbp - fd ; rbx - pollfds index ; r12 - address of client within clients array -; r13 - line length -; r11 - client buffer end of text after call to write(2) +; r13 - line start +; r14 - line end +; r15 - client buffer end +; r11 - client buffer, length of last incomplete line client__pollout: + push rbp push rbx push r12 push r13 + push r14 + push r15 + mov rbp, rdi mov rbx, rdx mov r12, rsi + mov r13, rsi + add r13, OFFSET_CLIENT_BUFFER + mov r15, r13 + add r15, 255 - push rdi - mov rdi, r12 - add rdi, OFFSET_CLIENT_BUFFER - mov rsi, 255 - call scanline - pop rdi - - ; poll(2)'d for POLLOUT but we had no line buffered; - ; should be impossible - cmp rax, 0 - je client__pollout__no_line - - mov r13, rax - - mov rax, SYS_WRITE + mov rdi, rbp mov rsi, r12 - add rsi, OFFSET_CLIENT_BUFFER - mov rdx, r13 - syscall + call client__pollout__before_fresh_lines - ; error from write(2) cmp rax, 0 - jl client__pollout__return + jle client__pollout__return - mov r10, r12 +client__pollout__scan: + mov rdi, r13 + mov rsi, 0 + mov sil, [r12 + OFFSET_CLIENT_BUFFER_LEN] + call scanline + + cmp rax, 0 + jle client__pollout__set_pollin ; no lines left + + sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al + + ; line_end = line_start + line_len + mov r14, r13 + add r14, rax + + mov rdi, rbp + mov rsi, r12 + mov rdx, r13 + mov rcx, r14 + sub rcx, r13 + call client__pollout__line + + mov r13, r14 + + cmp rax, 0 + jle client__pollout__shunt + jmp client__pollout__scan + +client__pollout__set_pollin: + mov word [pollfds + rbx * pollfd_size + 4], POLLIN + mov rax, 1 + +client__pollout__shunt: + mov r10, 0 mov r11, 0 mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN] add r11, r12 - sub r11, rax + add r11, OFFSET_CLIENT_BUFFER + sub r11, r13 -client__pollout__shunt: +client__pollout__shunt__loop: cmp r10, r11 jge client__pollout__shunt__finished - mov r8b, [r10 + rax] + mov r8b, [r10 + r13] mov [r10], r8b add r10, 1 - jmp client__pollout__shunt + jmp client__pollout__shunt__loop client__pollout__shunt__finished: - ; buffer_len -= rax - sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al - cmp rax, r13 - jl client__pollout__return - mov word [pollfds + rbx * pollfd_size + 4], POLLIN + mov r10, r13 + sub r10, r12 + sub r10, OFFSET_CLIENT_BUFFER client__pollout__return: + pop r15 + pop r14 pop r13 pop r12 pop rbx + pop rbp ret -client__pollout__no_line: - mov rax, -1024 - jmp client__pollout__return +; Errors: +; rax - -1024 - some scratch buffer bytes remain, stop write(2)ing +; rax - other negative or zero - from write(2) +; Arguments: +; rdi - fd +; rsi - address of client within clients array +client__pollout__before_fresh_lines: + mov rdx, 0 + mov dl, [rsi + OFFSET_CLIENT_SCRATCH_LEN] + cmp rdx, 0 + jle client__pollout__before_fresh_lines__return__succ + + mov rax, SYS_WRITE + push rdx + add rsi, OFFSET_CLIENT_SCRATCH + push rsi + syscall + + pop rsi + pop rdx + + cmp rax, 0 + jle return + + sub [rsi - OFFSET_CLIENT_SCRATCH + OFFSET_CLIENT_SCRATCH_LEN], al + + mov r10, rsi + mov r11, rsi + add r11, rdx + sub r11, rax + +client__pollout__before_fresh_lines__shunt: + cmp r10, r11 + jge client__pollout__before_fresh_lines__return + mov r8b, [r10 + rax] + mov [r10], r8b + add r10, 1 + jmp client__pollout__before_fresh_lines__shunt + +client__pollout__before_fresh_lines__return: + cmp rax, rdx + jl client__pollout__before_fresh_lines__return__fail + +client__pollout__before_fresh_lines__return__succ: + mov rax, 1 + ret + +client__pollout__before_fresh_lines__return__fail: + mov rax, -1024 + ret + +; Errors: +; rax - negative or zero - from write(2) +; Arguments: +; rdi - fd +; rsi - address of client within clients array +; rdx - line start +; rcx - line length +; Variables: +; rsi - client scratch +; r10 - line write(2) end +; r9 - line end +; Assumptions: +; scratch is empty, bc it was emptied by client__pollout__before_fresh_lines +; we must deal with the whole line we are given +client__pollout__line: + ; TODO we've got a line + ; - try writing it + ; - if socket is fucked: return + ; - if ok: cool + ; - if couldn't do the whole thing: you have scratch available, if it's needed for the protocol + + push rdx + push rcx + + mov rax, SYS_WRITE + mov rsi, rdx + mov rdx, rcx + syscall + + pop rcx + pop rdx + + ; TODO continue here also not sure calling fn is correct yet + ; check that changes to server.s haven't fucked anything up + + ; error from write(2) + cmp rax, 0 + jl client__pollout__line__error + + cmp rax, rcx + jl client__pollout__line__incomplete + + mov rax, 1 + ret + +client__pollout__line__error: + mov r10, 0 + jmp client__pollout__line__write_scratch + +client__pollout__line__incomplete: + mov r10, rax + +client__pollout__line__write_scratch: + add rsi, OFFSET_CLIENT_SCRATCH + add r10, rdx + mov r11, 0 + mov r9, rcx + add r9, rdx + +client__pollout__line__write_scratch__loop: + cmp r10, r9 + jge return + mov r8b, [r10 + r11] + mov [rsi + r11], r8b + add r11, 1 + jmp client__pollout__line__write_scratch__loop + + +; Arguments: ; rdi - fd client__shutdown_close: mov rax, SYS_SHUTDOWN diff --git a/main.s b/main.s index ffa5496..d78bb66 100644 --- a/main.s +++ b/main.s @@ -26,6 +26,7 @@ POLLERR equ 8 POLLNVAL equ 32 ; TODO(?) POLLPRI: see poll(2), tcp(7) SHUT_RDWR equ 2 +EAGAIN equ -11 ;STATE_READING equ 0 ;STATE_WRITING equ 1 @@ -34,14 +35,18 @@ SHUT_RDWR equ 2 OFFSET_CLIENT_FD equ 0 OFFSET_CLIENT_STATE equ 4 OFFSET_CLIENT_BUFFER_LEN equ 5 -OFFSET_CLIENT_BUFFER equ 6 +OFFSET_CLIENT_SCRATCH_LEN equ 6 +OFFSET_CLIENT_BUFFER equ 7 +OFFSET_CLIENT_SCRATCH equ 7 + client_buffer_size 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 +client_scratch_size equ 255 + +; fd, state, buffer_len, scratch_len, buffer, scratch +client_size equ 4 + 2 + client_buffer_size + client_scratch_size clients_capacity equ pollfds_capacity - 1 SECTION .data @@ -158,8 +163,12 @@ _client__pollout: mov rsi, r12 mov rdx, r15 call client__pollout + cmp rax, EAGAIN + je _client__pollout__finished cmp rax, 0 jle _client__error_or_eof + +_client__pollout__finished: add r15, 1 jmp scan__loop