echo server, multiple clients, lines <256 bytes

This commit is contained in:
root 2025-05-13 12:07:03 +00:00
parent d54596514c
commit 29f54ba779
6 changed files with 304 additions and 112 deletions

104
client.s Normal file
View file

@ -0,0 +1,104 @@
; Errors (in rax):
; 0 - EOF
; -1024 - line too long
; other negative - from read(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
; rdx - pollfds index
client__pollin:
push rdi
push rsi
push rdx
mov r10, 0
mov r10b, [rsi + 4 + 2] ; buffer_len
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
cmp rax, 0
jle return
add [rsi + 4 + 2], al ; buffer_len += rax
cmp r10, 0
jg client__pollin__complete_line
add [rsi + 4 + 1], al ; line_len += rax
ret
client__pollin__complete_line:
add [rsi + 4 + 1], r10b ; line_len += r10
mov word [pollfds + rdx * pollfd_size + 4], POLLOUT
ret
; rdi - fd
; rsi - address of client within clients array
; rdx - pollfds index
client__pollout:
push rdi
push rsi
push rdx
mov rax, SYS_WRITE
mov rdx, 0
mov dl, [rsi + 4 + 1]
add rsi, 8
syscall
pop rdx
pop rsi
pop rdi
cmp rax, 0
jl return
mov r10, rsi
add r10, 8
mov r11, 0
mov r11b, [rsi + 4 + 2]
sub r11, rax
add r11, r10
client__pollout__shunt:
cmp r10, r11
jge client__pollout__shunt__finished
mov r8b, [r10 + rax]
mov [r10], r8b
add r10, 1
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
client__pollout__wrote_line:
mov word [pollfds + rdx * pollfd_size + 4], POLLIN
ret
; rdi - fd
client__shutdown_close:
mov rax, SYS_SHUTDOWN
push rdi
mov rsi, SHUT_RDWR
syscall
mov rax, SYS_CLOSE
pop rdi
syscall
ret

69
clients.s Normal file
View file

@ -0,0 +1,69 @@
; edi - fd
clients__append:
; TODO check against client_capacity
mov r10, [clients_len]
imul r10, client_size
add r10, clients
mov [r10], edi
add qword [clients_len], 1
mov r11, 4
clients__append__write_zeros:
cmp r11, 8
jge return
mov byte [r10 + r11], 0
add r11, 1
jmp clients__append__write_zeros
; edi - fd
clients__search:
mov r11, [clients_len]
imul r11, client_size
add r11, clients
mov r10, clients
clients__search__loop:
cmp r10, r11
jge clients__search__fail
mov r8d, [r10]
cmp r8d, edi
je clients__search__succ
add r10, client_size
jmp clients__search__loop
clients__search__fail:
mov r10, -1
clients__search__succ:
mov rax, r10
ret
; rdi - address of client within clients array
clients__remove:
mov r10, [clients_len]
cmp r10, 1
jle clients__clear
add r10, -1
mov [clients_len], r10
mov r10, 0
mov r11, r10
imul r11, client_size
add r11, clients
clients__remove__loop:
cmp r10, client_size
jge return
mov r8b, [r11 + r10]
mov [rdi + r10], r8b
add r10, 1
jmp clients__remove__loop
; rdi - address of client within clients array
clients__clear:
mov r10, 0
mov [clients_len], r10
ret

View file

@ -14,5 +14,7 @@ void main() {
printf("sizeof(short) %d\n", sizeof(short)); printf("sizeof(short) %d\n", sizeof(short));
printf("POLLIN %d\n", POLLIN); printf("POLLIN %d\n", POLLIN);
printf("POLLOUT %d\n", POLLOUT); printf("POLLOUT %d\n", POLLOUT);
printf("POLLERR %d\n", POLLERR);
printf("POLLNVAL %d\n", POLLNVAL);
printf("SHUT_RDWR %d\n", SHUT_RDWR); printf("SHUT_RDWR %d\n", SHUT_RDWR);
} }

192
main.s
View file

@ -22,11 +22,19 @@ F_SETFL equ 4
O_NONBLOCK equ 2048 O_NONBLOCK equ 2048
POLLIN equ 1 POLLIN equ 1
POLLOUT equ 4 POLLOUT equ 4
POLLERR equ 8
POLLNVAL equ 32
; TODO(?) POLLPRI: see poll(2), tcp(7)
SHUT_RDWR equ 2 SHUT_RDWR equ 2
;STATE_READING equ 0
;STATE_WRITING equ 1
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_size equ 1 + 256 + 256 ; state, line buffer, uri
; fd, state, line_len, buffer_len, uri_len, buffer, uri
client_size equ 4 + 4 + 255 + 255
clients_capacity equ pollfds_capacity - 1 clients_capacity equ pollfds_capacity - 1
SECTION .data SECTION .data
@ -47,11 +55,14 @@ SECTION .text
%include "server.s" %include "server.s"
%include "readline.s" %include "readline.s"
%include "clients.s"
%include "pollfds.s"
%include "client.s"
_start: _start:
call make_server call make_server
mov rbx, rax ; server fd mov rbx, rax ; server fd
mov rdi, rax mov rdi, rbx
mov rsi, POLLIN mov rsi, POLLIN
call pollfds__append call pollfds__append
@ -63,144 +74,113 @@ poll:
syscall syscall
cmp rax, 0 cmp rax, 0
je poll je poll
jl exit ; TODO handle this gracefully jl exit ; poll(2) returned error TODO
mov rdi, rbx
; rdi - server fd scan:
pollfds__scan:
mov r15, 0 mov r15, 0
pollfds__scan__loop: ; Variables:
; r15 - pollfds index
; r14w - poll(2) revents
; r13d - fd
; r12 - client memory address
scan__loop:
cmp r15, [pollfds_len] cmp r15, [pollfds_len]
jge poll jge poll
mov r10w, [pollfds + r15 * pollfd_size + 6] mov r14w, [pollfds + r15 * pollfd_size + 6]
cmp r10w, 0 cmp r14w, 0
jne pollfds__scan__found jne scan__found
add r15, 1 add r15, 1
jmp pollfds__scan__loop jmp scan__loop
pollfds__scan__found: scan__found:
mov r14, 0 mov r13, 0
mov r14d, [pollfds + r15 * pollfd_size] mov r13d, [pollfds + r15 * pollfd_size]
cmp r14d, edi cmp r13d, ebx
je pollfds__scan__found__server je scan__found__server
pollfds__scan__found__client: scan__found__client:
; TODO check r10w, incl for POLLNVAL & POLLERR mov rdi, r13
push rdi call clients__search
mov r12, rax
cmp r12, 0
jl _client__not_stored
mov rdi, r14 mov r10w, r14w
call clients__append and r10w, POLLERR | POLLNVAL
cmp r10w, 0
jne _client__error
mov r12, [clients_len] mov r10w, r14w
add r12, -1 and r10w, POLLIN
imul r12, client_size cmp r10w, 0
add r12, clients jne _client__pollin
add r12, 4
mov rdi, r14 mov r10w, r14w
mov rsi, r12 and r10w, POLLOUT
mov rdx, 256 cmp r10w, 0
call readline jne _client__pollout
cmp rax, 0 ; TODO
jl exit
;push rax ; TODO
mov rdx, rax ; TODO what did poll(2) detect in this case?
mov rax, SYS_WRITE add r15, 1
mov rdi, r14 jmp scan__loop
mov rsi, r12
syscall
cmp rax, 0
jl exit ; TODO handle this gracefully
mov rax, SYS_SHUTDOWN _client__error:
mov rdi, 0 mov rdi, r12
mov edi, r14d call clients__remove
mov rsi, SHUT_RDWR
syscall
mov rax, SYS_CLOSE
mov rdi, 0
mov edi, r14d
syscall
_client__not_stored:
mov rdi, r13
call client__shutdown_close
mov rdi, r15 mov rdi, r15
call pollfds__remove call pollfds__remove
jmp scan__loop
pop rdi _client__pollin:
jmp pollfds__scan__loop mov rdi, r13
mov rsi, r12
mov rdx, r15
call client__pollin
cmp rax, 0
jle _client__error
add r15, rax
jmp scan__loop
pollfds__scan__found__server: _client__pollout:
; TODO check r10w, incl for POLLNVAL & POLLERR mov rdi, r13
push rdi mov rsi, r12
mov rdx, r15
call client__pollout
add r15, 1
jmp scan__loop
scan__found__server:
cmp r14w, POLLIN
jne exit
mov rax, SYS_ACCEPT mov rax, SYS_ACCEPT
mov rdi, r13
mov rsi, 0 mov rsi, 0
mov rdx, 0 mov rdx, 0
syscall syscall
cmp rax, 0 cmp rax, 0
jl exit ; TODO handle this gracefully jl exit ; accept(2) returned error TODO
mov rdi, rax mov rdi, rax
mov si, POLLIN | POLLOUT push rdi
mov si, POLLIN
call pollfds__append call pollfds__append
pop rdi pop rdi
call clients__append
add r15, 1 add r15, 1
jmp pollfds__scan__loop jmp scan__loop
; edi - fd
; si - events
pollfds__append:
; TODO check against pollfds_capacity
mov r10, [pollfds_len]
mov [pollfds + r10 * pollfd_size], edi
mov [pollfds + r10 * pollfd_size + 4], si
add r10, 1
mov [pollfds_len], r10
ret
; rdi - pollfds array index to remove
pollfds__remove:
mov r11, [pollfds_len]
cmp rdi, r10
jge return ; XXX index out of bounds, do some other error?
cmp r11, 1
jle pollfds__clear
mov r10, [pollfds + (r11 - 1) * pollfd_size]
mov [pollfds + rdi * pollfd_size], r10
sub r11, 1
mov [pollfds_len], r11
ret
pollfds__clear:
mov r10, 0
mov [pollfds_len], r10
ret
; esi - fd
clients__append:
; TODO check against client_capacity
mov r10, [clients_len]
imul r10, client_size
add r10, clients
mov [r10], esi
add r10, 4
mov r8b, 0
mov r11, 0
clients__append__init:
cmp r11, client_size
jge return
mov [r10 + r11], r8b
add r11, 1
jmp clients__append__init
return: return:
ret ret
exit: exit:
mov rax, SYS_EXIT mov rax, SYS_EXIT
mov rdi, 0 mov rdi, 255
syscall syscall

30
pollfds.s Normal file
View file

@ -0,0 +1,30 @@
; edi - fd
; si - events
pollfds__append:
; TODO check against pollfds_capacity
mov r10, [pollfds_len]
mov [pollfds + r10 * pollfd_size], edi
mov [pollfds + r10 * pollfd_size + 4], si
mov r11w, 0
mov [pollfds + r10 * pollfd_size + 6], r11w
add r10, 1
mov [pollfds_len], r10
ret
; rdi - pollfds array index to remove
pollfds__remove:
mov r11, [pollfds_len]
cmp rdi, r11
jge return ; XXX index out of bounds, do some other error?
cmp r11, 1
jle pollfds__clear
mov r10, [pollfds + (r11 - 1) * pollfd_size]
mov [pollfds + rdi * pollfd_size], r10
sub r11, 1
mov [pollfds_len], r11
ret
pollfds__clear:
mov r10, 0
mov [pollfds_len], r10
ret

View file

@ -1,34 +1,41 @@
; Returns length in rax ; 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): ; Errors (in rax):
; -1024 - line too long ; -1024 - line too long
; other negative - error from read(2) ; other negative - error from read(2)
; 0 - EOF from read(2)
; Arguments: ; Arguments:
; rdi - fd ; rdi - fd
; rsi - buffer ; rsi - buffer
; rdx - max length ; rdx - max length
readline: readline:
push rdi
push rsi push rsi
push rdx push rdx
mov rax, SYS_READ mov rax, SYS_READ
syscall syscall
pop rdx pop rdx
pop rsi pop rsi
pop rdi
cmp rax, 0 cmp rax, 0
jl return jl return
mov r10, 0 mov r10, 0
readline__scan: readline__scan:
cmp r10, rax cmp r10, rdx
jge readline__overflow jge readline__overflow
cmp r10, rax
jge readline__incomplete_line
mov r11b, [rsi + r10] mov r11b, [rsi + r10]
add r10, 1 add r10, 1
cmp r11b, 0x0a ; '\n' cmp r11b, 0x0a ; '\n'
jne readline__scan jne readline__scan
mov rdi, r10
ret
readline__return: readline__incomplete_line:
mov rax, r10 mov rdi, 0
ret ret
readline__overflow: readline__overflow: