rewrite client__pollout

algorithm:
1. call client__pollout__before_fresh_lines
2. if error, return
3. find line length
4. if no line, set POLLIN and goto 8
5. call client__pollout__line
6. if error, goto 7
7. finished with this line; goto 3
8. move the final incomplete line to the start of the client's buffer
9. return
This commit is contained in:
root 2025-05-21 09:23:48 +00:00
parent c16c82b15f
commit fc1cc26b0f
2 changed files with 194 additions and 42 deletions

221
client.s
View file

@ -70,83 +70,226 @@ client__pollin__line_too_long:
jmp client__pollin__return jmp client__pollin__return
; Returns:
; rax - non-negative from write(2)
; Errors: ; Errors:
; rax - -1024 - no line was buffered ; rax - negative or zero - from write(2)
; rax - other negative - from write(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: ; Variables:
; rbp - fd
; rbx - pollfds index ; rbx - pollfds index
; r12 - address of client within clients array ; r12 - address of client within clients array
; r13 - line length ; r13 - line start
; r11 - client buffer end of text after call to write(2) ; r14 - line end
; r15 - client buffer end
; r11 - client buffer, length of last incomplete line
client__pollout: client__pollout:
push rbp
push rbx push rbx
push r12 push r12
push r13 push r13
push r14
push r15
mov rbp, rdi
mov rbx, rdx mov rbx, rdx
mov r12, rsi mov r12, rsi
mov r13, rsi
add r13, OFFSET_CLIENT_BUFFER
mov r15, r13
add r15, 255
push rdi mov rdi, rbp
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 rsi, r12 mov rsi, r12
add rsi, OFFSET_CLIENT_BUFFER call client__pollout__before_fresh_lines
mov rdx, r13
syscall
; error from write(2)
cmp rax, 0 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 r11, 0
mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN] mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN]
add r11, r12 add r11, r12
sub r11, rax add r11, OFFSET_CLIENT_BUFFER
sub r11, r13
client__pollout__shunt: client__pollout__shunt__loop:
cmp r10, r11 cmp r10, r11
jge client__pollout__shunt__finished jge client__pollout__shunt__finished
mov r8b, [r10 + rax] mov r8b, [r10 + r13]
mov [r10], r8b mov [r10], r8b
add r10, 1 add r10, 1
jmp client__pollout__shunt jmp client__pollout__shunt__loop
client__pollout__shunt__finished: client__pollout__shunt__finished:
; buffer_len -= rax mov r10, r13
sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al sub r10, r12
cmp rax, r13 sub r10, OFFSET_CLIENT_BUFFER
jl client__pollout__return
mov word [pollfds + rbx * pollfd_size + 4], POLLIN
client__pollout__return: client__pollout__return:
pop r15
pop r14
pop r13 pop r13
pop r12 pop r12
pop rbx pop rbx
pop rbp
ret ret
client__pollout__no_line: ; Errors:
mov rax, -1024 ; rax - -1024 - some scratch buffer bytes remain, stop write(2)ing
jmp client__pollout__return ; 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 ; rdi - fd
client__shutdown_close: client__shutdown_close:
mov rax, SYS_SHUTDOWN mov rax, SYS_SHUTDOWN

15
main.s
View file

@ -26,6 +26,7 @@ POLLERR equ 8
POLLNVAL equ 32 POLLNVAL equ 32
; TODO(?) POLLPRI: see poll(2), tcp(7) ; TODO(?) POLLPRI: see poll(2), tcp(7)
SHUT_RDWR equ 2 SHUT_RDWR equ 2
EAGAIN equ -11
;STATE_READING equ 0 ;STATE_READING equ 0
;STATE_WRITING equ 1 ;STATE_WRITING equ 1
@ -34,14 +35,18 @@ SHUT_RDWR equ 2
OFFSET_CLIENT_FD equ 0 OFFSET_CLIENT_FD equ 0
OFFSET_CLIENT_STATE equ 4 OFFSET_CLIENT_STATE equ 4
OFFSET_CLIENT_BUFFER_LEN equ 5 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 pollfd_size equ 4 + 2 + 2 ; $ man 2 poll
pollfds_capacity equ 100 pollfds_capacity equ 100
client_buffer_size equ 255 client_buffer_size equ 255
; fd, state, buffer_len, buffer client_scratch_size equ 255
client_size equ 4 + 2 + client_buffer_size
; 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 clients_capacity equ pollfds_capacity - 1
SECTION .data SECTION .data
@ -158,8 +163,12 @@ _client__pollout:
mov rsi, r12 mov rsi, r12
mov rdx, r15 mov rdx, r15
call client__pollout call client__pollout
cmp rax, EAGAIN
je _client__pollout__finished
cmp rax, 0 cmp rax, 0
jle _client__error_or_eof jle _client__error_or_eof
_client__pollout__finished:
add r15, 1 add r15, 1
jmp scan__loop jmp scan__loop