x64-httpd/client.s
root fc1cc26b0f 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
2025-05-21 09:32:25 +00:00

304 lines
6 KiB
ArmAsm

; Returns:
; rax - 0
; Errors (in rax):
; 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 rbx
push r12
push r13
push r14
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 rax, SYS_READ
mov rsi, r13
mov rdx, 255
sub dl, [rsi + OFFSET_CLIENT_BUFFER_LEN]
syscall
cmp rax, 0
jle client__pollin__return ; TODO verify this shit
; buffer_len += read(2) length
add [r12 - OFFSET_CLIENT_BUFFER + OFFSET_CLIENT_BUFFER_LEN], al
mov rdi, r13
mov rsi, rax
call scanline
cmp rax, 0
je client__pollin__no_line
mov rax, 1
mov word [pollfds + rbx * 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
; Errors:
; 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 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
mov rdi, rbp
mov rsi, r12
call client__pollout__before_fresh_lines
cmp rax, 0
jle client__pollout__return
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
add r11, OFFSET_CLIENT_BUFFER
sub r11, r13
client__pollout__shunt__loop:
cmp r10, r11
jge client__pollout__shunt__finished
mov r8b, [r10 + r13]
mov [r10], r8b
add r10, 1
jmp client__pollout__shunt__loop
client__pollout__shunt__finished:
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
; 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
push rdi
mov rsi, SHUT_RDWR
syscall
mov rax, SYS_CLOSE
pop rdi
syscall
ret