diff --git a/client.s b/client.s index 073f42c..557898f 100644 --- a/client.s +++ b/client.s @@ -1,75 +1,146 @@ +; Returns: +; rax - 0 ; Errors (in rax): -; 0 - EOF -; -1024 - line too long -; other negative - from read(2) +; rax - 0 - EOF +; rax - -1024 - line too long +; rax - other negative - from read(2) ; Arguments: ; rdi - fd ; rsi - address of client within clients array ; rdx - pollfds index +; Variables: +; rbx - pollfds index +; r12 - client buffer +; r13 - start of line scanning +; r14 - client buffer end client__pollin: - push rdi - push rsi - push rdx + push rbx + push r12 + push r13 + push r14 - mov r10, 0 - mov r10b, [rsi + 4 + 2] ; buffer_len + mov rbx, rdx + mov r12, rsi + add r12, OFFSET_CLIENT_BUFFER + mov r13, 0 + mov r13b, [rsi + OFFSET_CLIENT_BUFFER_LEN] + add r13, r12 + mov r14, r12 + add r14, 255 - 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 + mov rax, SYS_READ + mov rsi, r13 + mov rdx, 255 + sub rdx, [rsi + OFFSET_CLIENT_BUFFER_LEN] + syscall cmp rax, 0 - jle return + jle client__pollin__return ; TODO verify this shit - add [rsi + 4 + 2], al ; buffer_len += rax + ; buffer_len += read(2) length + add [rsi + OFFSET_CLIENT_BUFFER_LEN], al - cmp r10, 0 - jg client__pollin__complete_line + mov rdi, r13 + mov rsi, rax + call scanline - add [rsi + 4 + 1], al ; line_len += rax - ret + cmp rax, 0 + je client__pollin__no_line -client__pollin__complete_line: - add [rsi + 4 + 1], r10b ; line_len += r10 + mov rax, 1 mov word [pollfds + rdx * pollfd_size + 4], POLLOUT + +client__pollin__return: + pop r14 + pop r13 + pop r12 + pop rbx ret +client__pollin__no_line: + mov r10, r13 + add r10, rax + cmp r10, r14 + jge client__pollin__line_too_long + mov rax, 1 + jmp client__pollin__return + +client__pollin__line_too_long: + mov rax, -1024 + jmp client__pollin__return + +client__pollin__line: + pop rdx + mov word [pollfds + rdx * pollfd_size + 4], POLLOUT + push rdx + ; TODO do something to the line + ; problem: we can't write here because the socket may + ; block; + ; how do we deal with multiple lines? + ; XXX call read(2) trying to fill the whole buffer + ; - if we have at least 1 line, + ; update the state and go back to main loop; + ; do whatever logic is necessary until we need to + ; call read(2) or write(2) next, ie nothing; + ; set POLLOUT and process line(s) in write(2) block + ; - if we have no line and we filled the buffer, + ; return -1024 + ; - if we have no line, go back to main loop + ; we could have multiple lines, and that's okay + ; XXX so this plan will work actually + ; XXX should we do logic here or in the write(2) block? + ; probably there, so here we just accumulate lines + ret + +; Returns: +; rax - non-negative from write(2) +; Errors: +; rax - -1024 - no line was buffered +; rax - other negative - from write(2) +; Arguments: ; rdi - fd ; rsi - address of client within clients array ; rdx - pollfds index +; Variables: +; rbx - pollfds index +; r12 - address of client within clients array +; r13 - line length +; r11 - client buffer end of text after call to write(2) client__pollout: - push rdi - push rsi - push rdx + push rbx + push r12 + push r13 + + mov rbx, rdx + mov r12, rsi + + mov rdi, r12 + mov rsi, 255 + call scanline + + ; poll(2)'d for POLLOUT but we had no line buffered; + ; should be impossible + cmp rax, 0 + mov rax, -1024 + je client__pollout__return + + mov r13, rax mov rax, SYS_WRITE - mov rdx, 0 - mov dl, [rsi + 4 + 1] - add rsi, 8 + mov rsi, r12 + add rsi, OFFSET_CLIENT_BUFFER + mov rdx, r13 syscall - pop rdx - pop rsi - pop rdi - + ; error from write(2) cmp rax, 0 - jl return + jl client__pollout__return - mov r10, rsi - add r10, 8 + mov r10, r12 mov r11, 0 - mov r11b, [rsi + 4 + 2] + mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN] + add r11, r12 sub r11, rax - add r11, r10 client__pollout__shunt: cmp r10, r11 @@ -80,14 +151,16 @@ client__pollout__shunt: 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 + ; 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 -client__pollout__wrote_line: - mov word [pollfds + rdx * pollfd_size + 4], POLLIN +client__pollout__return: + pop r13 + pop r12 + pop rbx ret ; rdi - fd diff --git a/main.s b/main.s index 190f240..3331bd8 100644 --- a/main.s +++ b/main.s @@ -30,11 +30,18 @@ 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 -; fd, state, line_len, buffer_len, uri_len, buffer, uri -client_size equ 4 + 4 + 255 + 255 +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 @@ -109,7 +116,7 @@ scan__found__client: mov r10w, r14w and r10w, POLLERR | POLLNVAL cmp r10w, 0 - jne _client__error + jne _client__error_or_eof mov r10w, r14w and r10w, POLLIN @@ -125,7 +132,7 @@ scan__found__client: add r15, 1 jmp scan__loop -_client__error: +_client__error_or_eof: mov rdi, r12 call clients__remove @@ -142,7 +149,7 @@ _client__pollin: mov rdx, r15 call client__pollin cmp rax, 0 - jle _client__error + jle _client__error_or_eof add r15, rax jmp scan__loop diff --git a/readline.s b/readline.s index 35e30dd..b1698a0 100644 --- a/readline.s +++ b/readline.s @@ -1,43 +1,20 @@ ; 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) +; rax - if line: line length; otherwise: 0 ; Arguments: -; rdi - fd -; rsi - buffer -; rdx - max length -readline: - push rsi - push rdx - mov rax, SYS_READ - syscall - pop rdx - pop rsi - cmp rax, 0 - jl return - mov r10, 0 +; rdi - buffer +; rsi - max length +scanline: + mov rax, 0 -readline__scan: - 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 +scanline__loop: + cmp rax, rsi + jge scanline__incomplete_line + mov r10b, [rdi + rax] + add rax, 1 + cmp r10b, 0x0a ; '\n' + jne scanline__loop ret -readline__incomplete_line: - mov rdi, 0 - ret - -readline__overflow: - mov rax, -1024 +scanline__incomplete_line: + mov rax, 0 ret