client__pollin: read as much as possible; client__pollout: do processing

This commit is contained in:
root 2025-05-17 08:10:55 +00:00
parent 8ab750ba97
commit 484d81baa8
3 changed files with 149 additions and 92 deletions

173
client.s
View file

@ -1,75 +1,146 @@
; Returns:
; rax - 0
; Errors (in rax): ; Errors (in rax):
; 0 - EOF ; rax - 0 - EOF
; -1024 - line too long ; rax - -1024 - line too long
; other negative - from read(2) ; rax - other negative - from read(2)
; Arguments: ; Arguments:
; rdi - fd ; rdi - fd
; rsi - address of client within clients array ; rsi - address of client within clients array
; rdx - pollfds index ; rdx - pollfds index
; Variables:
; rbx - pollfds index
; r12 - client buffer
; r13 - start of line scanning
; r14 - client buffer end
client__pollin: client__pollin:
push rdi push rbx
push rsi push r12
push rdx push r13
push r14
mov r10, 0 mov rbx, rdx
mov r10b, [rsi + 4 + 2] ; buffer_len 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 rax, SYS_READ
mov dl, 255 mov rsi, r13
sub dl, r10b ; rdx = 255 - buffer_len mov rdx, 255
add rsi, 8 sub rdx, [rsi + OFFSET_CLIENT_BUFFER_LEN]
add rsi, r10 syscall
call readline
mov r10, rdi
pop rdx
pop rsi
pop rdi
cmp rax, 0 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 mov rdi, r13
jg client__pollin__complete_line mov rsi, rax
call scanline
add [rsi + 4 + 1], al ; line_len += rax cmp rax, 0
ret je client__pollin__no_line
client__pollin__complete_line: mov rax, 1
add [rsi + 4 + 1], r10b ; line_len += r10
mov word [pollfds + rdx * pollfd_size + 4], POLLOUT mov word [pollfds + rdx * pollfd_size + 4], POLLOUT
client__pollin__return:
pop r14
pop r13
pop r12
pop rbx
ret 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 ; rdi - fd
; rsi - address of client within clients array ; rsi - address of client within clients array
; rdx - pollfds index ; 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: client__pollout:
push rdi push rbx
push rsi push r12
push rdx 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 rax, SYS_WRITE
mov rdx, 0 mov rsi, r12
mov dl, [rsi + 4 + 1] add rsi, OFFSET_CLIENT_BUFFER
add rsi, 8 mov rdx, r13
syscall syscall
pop rdx ; error from write(2)
pop rsi
pop rdi
cmp rax, 0 cmp rax, 0
jl return jl client__pollout__return
mov r10, rsi mov r10, r12
add r10, 8
mov r11, 0 mov r11, 0
mov r11b, [rsi + 4 + 2] mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN]
add r11, r12
sub r11, rax sub r11, rax
add r11, r10
client__pollout__shunt: client__pollout__shunt:
cmp r10, r11 cmp r10, r11
@ -80,14 +151,16 @@ client__pollout__shunt:
jmp client__pollout__shunt jmp client__pollout__shunt
client__pollout__shunt__finished: client__pollout__shunt__finished:
sub [rsi + 4 + 2], al ; buffer_len -= rax ; buffer_len -= rax
sub [rsi + 4 + 1], al ; line_len -= rax sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al
cmp byte [rsi + 4 + 1], 0 cmp rax, r13
je client__pollout__wrote_line jl client__pollout__return
ret mov word [pollfds + rbx * pollfd_size + 4], POLLIN
client__pollout__wrote_line: client__pollout__return:
mov word [pollfds + rdx * pollfd_size + 4], POLLIN pop r13
pop r12
pop rbx
ret ret
; rdi - fd ; rdi - fd

17
main.s
View file

@ -30,11 +30,18 @@ SHUT_RDWR equ 2
;STATE_READING equ 0 ;STATE_READING equ 0
;STATE_WRITING equ 1 ;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 pollfd_size equ 4 + 2 + 2 ; $ man 2 poll
pollfds_capacity equ 100 pollfds_capacity equ 100
; fd, state, line_len, buffer_len, uri_len, buffer, uri client_buffer_size equ 255
client_size equ 4 + 4 + 255 + 255 ; fd, state, buffer_len, buffer
client_size equ 4 + 2 + client_buffer_size
clients_capacity equ pollfds_capacity - 1 clients_capacity equ pollfds_capacity - 1
SECTION .data SECTION .data
@ -109,7 +116,7 @@ scan__found__client:
mov r10w, r14w mov r10w, r14w
and r10w, POLLERR | POLLNVAL and r10w, POLLERR | POLLNVAL
cmp r10w, 0 cmp r10w, 0
jne _client__error jne _client__error_or_eof
mov r10w, r14w mov r10w, r14w
and r10w, POLLIN and r10w, POLLIN
@ -125,7 +132,7 @@ scan__found__client:
add r15, 1 add r15, 1
jmp scan__loop jmp scan__loop
_client__error: _client__error_or_eof:
mov rdi, r12 mov rdi, r12
call clients__remove call clients__remove
@ -142,7 +149,7 @@ _client__pollin:
mov rdx, r15 mov rdx, r15
call client__pollin call client__pollin
cmp rax, 0 cmp rax, 0
jle _client__error jle _client__error_or_eof
add r15, rax add r15, rax
jmp scan__loop jmp scan__loop

View file

@ -1,43 +1,20 @@
; Returns: ; Returns:
; rax - read(2) length ; rax - if line: line length; otherwise: 0
; 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: ; Arguments:
; rdi - fd ; rdi - buffer
; rsi - buffer ; rsi - max length
; rdx - max length scanline:
readline: mov rax, 0
push rsi
push rdx
mov rax, SYS_READ
syscall
pop rdx
pop rsi
cmp rax, 0
jl return
mov r10, 0
readline__scan: scanline__loop:
cmp r10, rdx cmp rax, rsi
jge readline__overflow jge scanline__incomplete_line
cmp r10, rax mov r10b, [rdi + rax]
jge readline__incomplete_line add rax, 1
mov r11b, [rsi + r10] cmp r10b, 0x0a ; '\n'
add r10, 1 jne scanline__loop
cmp r11b, 0x0a ; '\n'
jne readline__scan
mov rdi, r10
ret ret
readline__incomplete_line: scanline__incomplete_line:
mov rdi, 0 mov rax, 0
ret
readline__overflow:
mov rax, -1024
ret ret