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
; 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