From 6030a5f8fe7626cf5ad38d6a37d881f9ce2e620e Mon Sep 17 00:00:00 2001 From: Doczom <78043169+Doczom@users.noreply.github.com> Date: Sun, 19 Nov 2023 13:15:58 +0500 Subject: [PATCH] Added file server Added file server for no units URI paths. Fixed a lot of bugs in parser and mainloop. Added function Get_MIME_Type --- file_server.inc | 278 ++++++++++++++++++++++++++++++++++++++++++++++++ httpd.asm | 78 ++++++++++---- httpd.kex | Bin 0 -> 3118 bytes httpd_lib.inc | 103 ++++++++++++++++-- parser.inc | 30 +++++- settings.inc | 36 +++++-- sys_func.inc | 141 ++++++++++++++++++++++-- 7 files changed, 613 insertions(+), 53 deletions(-) create mode 100644 file_server.inc create mode 100644 httpd.kex diff --git a/file_server.inc b/file_server.inc new file mode 100644 index 0000000..032a2c4 --- /dev/null +++ b/file_server.inc @@ -0,0 +1,278 @@ +; Это модуль для обработки стандартных запросов на получение файла +; по пути, который не относится к другому модулю + + +file_server: + + ; check http version (skip RTSP) + mov ecx, [esi + CONNECT_DATA.http_verion] + cmp dword[ecx], 'HTTP' + jne .err_http_501 + cmp word[ecx + 4], '/1' + jne .err_http_501 + +; cmp byte[ecx + 7], '1' +; je .http_1_1 +; ; http 1.0; +; +;.http_1_1: + + ; check name on ../../ and other bad items + mov ecx, [esi + CONNECT_DATA.uri_path] +@@: + cmp byte[ecx], 0 + je .good_name + inc ecx + cmp dword[ecx - 1], '/../' ; if path "/.." then system read dir and + jne @b ; and skip this path with 404 error + jmp .err_http_501 + +.good_name: + + ; check file of name (generate full name: work_dir + path) + ; + ; alloc 4 kib for path to file name + ; memory alloced on stack and for working program alloced with buffer + ; for code stack + lea edx, [esp - 6*1024 - 4096] ; edx <- buffer for full path + + mov edi, edx + sub edi, sizeof.FILED; edi <- struct FILED + mov [edi + FILED.path], edx + + mov eax, esi + push esi edi + ;; copy work_dir + mov esi, GLOBAL_DATA.work_dir + mov edi, edx + mov ecx, [GLOBAL_DATA.work_dir.size] + rep movsb + ;; copy path + mov esi, [eax + CONNECT_DATA.uri_path] +@@: + movsb + cmp byte[esi - 1], 0 + jne @b + + mov eax, edi + dec eax + pop edi esi + mov [edi + FILED.end_path], eax + + ;; check file info (skip of directory and if syscall return error) + lea eax, [edi - 40] ; buffer for file info + mov [edi + FILED.buffer], eax + + push edi + call FileInfo + test eax, eax + jnz .err_not_found + + test dword[edi - 40], 11000b ; check dir OR disk partition + jnz .err_not_found + + + ; check method OPTIONS + mov ecx, [esi + CONNECT_DATA.http_method] + cmp dword[ecx], 'OPTI' + jne @f + cmp dword[ecx + 4], 'ONS' + je .send_options +@@: + cmp dword[ecx], 'POST' + jne @f + cmp byte[ecx + 4], 0 + je .send_file +@@: + cmp dword[ecx], 'GET' + jne .err_http_501 + +.send_file: + ; create http response (set 200 code, MINE type and length of body) + ;; alloc 33 kib + push dword 33*1024 + call Alloc + test eax, eax + jz .err_http_501 ; error memory + + push esi + push edi + push eax ; save pointer for Free + + mov esi, base_response + mov ecx, response.body + mov edi, [esp] + rep movsb + + mov edi, [esp] + mov dword[edi + response.code], '200 ' + + push dword[esp + 4] ; <-FILED + call Get_MIME_Type + + add edi, response.content_type + mov esi, eax +@@: + movsb + cmp byte[esi], 0 + jne @b + + + pop edi ; buffer on 32 kib + pop ebx ; FD + pop esi ; CONNECT_DATA + + ; copy length + mov edx, [ebx - 40 + 36] + mov eax, [ebx - 40 + 32] + lea ecx, [edi + response.content_len + 21] + test eax, eax + jne @f + test edx, edx + jz .err_not_found_1 +@@: + cmp edx, 1000 ; 999*4 - max length of file + jae .err_not_found_1 + ; edx:eax ecx - end char in string '000000' +.div1000: + div dword[_DIV_1000_] + push eax + + mov eax, edx + xor edx, edx +;.div100: + div dword[_DIV_100_] + push eax + + mov eax, edx + xor edx, edx + div dword[_DIV_10_] + add byte[ecx], dl + add byte[ecx - 1], al + sub ecx, 3 + + pop eax + add byte[ecx + 1], al + ;xor edx, edx + ;test eax, eax + ;jne .div100 + pop eax + xor edx, edx + test eax, eax + jne .div1000 + + ;send_response_header + push dword 0 ; flags + push response.body + push edi + push dword[esi + CONNECT_DATA.socket] + call netfunc_send + cmp eax, -1 + je .exit_free + + mov dword[ebx + FILED.offset], 0 + mov dword[ebx + FILED.offset + 4], 0 + mov [ebx + FILED.buffer], edi + mov [ebx + FILED.size], 32*1024 +.send_response_body: + ; read 32 kib to file + push ebx + call FileRead + test eax, eax + jz @f + cmp eax, 6 + jne .exit_free +@@: + ; send this block data + push dword 0 ; flags + push 32*1024 + push edi + push dword[esi + CONNECT_DATA.socket] + call netfunc_send + cmp eax, -1 + je .exit_free + + ; check end file + mov ecx, [ebx + FILED.offset + 4] + cmp [ebx - 4], ecx + ja .add_offset + + mov edx, [ebx + FILED.offset] + cmp [ebx - 8], edx + jbe .exit_free + +.add_offset: + add [ebx + FILED.offset], 32*1024 + adc [ebx + FILED.offset + 4], 0 + + jmp @b + +.exit_free: + push edi + call Free + ret + +.send_options: + ; send standart options of file server + push dword 0 ; flags + push http_response_options.size + push http_response_options + push dword[esi + CONNECT_DATA.socket] + call netfunc_send + + ret + +.err_not_found_1: + push edi + call Free +.err_not_found: + ; send error 404 + push dword 0 ; flags + push http_response_err_404.size + push http_response_err_404 + push dword[esi + CONNECT_DATA.socket] + call netfunc_send + + ret + +.err_http_501: + ; send error 501 + push dword 0 ; flags + push http_response_err_501.size + push http_response_err_501 + push dword[esi + CONNECT_DATA.socket] + call netfunc_send + + ret + + +; char* stdcall Get_MIME_Type(FILED* fd); //path is ASCIIZ string +Get_MIME_Type: + push esi edi + mov edx, [GLOBAL_DATA.MIME_types_arr] + mov esi, [esp + 4*2 + 4] + sub edx, 8 +.next: + add edx, 8 + mov ecx, [esi + FILED.end_path] ;pointer to \0 full path + + cmp dword[edx], 0 + jz .found + + mov edi, [edx] + movzx eax, byte[edi] + sub ecx, eax +@@: + inc edi + mov al, [edi] + cmp byte[ecx], al + jne .next + + inc ecx + test al, al + jne @b + +.found: + mov eax, [edx + 4] + pop edi esi + ret 4 diff --git a/httpd.asm b/httpd.asm index 82f4686..33cd00c 100644 --- a/httpd.asm +++ b/httpd.asm @@ -7,15 +7,20 @@ ; Version 0.0.1, 12 November 2023 ; ; ; ;*****************************************************************************; -use32 -org 0 - +;include "macros.inc" +include 'D:\kos\programs\macros.inc' +;include 'D:\kos\programs\network.inc' + use32 + org 0 + db 'MENUET01' + dd 1, START, I_END, MEM, STACKTOP, PATH, 0 +;KOS_APP_START include 'sys_func.inc' include 'settings.inc' - -start: +;CODE +START: mcall 68, 11 ; init heap mcall 40, EVM_STACK ;set event bitmap @@ -30,7 +35,7 @@ start: jnz .err_settings ;init server socket - push dword SO_NONBLOCK + push dword SO_NONBLOCK ; IPPROTO_TCP push dword SOCK_STREAM push dword AF_INET4 call netfunc_socket; AF_INET4, SOCK_STREAM, SO_NONBLOCK ; we dont want to block on accept @@ -64,9 +69,9 @@ start: .listen_err: .bind_err: push dword[srv_socket] - call close; [srv_socket] + call netfunc_close; [srv_socket] -..err_settings: +.err_settings: .sock_err: mcall -1 @@ -77,9 +82,12 @@ thread_connect: mcall 40, EVM_STACK ; set event bitmap - network event ; ожидание подключения Accept, sockaddr находится на вершине стека нового потока - lea edx, [esp + CONNECT_DATA.sockaddr] ; new sockaddr - push dword 16 ; 16 byte - sockaddr length - push edx + ;lea edx, [esp + CONNECT_DATA.sockaddr] ; new sockaddr + ;push dword 16 ; 16 byte - sockaddr length + ;push edx + push srv_sockaddr.length + push dword srv_sockaddr + push dword[srv_socket] call netfunc_accept @@ -119,8 +127,8 @@ thread_connect: test eax, eax jz @f add [esi + CONNECT_DATA.request_size], eax - cmp [esi + CONNECT_DATA.request_size], 0x8000 ; check end buffer - jb @b + ; cmp [esi + CONNECT_DATA.request_size], 0x8000 ; check end buffer + ; jb @b @@: ; после получения всего запроса(более или менее всего) выделяем озу для ; ассоциативного массива заголовков и аргументов запроса @@ -129,21 +137,26 @@ thread_connect: ; esp + 1024 .. esp + 2048 -> for URI args sub esp, 2048 - ; parse http message - call parse_http_query ; ecx - buffer edx - length data in buffer + ; parse http message + mov ecx, [esi + CONNECT_DATA.buffer_request] + call parse_http_query ; ecx - buffer test eax, eax jz .err_parse ; вызов нужной функции из списка моделей ; TODO + + ; if not found units, call file_server + call file_server ; esi - struct + ;TEST SERVER, DELETE ON RELISE + ; end work thread jmp .end_work .err_parse: - ; send error 501 - + call file_server.err_http_501 .end_work: add esp, 2048 ; free OUT buffer @@ -167,14 +180,21 @@ thread_connect: include 'parser.inc' +include 'file_server.inc' ; DATA AND FUNCTION include 'httpd_lib.inc' +default_ini_path: db 'httpd.ini',0 +I_END: +;DATA + ; DATA -srv_backlog: dd 0 ; максимум одновременных подключений подключений +;UDATA -srv_socket: dd 0 +srv_backlog: rd 1 ; максимум одновременных подключений подключений + +srv_socket: rd 1 srv_sockaddr: dw AF_INET4 @@ -184,9 +204,21 @@ srv_sockaddr: .length = $ - srv_sockaddr GLOBAL_DATA: - .units dd 0 ; указатель на ассоциативный массив пути и указателя на функцию либы(см ниж) - .unit_count dd 0 ; количество записей в массиве - .libs dd 0 ; указатель на массив указателей на ассоциативные массивы библиотек + .units rd 1 ; указатель на ассоциативный массив пути и указателя на функцию либы(см ниж) + .unit_count rd 1 ; количество записей в массиве + .libs rd 1 ; указатель на массив указателей на ассоциативные массивы библиотек + .work_dir rb 1024 ; max size path to work directory + .work_dir.size rd 1 ; length string + .unit_dir rb 1024 + .unit_dir.size rd 1 + + .MIME_types_arr rd 1 ;; .flags dd 0 ; 1 - all hosts(элемент hosts не указатель на массив, а на функцию) - +PATH: + rb 256 +; stack memory + rb 4096 +STACKTOP: +MEM: +;KOS_APP_END diff --git a/httpd.kex b/httpd.kex new file mode 100644 index 0000000000000000000000000000000000000000..2b23b9433cd5cc817cd9f92edfd5b761da463cab GIT binary patch literal 3118 zcmbtWTWlLy89r(3W*Y3ZSrTm*wdja?S1mZc=le!L=u`BgY;* zGucLj%9azvFdJBji$FZ^K!p(S!b+e-LB&m=MyM4K3AW+^AuX5LP0?o66-h(c;X5-< z(z455#7O^{Gv9yv{&W6w>~q7hr-u`PU<)DSHii#42#Gz`ln#J+;>o46c&)Ix_HmCx zOL*Lx?CH4KKQ_ARAaP5}B0$UC>>pjVkz^A+@CKjJv3;M`rVk=Im>;+2XMc0QWU3kW zprv=ivjbcXYjd6>h%i33>LzbdcJH0+Oq z*8zgbaYk^YVgC@`_3x{l4LjSSc7Vy$&j&EQs)O3H4Zxi%<6{l`019AV4f`4F-_m;s z3D(!v{L-vsQ3inIOULnAshIQS7z`^sQS8ed2&jMFFpPz|QqDnJ$+5z7Y#a60{%shw zZA1R#cRvWTDR+*MH2T5tF{X7myfBjpye&z0IH5Le0_>al%3V%%gRE4L?=Jgg5-k4zH;ui># zsF5dw>jUbuf7t#PK9aqs;qVd5;l#c}A9H}wJs2^IW3mHE`NazVxU#uX2cSG`n#4}B z+|=T<)`(EhCdjnSGI@gQSi{x`$6u4$K-k%?w80CU*Qz_{R3g1Ppe89Jv&Hhj?9UZG zr2KO?J5XRZ!V}e51I~9?;o*%RBd8j2*DgCAE?-n*hwo#c{`$j7uJ-Z)KIym|)qjb_ zZX#_A=~H7zc4KW#G!P6$-sjP&KZW%+5tz>%RAc?><{D0d7CTbqPbCr~u7y{yyP#w9 z2VDy z7@UvAiEG{myvmQ9k0+Fam025+9aTO$oPftLG&wSlBQtLWobLgWOpRQ1;wD)B2f}J6 zJs@(@(}*7G4g@GV)TTei0ye$@t$O`R<)cK|86O?f;`g+{?ZvMw0LCfj7S>(!zrwt_ zqod7TwVz?W)#pZmBkFI1>sx(}{VB&z)O$(TsJ+yBfrMKw1lJMbcjghxF%~JDs|!2U zRWRBZv;o?^_0-R~8-osZ2;;iltU|Wewht=3mN!!{@Ao&ok7{Q*{_MSHI4y4D=grM4$ql)s1P>&k1|fDJ!0HuBuL zQqh}G1aC^ndJ{Rt8!6|#@wDuXD@E^_bdg4ci}YN&Ov7Rs?^$|ADMAV~tW46lAky<0 znZ`;pbV$h1a3&*&a@Qx)#YsU5(TlUPAUWFyOU0s)k@KZuh-L~UNg(J4dTKa4#JXhU z=>#1KCk9WkcJ>E-K^nl$JKN(zc}6IQsFa@;3qn^;mc^_;;0ySI&i0|SEQBayNP7Y% zgYH0gHx2NiZax(3q0w^*Gp#HX<*tHIoRo7R8rX;ASrPuSa7p%yg>=67CLEpZ&h|Y< zeSzTHFhY$FB;&zy7kh`D0K(Q(k z){^EWS}e&_Qbe&-mW3>ZcN$1eC{uyO^6l~O4fMWC{=I$gnm^+vnVUv4C8dxx*-hk& zSqe(KrGTc$D%qpf{kGJ?g+l3>5M|d4ZWu2`^LQ!ioVVV!z&q%p!E`1kbg_LZmkJ>e z?#eJ^zx3f^rj*5YglImCUdqd}`?|fpLchN8*|)Q{pZ=fE|0ve%;ha2OAm%J1N!Da4 zJ(HF)<-90c-)5VWv?vzxnKV0!{wb+cd;k!$6C^*4&GC!HNs?Bw`I3KH6eh_GYG>2l z2h2+uS&+LVxh$loiQQ*%u=yB)R^OCFY(DvtjFCmP13)r-Ah69hE%umWFR9{h+z#&k zFXC;3d>P_|d=+vO@+}At`3~eb