spartserv

Simple client and server for the spartan protocol
git clone https://noulin.net/git/spartserv.git
Log | Files | Refs | README

main.asm (6527B)


      1 %include "constants.asm"
      2 %include "macros.asm"
      3 
      4 ;Follwing amd64 syscall standards for internal function calls: rdi rsi rdx r10 r8 r9
      5 
      6 section .data
      7     %include "data.asm"
      8 
      9 section .bss
     10     listen_socket: resq 1
     11     listen_port: resw 1
     12     one_constant: resq 1
     13     directory_path: resq 1
     14 
     15 section .text
     16     %include "string.asm"
     17     %include "syscall.asm"
     18 
     19 global  _start
     20 
     21 _start:
     22 
     23     mov QWORD [one_constant], 1
     24 
     25     mov rdi, [rsp]    ;Num of args
     26     cmp rdi,3         ;Exit if no argument, should be directory location
     27     jne exit_with_help
     28 
     29     mov rdi, [rsp+16+8]; Port (second) parameter
     30     call string_atoi
     31     xchg al, ah
     32     mov [listen_port], eax
     33 
     34     mov rax, [rsp+16] ;Directory (first) parameter
     35     mov [directory_path], rax
     36 
     37     ;Try opening directory
     38     mov rdi, [directory_path]
     39     call sys_open_directory
     40 
     41     cmp rax, 0
     42     jl exit_with_no_directory_error
     43 
     44     ;Create socket
     45     call sys_create_tcp_socket
     46     cmp rax, 0
     47     jl exit_error
     48     mov [listen_socket], rax
     49 
     50     ;reuseaddr
     51     mov rdi, [listen_socket]
     52     call sys_reuse
     53 
     54     ;Bind to port
     55     call sys_bind_server
     56     cmp rax, 0
     57     jl exit_bind_error
     58 
     59     ;Start listening
     60     call sys_listen
     61 
     62     mov rbp, rsp
     63     sub rsp, 16
     64     ;Offsets: 8 - socket fd, 16 - buffer
     65 
     66     mov QWORD [rbp-16], 0 ; Used for pointer to recieve buffer
     67 
     68     mov rdi, BUFFER_SIZE+2+URL_LENGTH_LIMIT+DIRECTORY_LENGTH_LIMIT ; Allow room to append nul, and to create path
     69     call sys_mmap_mem
     70     mov QWORD [rbp-16], rax
     71 
     72 event_loop_start:
     73 
     74     call sys_accept
     75 
     76     mov [rbp-8], rax ; save fd
     77 
     78     mov rdi, rax
     79     call sys_cork ; cork it
     80 
     81     ;Network stuff starts here
     82     mov rdi, QWORD [rbp-8] ;fd
     83     mov rsi, [rbp-16]      ;buffer
     84     mov rdx, BUFFER_SIZE   ;size
     85     call sys_recv
     86 
     87     cmp rax, 0
     88     jle close_client_connection
     89 
     90     push rax ; save original received length
     91 
     92     ; add nul
     93     mov rdi, [rbp-16]
     94     add rdi, rax
     95     mov BYTE [rdi], 0x00
     96 
     97     ;Make sure its a valid request
     98     mov rdi, [rbp-16]
     99     mov rsi, crlf
    100     call string_ends_with
    101     cmp rax, 1
    102     jne invalid_request_response_pop_length
    103 
    104     ;Find request
    105     mov rax, 0x2F ; '/' character
    106     mov rdi, [rbp-16] ;scan buffer
    107     mov rcx, -1         ;Start count
    108     cld               ;Increment rdi
    109     repne scasb
    110     jne invalid_request_response_pop_length
    111     mov rax, -2
    112     sub rax, rcx      ;Get the length
    113 
    114     mov r8, rax ; start offset for requested file
    115     mov rdi, [rbp-16]
    116     add rdi, r8
    117     mov rax, 0x20  ;'space' character
    118     mov rcx, -1
    119     cld
    120     repne scasb
    121     jne invalid_request_response_pop_length
    122     mov rax, -1
    123     sub rax, rcx
    124     mov r9, rax
    125     add r9, r8  ;end offset
    126 
    127     ;TODO: Assuming it's a file, need directory handling too
    128 
    129     pop r11 ; restore orig recvd length
    130     mov rdi, [rbp-16]
    131     add rdi, r11 ; end of buffer, lets use it!
    132     mov r12, r11 ; keeping count
    133 
    134     mov rsi, [directory_path]
    135     xor r15, r15 ; Make sure directory path does not exceed DIRECTORY_LENGTH_LIMIT
    136 
    137 append_directory_path:
    138     inc r15
    139     cmp r15, DIRECTORY_LENGTH_LIMIT
    140     je invalid_request_response
    141     lodsb
    142     stosb
    143     inc r12
    144     cmp al, 0x00
    145     jne append_directory_path
    146 
    147     dec r12 ; get rid of 0x00
    148 
    149     ; Adds the file to the end of buffer ( where we just put the document prefix )
    150     mov rsi, [rbp-16]
    151     add rsi, r8  ; points to beginning of path
    152     mov rdi, [rbp-16]
    153     add rdi, r12 ;go to end of buffer
    154     mov rcx, r9
    155     sub rcx, r8
    156     cmp rcx, URL_LENGTH_LIMIT ; Make sure this does not exceed URL_PATH_LENGTH
    157     jg invalid_request_response
    158     add r12, rcx
    159     rep movsb
    160 
    161     dec r12 ; exclude space character
    162     mov rdi, [rbp-16]
    163     add rdi, r12
    164     mov BYTE [rdi], 0x00 ; add nul
    165 
    166     mov r9, r11 ; saving offset into a stack saved register
    167     ; [rbp-16] + r9 now holds string for file opening
    168 
    169     remove_pre_dir:
    170 
    171     ;-----Simple request logging
    172     ; mov rdi, msg_request_log
    173     ; mov rsi, msg_request_log_len
    174     ; call sys_write
    175     ; mov rdi, [rbp-16]
    176     ; add rdi, r9
    177     ; call get_string_length
    178     ; mov rsi, rax
    179     ; call print_line
    180     ;-----End Simple logging
    181 
    182     mov rdi, [rbp-16]
    183     add rdi, r9
    184     mov rsi, filter_prev_dir ; remove any '../'
    185     call string_remove
    186     cmp rax, 0
    187     jne remove_pre_dir
    188 
    189 
    190     ; TODO content types
    191     ; mov rdi, [rbp-16]
    192     ; add rdi, r9
    193     ; call detect_content_type
    194     ; mov r8, rax ;r8: Content Type
    195 
    196     ;------------response----------------
    197 
    198     ;Try to open requested file
    199     mov rdi, [rbp-16]
    200     add rdi, r9
    201     call sys_open
    202     cmp rax, 0
    203 
    204     jl invalid_request_response ;file not found
    205 
    206     ; Done with buffer offsets, put response and data into it starting at beg
    207     mov r10, rax ; r10: file fd
    208 
    209     ; we're good to go
    210 
    211     ;---------2 Response Start------------
    212 
    213     ; get file size
    214     mov rdi, r10 ; fd
    215     xor rsi, rsi
    216     mov rdx, LSEEK_END
    217     call sys_lseek
    218 
    219     ;rax - total filesize
    220     push rax
    221 
    222     ;Seek to beg of file
    223     mov rdi, r10 ; fd
    224     xor rsi, rsi
    225     mov rdx, LSEEK_SET
    226     call sys_lseek
    227 
    228     ; send response header
    229     mov rdi, [rbp-8] ; socket
    230     mov rsi, text_gemini_s
    231     mov rdx, text_gemini_s_len
    232     call sys_send
    233 
    234     cmp rax, 0
    235     jle close_file
    236 
    237     ; send file
    238     mov rdi, [rbp-8] ; socket
    239     mov rsi, r10 ; fd
    240     pop rdx ; file size
    241     call sys_sendfile
    242     jmp close_file
    243     ;---------2 Response End--------------
    244 
    245     ;---------4 Response Start------------
    246 invalid_request_response_pop_length:
    247     pop rsi
    248 
    249 invalid_request_response:
    250     mov rdi, [rbp-8] ; socket
    251     mov rsi, invalid_s
    252     mov rdx, invalid_s_len
    253     call sys_send
    254 
    255     jmp close_client_connection
    256     ;---------4 Response End--------------
    257 
    258  close_file:
    259     ;Uncork
    260     mov rdi, [rbp-8]
    261     call sys_uncork
    262 
    263     ;Close File
    264     mov rdi, r10
    265     call sys_close
    266 
    267     ;Close Socket
    268 close_client_connection:
    269     mov rdi, [rbp-8]
    270     call sys_close
    271 
    272     jmp event_loop_start
    273 
    274 exit_with_no_directory_error:
    275     mov rdi, msg_not_a_directory
    276     mov rsi, msg_not_a_directory_len
    277     call print_line
    278     jmp exit
    279 
    280 exit_with_help:
    281     mov rdi, msg_help
    282     mov rsi, msg_help_len
    283     call print_line
    284     jmp exit
    285 
    286 exit_error:
    287     mov rdi, msg_error
    288     mov rsi, msg_error_len
    289     call print_line
    290 
    291     mov rdi, -1
    292     mov rax, SYS_EXIT_GROUP
    293     syscall
    294     jmp exit
    295 
    296 exit_bind_error:
    297     mov rdi, msg_bind_error
    298     mov rsi, msg_bind_error_len
    299     call print_line
    300 
    301     mov rdi, -1
    302     mov rax, SYS_EXIT_GROUP
    303     syscall
    304     jmp exit
    305 
    306 exit:
    307 
    308     mov rdi, [listen_socket]
    309     call sys_close
    310 
    311     xor rdi, rdi
    312     mov rax, SYS_EXIT_GROUP
    313     syscall
    314