diff --git a/bin/httpd b/bin/httpd new file mode 100644 index 0000000..b1b9943 Binary files /dev/null and b/bin/httpd differ diff --git a/example/httpd.ini b/bin/httpd.ini similarity index 66% rename from example/httpd.ini rename to bin/httpd.ini index 0ab3f65..f7ef16e 100644 --- a/example/httpd.ini +++ b/bin/httpd.ini @@ -1,29 +1,27 @@ -[MAIN] -; server IPv4 address. Non IPv6 address -ip=192.168.137.21 -; server port number -port=80 -; count open connection -conn=100 - -; 1000 - no parse http headers, raw data in CONNECT_DATA.message_body -; This flags using for http/2.0 and other protocol execution. -;flags=0000 ; parsing http headers - -; directory for find files -work_dir=/usbhd0/3/server_data -; directory for find units(library) -units_dir=/usbhd0/3 - -mime_file=/usbhd0/3/mime_types.bin - -[UNITS] -; list units -; path = path to lib in units_dir -test=test_unit.obj -rasp=test_unit_2.obj -;database/sqlite3=sqlite3_serv.obj -;database/cvs=cvs_table_server.obj - -; server calling function httpd_serv(CONNECT_DATA* struct_server ); -; for init unit, server calling function httpd_init(void* global_data); \ No newline at end of file +[MAIN] +; server IPv4 address. Non IPv6 address +ip=192.168.137.21 +; server port number +port=80 +; count open connection +conn=100 + +; 1000 - no parse http headers, raw data in CONNECT_DATA.message_body +; This flags using for http/2.0 and other protocol execution. +;flags=0000 ; parsing http headers + +; directory for find files +work_dir=/usbhd0/3/server_data +; directory for find units(library) +modules_dir=/usbhd0/3 + +mime_file=/usbhd0/3/mime_types.bin + +[MODULES] +; list units +; path = unit_name;cmdline +; not uning ' ' in unit_name;cmdline : "path = unit_name ; cmdline" is bad name +test=test_unit.obj +rasp=test_unit_2.obj +;database/sqlite3=sqlite3_serv.obj +;database/cvs=cvs_table_server.obj \ No newline at end of file diff --git a/utils/mime_types.bin b/bin/mime_types.bin similarity index 100% rename from utils/mime_types.bin rename to bin/mime_types.bin diff --git a/bin/modules/test_unit.obj b/bin/modules/test_unit.obj new file mode 100644 index 0000000..44922db Binary files /dev/null and b/bin/modules/test_unit.obj differ diff --git a/bin/modules/test_unit4.obj b/bin/modules/test_unit4.obj new file mode 100644 index 0000000..190a0e3 Binary files /dev/null and b/bin/modules/test_unit4.obj differ diff --git a/bin/modules/test_unit_2.obj b/bin/modules/test_unit_2.obj new file mode 100644 index 0000000..3bb0572 Binary files /dev/null and b/bin/modules/test_unit_2.obj differ diff --git a/example/test_unit.asm b/example/test_unit.asm index e83f870..efb2e85 100644 --- a/example/test_unit.asm +++ b/example/test_unit.asm @@ -1,70 +1,11 @@ format MS COFF public @EXPORT as 'EXPORTS' -API_VERSION = 0x05 -FLAG_KEEP_ALIVE = 0x01 +include "macros.inc" + +include '../module_api.inc' NO_DEBUG_INPUT = 0 -include 'D:\kos\programs\macros.inc' - -struct IMPORT_DATA - version rd 1 ; dword for check api - sizeof rd 1 ; size struct - netfunc_socket rd 1 - netfunc_close rd 1 - netfunc_bind rd 1 - netfunc_accept rd 1 - netfunc_listen rd 1 - netfunc_recv rd 1 - netfunc_send rd 1 - FileInfo rd 1 - FileRead rd 1 - Alloc rd 1 - Free rd 1 - parse_http_query rd 1 - ;send_resp(RESPD* ptr, char* content, uint32_t length) - ;create_resp(CONNECT_DATA* session, uint32_t flags) - ; FLAG_KEEP_ALIVE = 0x01 - ; FLAG_ADD_DATE = 0x02 ;(not supported) - ; FLAG_NO_SET_CACHE = 0x04 ;(not supported) - ; FLAG_NO_CONTENT_ENCODING = 0x08 ;(not supported) - ; - ;destruct_resp(RESPD* ptr) - ;set_http_status(RESPD* ptr, uint32_t status) ; status in '200' format, - ;add_http_header(RESPD* ptr, char* ptr_header) - ;del_http_header(RESPD* ptr, char* ptr_header) ; no del std header - ;set_http_ver(RESPD* ptr, char* version) ; example: RTSP/1.1 - send_resp rd 1 - create_resp rd 1 - destruct_resp rd 1 - set_http_status rd 1 - add_http_header rd 1 - del_http_header rd 1 - set_http_ver rd 1 - - base_response rd 1 - GLOBAL_DATA rd 1 -ends - -struct CONNECT_DATA ; 16*4 = 64 bytes - socket dd 0 ; номер сокета подключения - sockaddr dd 16/4 ; socaddr connection - buffer_request dd 0 ; pointer to buffer for geting message socket - request_size dd 0 ; size geted data from client - end_buffer_request dd 0 ; для парсера - buffer_response dd 0 ; pointer to buffwr for resp message - http_method dd 0 ; указатель на строку - http_verion dd 0 ; указатель на строку - num_headers dd 0 ; number items in REQUEST_DATA - http_headers dd 0 ; указатель на массив REQUEST_DATA - uri_scheme dd 0 ; указатель на схему - uri_authority dd 0 ; pointer to struct ? - uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров) - num_uri_args dd 0 ; - uri_arg dd 0 ; pointer to array REQUEST_DATA аргументов uri строк - uri_fragment dd 0 ; указатель на строку - message_body dd 0 ; указатель на тело http запроса -ends macro board_input message { if NO_DEBUG_INPUT = 0 @@ -89,7 +30,7 @@ end if section '.flat' code readable align 16 unit_init: - mov eax, -1 + xor eax, eax push esi edi mov esi, [esp + 4*2 + 4] mov [import_httpd], esi @@ -102,10 +43,10 @@ unit_init: shr ecx, 2 ; div 4 rep movsd - xor eax, eax + mov eax, 1 ;no zero return - unit init successful .exit: pop edi esi - ret 4 + ret 8 server_entry: @@ -165,7 +106,7 @@ server_entry: board_input 'create message' ; create http message push dword 8*1024 - call [IMPORT + IMPORT_DATA.Alloc] + call [IMPORT.Alloc] test eax, eax jz .exit @@ -214,13 +155,18 @@ server_entry: push sceleton_resp.size push edi push dword[esi + CONNECT_DATA.socket] - call [IMPORT + IMPORT_DATA.netfunc_send] + call [IMPORT.netfunc_send] board_input 'send' .exit: pop edi esi + ret 8 + +server_close: + ret 4 + section '.data' data readable writable align 16 _10: dd 10 @@ -263,7 +209,8 @@ text_message: @EXPORT: export \ unit_init, 'httpd_init', \ - server_entry, 'httpd_serv' + server_entry, 'httpd_serv',\ + server_close, 'httpd_close' IMPORT IMPORT_DATA ; \ No newline at end of file diff --git a/example/test_unit.obj b/example/test_unit.obj deleted file mode 100644 index d270688..0000000 Binary files a/example/test_unit.obj and /dev/null differ diff --git a/example/test_unit4.asm b/example/test_unit4.asm new file mode 100644 index 0000000..e55cb60 --- /dev/null +++ b/example/test_unit4.asm @@ -0,0 +1,100 @@ +; test api 0.1.0 - get cmd path and get context unit +format MS COFF ;<- this is lib format +public @EXPORT as 'EXPORTS' + +NO_DEBUG_INPUT = 0 +include "macros.inc" +purge mov,add,sub +include "proc32.inc" + +include '../module_api.inc' + +section '.flat' code readable align 16 + +unit_init: + xor eax, eax + push esi edi + mov esi, [esp + 4*2 + 4] + + cmp dword[esi + IMPORT_DATA.version], API_VERSION + jne .exit + + mov edi, IMPORT + mov ecx, [esi + IMPORT_DATA.sizeof] + shr ecx, 2 ; div 4 + rep movsd + + ; create unit context + invoke IMPORT.Alloc, 4096 ; for cmd path + test eax, eax + jz .exit + + mov dword[eax], 0 + mov esi, [esp + 4*2 + 8] + lea edi, [eax + 4] + test esi, esi + jz .exit + pushfd + cld +@@: + cmp byte[esi], 0 + jz @f + movsb + inc dword[eax] + jmp @b +@@: + popfd + ;unit init successful +.exit: + pop edi esi + ret 8 + + +server_entry: + push esi edi + mov esi, [esp + 4*2 + 4] ; request context + + mov edi, [esp + 4*2 + 8] ; unit context + cmp dword[edi], 0 + je .no_cmd + + add edi, 4 + invoke IMPORT.create_resp, esi, 0 + test eax, eax + jz .exit + + push eax + invoke IMPORT.send_resp, eax, edi, [edi - 4] + invoke IMPORT.destruct_resp ; arg in stack +.exit: + pop edi esi + ret 8 +.no_cmd: + invoke IMPORT.create_resp, esi, 0 + test eax, eax + jz .exit + + push eax + invoke IMPORT.send_resp, eax, text_no_cmd, text_no_cmd.size + invoke IMPORT.destruct_resp + jmp .exit + +server_close: + + ret 4 + + +section '.data' data readable writable align 16 + +text_no_cmd: + db 'For this unit in config not set arguments' +.size = $ - $$ + +@EXPORT: +export \ + unit_init, 'httpd_init', \ + server_entry, 'httpd_serv',\ + server_close, 'httpd_close' + + +IMPORT IMPORT_DATA \ No newline at end of file diff --git a/example/test_unit_2.asm b/example/test_unit_2.asm index 21aea90..cc21380 100644 --- a/example/test_unit_2.asm +++ b/example/test_unit_2.asm @@ -1,72 +1,12 @@ format MS COFF public @EXPORT as 'EXPORTS' -API_VERSION = 0x05 -FLAG_KEEP_ALIVE = 0x01 - NO_DEBUG_INPUT = 0 -include 'D:\kos\programs\macros.inc' +include "macros.inc" purge mov,add,sub -include 'D:\kos\programs\proc32.inc' +include "proc32.inc" -struct IMPORT_DATA - version rd 1 ; dword for check api - sizeof rd 1 ; size struct - netfunc_socket rd 1 - netfunc_close rd 1 - netfunc_bind rd 1 - netfunc_accept rd 1 - netfunc_listen rd 1 - netfunc_recv rd 1 - netfunc_send rd 1 - FileInfo rd 1 - FileRead rd 1 - Alloc rd 1 - Free rd 1 - parse_http_query rd 1 - ;send_resp(RESPD* ptr, char* content, uint32_t length) - ;create_resp(CONNECT_DATA* session, uint32_t flags) - ; FLAG_KEEP_ALIVE = 0x01 - ; FLAG_ADD_DATE = 0x02 ;(not supported) - ; FLAG_NO_SET_CACHE = 0x04 ;(not supported) - ; FLAG_NO_CONTENT_ENCODING = 0x08 ;(not supported) - ; - ;destruct_resp(RESPD* ptr) - ;set_http_status(RESPD* ptr, uint32_t status) ; status in '200' format, - ;add_http_header(RESPD* ptr, char* ptr_header) - ;del_http_header(RESPD* ptr, char* ptr_header) ; no del std header - ;set_http_ver(RESPD* ptr, char* version) ; example: RTSP/1.1 - send_resp rd 1 - create_resp rd 1 - destruct_resp rd 1 - set_http_status rd 1 - add_http_header rd 1 - del_http_header rd 1 - set_http_ver rd 1 - - base_response rd 1 - GLOBAL_DATA rd 1 -ends - -struct CONNECT_DATA ; 16*4 = 64 bytes - socket dd 0 ; номер сокета подключения - sockaddr dd 16/4 ; socaddr connection - buffer_request dd 0 ; pointer to buffer for geting message socket - request_size dd 0 ; size geted data from client - end_buffer_request dd 0 ; для парсера - buffer_response dd 0 ; pointer to buffwr for resp message - http_method dd 0 ; указатель на строку - http_verion dd 0 ; указатель на строку - num_headers dd 0 ; number items in REQUEST_DATA - http_headers dd 0 ; указатель на массив REQUEST_DATA - uri_scheme dd 0 ; указатель на схему - uri_authority dd 0 ; pointer to struct ? - uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров) - num_uri_args dd 0 ; - uri_arg dd 0 ; pointer to array REQUEST_DATA аргументов uri строк - uri_fragment dd 0 ; указатель на строку - message_body dd 0 ; указатель на тело http запроса -ends +include '../module_api.inc' macro board_input message { if NO_DEBUG_INPUT = 0 @@ -91,7 +31,7 @@ end if section '.flat' code readable align 16 unit_init: - mov eax, -1 + xor eax, eax push esi edi mov esi, [esp + 4*2 + 4] @@ -103,10 +43,10 @@ unit_init: shr ecx, 2 ; div 4 rep movsd - xor eax, eax + mov eax, 1 ;no zero return - unit init successful .exit: pop edi esi - ret 4 + ret 8 server_entry: @@ -193,7 +133,7 @@ server_entry: invoke IMPORT.destruct_resp ; arg in stack .exit: pop edi esi - ret 4 + ret 8 .send_data: ; eax - ptr to buffer mov edi, eax @@ -223,7 +163,9 @@ server_entry: invoke IMPORT.destruct_resp, edi jmp .exit +server_close: + ret 4 section '.data' data readable writable align 16 @@ -258,7 +200,8 @@ btp_name: @EXPORT: export \ unit_init, 'httpd_init', \ - server_entry, 'httpd_serv' + server_entry, 'httpd_serv',\ + server_close, 'httpd_close' IMPORT IMPORT_DATA ; \ No newline at end of file diff --git a/example/test_unit_2.obj b/example/test_unit_2.obj deleted file mode 100644 index 6ec6f20..0000000 Binary files a/example/test_unit_2.obj and /dev/null differ diff --git a/file_server.inc b/file_server.inc index f32a846..33fad47 100644 --- a/file_server.inc +++ b/file_server.inc @@ -1,7 +1,7 @@ ; This is a module for processing standard requests to get a file along ; a path that does not belong to another module. -SIZE_FILE_BUFFER = 64*1024 +SIZE_FILE_BUFFER = 64*1024 file_server: @@ -258,7 +258,10 @@ file_server: Get_MIME_Type: push esi edi mov eax, [esp + 4*2 + 4] + mov edx, [eax + FILED.path] mov eax, [eax + FILED.end_path] + push eax + sub [esp], edx mov edx, [GLOBAL_DATA.MIME_types_arr] @@: mov esi, [edx] @@ -268,12 +271,16 @@ Get_MIME_Type: mov edi, eax movzx ecx, byte [esi] + cmp ecx, [esp] + jae @b + inc esi sub edi, ecx repe cmpsb jne @b @@: mov eax, esi + pop edi ;clear value in stack pop edi esi ret 4 .other: diff --git a/httpd.asm b/httpd.asm index 1ee4200..d5a0f3c 100644 --- a/httpd.asm +++ b/httpd.asm @@ -8,16 +8,18 @@ ; ; ;*****************************************************************************; -API_VERSION = 0x05 ; 0.0.5 ;include "macros.inc" use32 org 0 db 'MENUET01' dd 1, START, I_END, MEM, STACKTOP, PATH, 0 -include 'D:\kos\programs\macros.inc' +include "macros.inc" purge mov,add,sub -include 'D:\kos\programs\proc32.inc' -include 'D:\kos\programs\dll.inc' + +include 'module_api.inc' + +include "proc32.inc" +include "dll.inc" ;include 'D:\kos\programs\network.inc' ;KOS_APP_START @@ -153,36 +155,37 @@ thread_connect: test eax, eax jz .err_parse ; find unit for uri path - cmp dword[GLOBAL_DATA.units], 0 - jz .no_units + cmp dword[GLOBAL_DATA.modules], 0 + jz .no_modules - mov eax, [GLOBAL_DATA.units] + mov eax, [GLOBAL_DATA.modules] .next_unit: push esi edi mov esi, [esi + CONNECT_DATA.uri_path] - lea edi, [eax + HTTPD_UNIT.uri_path] + lea edi, [eax + HTTPD_MODULE.uri_path] @@: cmpsb jne @f cmp byte[edi - 1], 0 jne @b - ; found unit + ; found module pop edi esi - push esi - call dword[eax + HTTPD_UNIT.httpd_serv] ; call unit function + push dword[eax + HTTPD_MODULE.pdata] ; context of module + push esi ; coutext of request + call dword[eax + HTTPD_MODULE.httpd_serv] ; call unit function jmp .end_work @@: pop edi esi - mov eax, [eax] ; HTTPD_UNIT.next + mov eax, [eax] ; HTTPD_MODULE.next test eax, eax ; terminate list jne .next_unit -.no_units: - ; if not found units, call file_server +.no_modules: + ; if not found modules, call file_server call file_server ; esi - struct ; end work thread jmp .end_work @@ -232,29 +235,31 @@ import libini,\ default_ini_path: db 'httpd.ini',0 -ini_section_units: db 'UNITS',0 +ini_section_units: db 'MODULES',0 ini_section_main: db 'MAIN', 0 ini_key_ip db 'ip',0 ini_key_port db 'port',0 ini_key_conn db 'conn',0 -;ini_key_flags db 'flags',0 +ini_key_flags db 'flags',0 ini_key_work_dir db 'work_dir',0 -ini_key_units_dir db 'units_dir',0 +ini_key_modules_dir db 'modules_dir',0 ini_key_mime_file db 'mime_file',0 -httpd_unit_init db 'httpd_init',0 -httpd_unit_serv db 'httpd_serv',0 +httpd_module_init db 'httpd_init',0 +httpd_module_serv db 'httpd_serv',0 +httpd_module_close db 'httpd_close',0 -IMPORT_UNIT: - dd httpd_import, GLOBAL_DATA.unit_dir, 0 +IMPORT_MODULE: + dd httpd_import, GLOBAL_DATA.modules_dir, 0 httpd_import: -.init dd httpd_unit_init -.serv dd httpd_unit_serv +.init dd httpd_module_init +.serv dd httpd_module_serv +.close dd httpd_module_close dd 0 -EXPORT_DATA: +EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA dd API_VERSION dd .size dd netfunc_socket @@ -277,6 +282,9 @@ EXPORT_DATA: dd add_http_header dd del_http_header dd set_http_ver + dd find_uri_arg + dd find_header + dd close_server dd base_response dd GLOBAL_DATA @@ -298,15 +306,16 @@ srv_sockaddr: .length = $ - srv_sockaddr GLOBAL_DATA: - .units rd 1 ; pointer to a doubly connected non-cyclic list (null terminator) + .modules rd 1 ; pointer to a doubly connected non-cyclic list (null terminator) ; next, prev, ptr of httpd_serv(), uri path - .work_dir rb 1024 ; max size path to work directory - .work_dir.size rd 1 ; length string - .unit_dir rb 1024 - .unit_dir.end rd 1 + .work_dir rb 1024 ; max size path to work directory + .work_dir.size rd 1 ; length string + .modules_dir rb 1024 + .modules_dir.end rd 1 - .MIME_types_arr rd 1 -; .flags rd 1 + .MIME_types_arr rd 1 + .flags rd 1 + ._module_cmd rd 1 PATH: rb 256 diff --git a/httpd.ini b/httpd.ini index 10c21c1..1fd225b 100644 --- a/httpd.ini +++ b/httpd.ini @@ -15,9 +15,9 @@ work_dir=/sys/http_server/data ; directory for find lib units_dir=/sys/http_units -;mime_file=/sys/network/mime.bin +mime_file=/sys/network/mime.bin -;[UNITS] +[UNITS] ; list units ; path = path to lib in units_dir ;database/sqlite3=sqlite3_serv.obj diff --git a/httpd_lib.inc b/httpd_lib.inc index 338a76b..e5f17d9 100644 --- a/httpd_lib.inc +++ b/httpd_lib.inc @@ -51,7 +51,6 @@ ;serv_header: ; .Accept_Ranges db 'Accept-Ranges: bytes',13,10 - ; .connection db 'Connection: close',0 ;http_method: ; .get: db 'GET ' diff --git a/makefile b/makefile new file mode 100644 index 0000000..f5d9b19 --- /dev/null +++ b/makefile @@ -0,0 +1,19 @@ +OUTPUT_DIR=bin +OUTPUT_MODULES=$(OUTPUT_DIR)/modules + +examples=$(wildcard example/*.asm) +examples_obj=$(patsubst %.asm,%.obj,$(examples)) + + +all: build-main build-mime $(examples_obj) + + +build-main: + fasm httpd.asm $(OUTPUT_DIR)/httpd + +build-mime: + fasm utils/mime_types.asm $(OUTPUT_DIR)/mime_types.bin + +example/%.obj: example/%.asm + fasm $< $(OUTPUT_MODULES)/$(notdir $(basename $@)).obj + diff --git a/module_api.inc b/module_api.inc new file mode 100644 index 0000000..6b9096c --- /dev/null +++ b/module_api.inc @@ -0,0 +1,78 @@ +;*****************************************************************************; +; ; +; Structures and constants for modules of simple-httpd ; +; ; +;*****************************************************************************; + +API_VERSION = 0x100 ; 0.1.0 + +FLAG_KEEP_ALIVE = 0x01 +FLAG_ADD_DATE = 0x02 ;(not supported) +FLAG_NO_SET_CACHE = 0x04 ;(not supported) +FLAG_NO_CONTENT_ENCODING = 0x08 ;(not supported) +FLAG_TRASFER_CHUNKED = 0x10 ;(not supported) + +struct CONNECT_DATA ; 16*4 = 64 bytes + socket dd 0 ; номер сокета подключения + sockaddr dd 16/4 ; socaddr connection + buffer_request dd 0 ; pointer to buffer for geting message socket + request_size dd 0 ; size geted data from client + end_buffer_request dd 0 ; для парсера + buffer_response dd 0 ; pointer to buffwr for resp message + http_method dd 0 ; указатель на строку + http_verion dd 0 ; указатель на строку + num_headers dd 0 ; number items in REQUEST_DATA + http_headers dd 0 ; указатель на массив REQUEST_DATA + uri_scheme dd 0 ; указатель на схему + uri_authority dd 0 ; pointer to struct ? + uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров) + num_uri_args dd 0 ; + uri_arg dd 0 ; pointer to array REQUEST_DATA аргументов uri строк + uri_fragment dd 0 ; указатель на строку + message_body dd 0 ; указатель на тело http запроса +ends + + +struct IMPORT_DATA + version rd 1 ; dword for check api + sizeof rd 1 ; size struct + netfunc_socket rd 1 + netfunc_close rd 1 + netfunc_bind rd 1 + netfunc_accept rd 1 + netfunc_listen rd 1 + netfunc_recv rd 1 + netfunc_send rd 1 + FileInfo rd 1 + FileRead rd 1 + Alloc rd 1 + Free rd 1 + parse_http_query rd 1 ; not standart calling, not using this function + send_resp rd 1 + ; send_resp(RESPD* ptr, char* content, uint32_t length); + create_resp rd 1 + ; RESPD* create_resp(CONNECT_DATA* session, uint32_t flags); + destruct_resp rd 1 + ; void stdcall destruct_resp(RESPD* ptr); + set_http_status rd 1 + ; void set_http_status(RESPD* ptr, uint32_t status); + ; status in '200' format + add_http_header rd 1 + ; uint32_t add_http_header(RESPD* ptr, char* ptr_header, uint32_t length); + del_http_header rd 1 + ; uint32_t del_http_header(RESPD* ptr, char* ptr_header); + ; no del std header + set_http_ver rd 1 + ; void set_http_ver(RESPD* ptr, char* version, uint32_t length); + ; example: 'RTSP/1.1 ' + find_uri_arg rd 1 + ;char* find_uri_arg(CONNECT_DATA* session, char* key); + find_header rd 1 + ;char* find_header(CONNECT_DATA* session, char* key); + close_server rd 1 + ;void close_server(); + + + base_response rd 1 + GLOBAL_DATA rd 1 +ends \ No newline at end of file diff --git a/readme.md b/readme.md index bfdc664..022eaba 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ -# simple_http +# simple_httpd Это небольшой http-сервер для Колибри ОС позволяющий хостить статичные сайты и создавать модули, для динамической генерации отправляемых клиенту данных. Сервер отправляет содержимое файлов без сжатия в соответствии с заданной таблицей ассоциации MIME типа и расширения файла. @@ -15,28 +15,37 @@ - conn - максимальное количество открытых соединений(по умолчанию 10) - work_dir - директория для размещения файлов, отправляемых сервером - mime_file - путь к файлу с таблицей сопоставлениея mime типов и расширений файлов (если не указан, то используется встроенная в сервер таблица сопоставления) - - unit_dir - директория расположения модулей сервера + - modules_dir - директория расположения модулей сервера - В секции UNITS может находиться множество параметров, имеющих вид uri_path=file_name где: + В секции MODULES может находиться множество параметров, имеющих вид uri_path=file_name;cmdline где: - uri_path - путь указываемый клиентом во время запроса - - file_name - название/путь до файла модуля относительно work_dir + - file_name - название/путь до файла модуля относительно modules_dir + - cmdline - строка параметров, которая передаётся в функцию инициализации модуля. Данное значение не обязательна и может не использоваться. -## API for units +## API for modules К серверу можно подключить дополнительные модули в виде библиотек со специальными экспортируемыми функциями: - - uint32_t stdcall httpd_init(IMPORT_DATA* import) + - uint32_t stdcall httpd_init(IMPORT_DATA* import, char* cmdline) -Эта функция необходима для передачи модулю необходимых данных, таких как функции работы с сетью, рабочие директории и тд. -Если инициализация модуля прошла успешно, функция возвращает 0. - - - void stdcall httpd_server(CONNECT_DATA* request_data) -Эта функция вызывается при получении запроса с uri путём указанном в файле конфигурации для этого модуля. Сервер передаёт в функцию структуру соединения, в которой находятся данные запроса(заголовки, параметры, http метод и версия). На основе этих данных функция может генерировать необходимый ответ. +Эта функция служит для инициализации модуля для каждого связанного с модулем uri . В файле конфигурации для конкретного uri можно добавить командную строку, передаваемую в эту функцию. Например + ``` test3=test_unit4.obj; -database="file.sqlite" ``` +При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль. +Для упрощения многих операций, сервер передаёт в функцию инициализации модуля таблицу некоторых функций, необходимых для работы с сетью, с файловой системой и прочими интерфейсами. + + - void stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata) +Эта функция вызывается сервером при получении запроса с uri путём указанном в файле конфигурации для этого модуля. +Сервер передаёт в функцию контекст запроса, содержащий: аргументы, заголовки, тело запроса, http метод и версию; и значение возвращённое функцией httpd_init. + + - void stdcall httpd_close(uint32_t pdata) +Эта функция вызывается сервером при завершении работы или в процессе управления сервером. Данная функция предназначена для корректного завершения работы модуля и освобождением связанных с ним ресурсов. ## Bugs - - В ходе тестов был обнаружена ошибка отправки "больших" файлов. Это баг сетевого стека. + - Сервер не поддерживает работу с файлами, имеющими не ascii символы, так как не производит преобразование uri пути; + - Сервер не имеет интерфейса для управления, что может вызвать трудности в сохранении временных данных модулей при завершении работы; + - В ходе тестов был обнаружена ошибка отправки "больших" файлов. Это баг сетевого стека; - При длительной работе сервер может начать "подзависать" или перестать отвечать на сообщения. Это баг сетевого стека. diff --git a/settings.inc b/settings.inc index 745f742..626d6b7 100644 --- a/settings.inc +++ b/settings.inc @@ -1,30 +1,14 @@ -struct CONNECT_DATA ; 16*4 = 64 bytes - socket dd 0 ; номер сокета подключения - sockaddr dd 16/4 ; socaddr connection - buffer_request dd 0 ; pointer to buffer for geting message socket - request_size dd 0 ; size geted data from client - end_buffer_request dd 0 ; для парсера - buffer_response dd 0 ; pointer to buffwr for resp message - http_method dd 0 ; указатель на строку - http_verion dd 0 ; указатель на строку - num_headers dd 0 ; number items in REQUEST_DATA - http_headers dd 0 ; указатель на массив REQUEST_DATA - uri_scheme dd 0 ; указатель на схему - uri_authority dd 0 ; pointer to struct ? - uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров) - num_uri_args dd 0 ; - uri_arg dd 0 ; pointer to array REQUEST_DATA аргументов uri строк - uri_fragment dd 0 ; указатель на строку - message_body dd 0 ; указатель на тело http запроса -ends -struct HTTPD_UNIT + +struct HTTPD_MODULE next rd 1 prev rd 1 + httpd_close rd 1 httpd_serv rd 1 - uri_path rb 4096-3*4 + pdata rd 1 + uri_path rb 4096-5*4 ends struct RESPD @@ -112,89 +96,101 @@ load_settings: call load_mime_file ; units_dir - invoke ini.get_str, ebp, ini_section_main, ini_key_units_dir, GLOBAL_DATA.unit_dir, 1024, 0 + invoke ini.get_str, ebp, ini_section_main, ini_key_modules_dir, GLOBAL_DATA.modules_dir, 1024, 0 test eax, eax - jnz .no_units + jnz .no_modules push edi mov ecx, 1024 - mov edi, GLOBAL_DATA.unit_dir + mov edi, GLOBAL_DATA.modules_dir xor eax, eax repne scasb mov byte[edi-1], '/' - mov [GLOBAL_DATA.unit_dir.end], edi + mov [GLOBAL_DATA.modules_dir.end], edi pop edi ; get all units - invoke ini.enum_keys, ebp, ini_section_units, .add_unit -.no_units: + invoke ini.enum_keys, ebp, ini_section_units, .add_module +.no_modules: xor eax, eax ret -.add_unit: ; [esp + 4*3] - name [esp + 4*4] - value +.add_module: ; [esp + 4*3] - name [esp + 4*4] - value ; add new item in list - push dword sizeof.HTTPD_UNIT + push dword sizeof.HTTPD_MODULE call Alloc test eax, eax - jz .add_unit.exit + jz .add_module.exit - mov ecx, [GLOBAL_DATA.units] - mov [eax + HTTPD_UNIT.next], ecx - mov dword[eax + HTTPD_UNIT.prev], GLOBAL_DATA.units - mov [GLOBAL_DATA.units], eax + mov ecx, [GLOBAL_DATA.modules] + mov [eax + HTTPD_MODULE.next], ecx + mov dword[eax + HTTPD_MODULE.prev], GLOBAL_DATA.modules + mov [GLOBAL_DATA.modules], eax test ecx, ecx jnz @f - mov [ecx + HTTPD_UNIT.prev], eax + mov [ecx + HTTPD_MODULE.prev], eax @@: ; copy uri path push esi edi mov esi, [esp + 4*2 + 4*3] ; name - lea edi, [eax + HTTPD_UNIT.uri_path + 1] + lea edi, [eax + HTTPD_MODULE.uri_path + 1] mov byte[edi - 1], '/' @@: movsb cmp byte[edi - 1], 0 jne @b ; copy file name - mov edi, [GLOBAL_DATA.unit_dir.end] + mov [GLOBAL_DATA._module_cmd], 0 + mov edi, [GLOBAL_DATA.modules_dir.end] mov esi, [esp + 4*2 + 4*4] @@: movsb cmp byte[edi - 1], 0 - jne @b + je @f + cmp byte[esi - 1], ';' + jne @b + mov byte[edi - 1], 0 + mov [GLOBAL_DATA._module_cmd], esi +@@: pop edi esi mov esi, eax ; load library push esi - stdcall dll.Load, IMPORT_UNIT + stdcall dll.Load, IMPORT_MODULE pop esi test eax, eax jz @f - .add_unit.err: + .add_module.err: ; error - mov eax, [esi + HTTPD_UNIT.next] ; next - mov [GLOBAL_DATA.units], eax - mov dword[eax + HTTPD_UNIT.prev], GLOBAL_DATA.units + mov eax, [esi + HTTPD_MODULE.next] ; next + mov [GLOBAL_DATA.modules], eax + mov dword[eax + HTTPD_MODULE.prev], GLOBAL_DATA.modules push esi call Free - jmp .add_unit.exit + jmp .add_module.exit @@: ; good - ; init httpd unit + ; init httpd module + push dword[GLOBAL_DATA._module_cmd] push dword EXPORT_DATA invoke httpd_import.init + test eax, eax - jnz .add_unit.err + jz .add_module.err + mov [esi + HTTPD_MODULE.pdata], eax mov eax, [httpd_import.serv] - mov dword[esi + HTTPD_UNIT.httpd_serv], eax + mov dword[esi + HTTPD_MODULE.httpd_serv], eax + mov eax, [httpd_import.close] + mov dword[esi + HTTPD_MODULE.httpd_close], eax - mov [httpd_import.init], httpd_unit_init - mov [httpd_import.serv], httpd_unit_serv -.add_unit.exit: + mov [httpd_import.init], httpd_module_init + mov [httpd_import.serv], httpd_module_serv + mov [httpd_import.close], httpd_module_close +.add_module.exit: ret 16 diff --git a/sys_func.inc b/sys_func.inc index d4da36c..34a51e0 100644 --- a/sys_func.inc +++ b/sys_func.inc @@ -218,13 +218,6 @@ FileRead: -FLAG_KEEP_ALIVE = 0x01 -FLAG_ADD_DATE = 0x02 ;(not supported) -FLAG_NO_SET_CACHE = 0x04 ;(not supported) -FLAG_NO_CONTENT_ENCODING = 0x08 ;(not supported) - - - ;RESPD* stdcall create_resp(CONNECT_DATA* session, uint32_t flags) create_resp: @@ -244,7 +237,7 @@ create_resp: .exit: ret 8 -;void destruct_resp(RESPD* ptr) +;void stdcall destruct_resp(RESPD* ptr) destruct_resp: stdcall Free, [esp + 4] ret 4 @@ -452,3 +445,71 @@ send_resp: mov eax, -1 jmp .exit + + +;char* find_uri_arg(CONNECT_DATA* session, char* key) +find_uri_arg: + push esi edi + mov edx, [esp + 4*2 + 4] + mov ecx, [edx + CONNECT_DATA.num_uri_args] + mov esi, [esp + 4*2 + 8] + mov edx, [edx + CONNECT_DATA.uri_arg] + test ecx, ecx + jz .not_found +.loop: + mov edi, [edx] + push esi +@@: + cmpsb + jne @f + cmp byte[esi - 1], 0 + jne @b + + pop esi + mov eax, [edx + 4] + jmp .exit +@@: + pop esi + add edx, 4*2 ; size array item + loop .loop +.not_found: + xor eax, eax +.exit: + pop edi esi + ret 8 + +;char* find_header(CONNECT_DATA* session, char* key) +find_header: + push esi edi + mov edx, [esp + 4*2 + 4] + mov ecx, [edx + CONNECT_DATA.num_headers] + mov esi, [esp + 4*2 + 8] + mov edx, [edx + CONNECT_DATA.http_headers] + test ecx, ecx + jz .not_found +.loop: + mov edi, [edx] + push esi +@@: + cmpsb + jne @f + cmp byte[esi - 1], 0 + jne @b + + pop esi + mov eax, [edx + 4] + jmp .exit +@@: + pop esi + add edx, 4*2 ; size array item + loop .loop +.not_found: + xor eax, eax +.exit: + pop edi esi + ret 8 + +;void close_server() +close_server: + + ret \ No newline at end of file