Update to 0.2.0 version

## Program interface
- Added the function ``` char* find_uri_args(CONNECT_DATA* session, char* key) ```
- Added the function ``` char* find_header(CONNECT_DATA* session, char* key) ```
- Fixed a bug in ``` Get_MIME_Type ```
- Added the function ``` void close_server(); ```

## Module interface
- The initialization function and the request processing function have been changed:

``` uint32_t stdcall httpd_init(IMPORT_DATA* import, char* cmdline) ```

```` void stdcall httpd_server(CONNECT_DATA* request_data, uint32_t pdata) ```

Added a module shutdown function for a specific uri:

``` void stdcall httpd_close(uint32_t pdata) ```

## Modules
- Added a module for testing parameter transmission during initialization

## Other
- Added a build script
- Added a single file for the program and modules with constants and structures
This commit is contained in:
2024-02-11 21:45:47 +05:00
parent 31f574270c
commit cde50c18ed
20 changed files with 436 additions and 270 deletions

BIN
bin/httpd Normal file

Binary file not shown.

View File

@@ -13,17 +13,15 @@ conn=100
; directory for find files ; directory for find files
work_dir=/usbhd0/3/server_data work_dir=/usbhd0/3/server_data
; directory for find units(library) ; directory for find units(library)
units_dir=/usbhd0/3 modules_dir=/usbhd0/3
mime_file=/usbhd0/3/mime_types.bin mime_file=/usbhd0/3/mime_types.bin
[UNITS] [MODULES]
; list units ; list units
; path = path to lib in units_dir ; path = unit_name;cmdline
; not uning ' ' in unit_name;cmdline : "path = unit_name ; cmdline" is bad name
test=test_unit.obj test=test_unit.obj
rasp=test_unit_2.obj rasp=test_unit_2.obj
;database/sqlite3=sqlite3_serv.obj ;database/sqlite3=sqlite3_serv.obj
;database/cvs=cvs_table_server.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);

BIN
bin/modules/test_unit.obj Normal file

Binary file not shown.

BIN
bin/modules/test_unit4.obj Normal file

Binary file not shown.

BIN
bin/modules/test_unit_2.obj Normal file

Binary file not shown.

View File

@@ -1,70 +1,11 @@
format MS COFF format MS COFF
public @EXPORT as 'EXPORTS' public @EXPORT as 'EXPORTS'
API_VERSION = 0x05 include "macros.inc"
FLAG_KEEP_ALIVE = 0x01
include '../module_api.inc'
NO_DEBUG_INPUT = 0 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 { macro board_input message {
if NO_DEBUG_INPUT = 0 if NO_DEBUG_INPUT = 0
@@ -89,7 +30,7 @@ end if
section '.flat' code readable align 16 section '.flat' code readable align 16
unit_init: unit_init:
mov eax, -1 xor eax, eax
push esi edi push esi edi
mov esi, [esp + 4*2 + 4] mov esi, [esp + 4*2 + 4]
mov [import_httpd], esi mov [import_httpd], esi
@@ -102,10 +43,10 @@ unit_init:
shr ecx, 2 ; div 4 shr ecx, 2 ; div 4
rep movsd rep movsd
xor eax, eax mov eax, 1 ;no zero return - unit init successful
.exit: .exit:
pop edi esi pop edi esi
ret 4 ret 8
server_entry: server_entry:
@@ -165,7 +106,7 @@ server_entry:
board_input 'create message' board_input 'create message'
; create http message ; create http message
push dword 8*1024 push dword 8*1024
call [IMPORT + IMPORT_DATA.Alloc] call [IMPORT.Alloc]
test eax, eax test eax, eax
jz .exit jz .exit
@@ -214,13 +155,18 @@ server_entry:
push sceleton_resp.size push sceleton_resp.size
push edi push edi
push dword[esi + CONNECT_DATA.socket] push dword[esi + CONNECT_DATA.socket]
call [IMPORT + IMPORT_DATA.netfunc_send] call [IMPORT.netfunc_send]
board_input 'send' board_input 'send'
.exit: .exit:
pop edi esi pop edi esi
ret 8
server_close:
ret 4 ret 4
section '.data' data readable writable align 16 section '.data' data readable writable align 16
_10: dd 10 _10: dd 10
@@ -263,7 +209,8 @@ text_message:
@EXPORT: @EXPORT:
export \ export \
unit_init, 'httpd_init', \ unit_init, 'httpd_init', \
server_entry, 'httpd_serv' server_entry, 'httpd_serv',\
server_close, 'httpd_close'
IMPORT IMPORT_DATA ; IMPORT IMPORT_DATA ;

Binary file not shown.

100
example/test_unit4.asm Normal file
View File

@@ -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

View File

@@ -1,72 +1,12 @@
format MS COFF format MS COFF
public @EXPORT as 'EXPORTS' public @EXPORT as 'EXPORTS'
API_VERSION = 0x05
FLAG_KEEP_ALIVE = 0x01
NO_DEBUG_INPUT = 0 NO_DEBUG_INPUT = 0
include 'D:\kos\programs\macros.inc' include "macros.inc"
purge mov,add,sub purge mov,add,sub
include 'D:\kos\programs\proc32.inc' include "proc32.inc"
struct IMPORT_DATA include '../module_api.inc'
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 { macro board_input message {
if NO_DEBUG_INPUT = 0 if NO_DEBUG_INPUT = 0
@@ -91,7 +31,7 @@ end if
section '.flat' code readable align 16 section '.flat' code readable align 16
unit_init: unit_init:
mov eax, -1 xor eax, eax
push esi edi push esi edi
mov esi, [esp + 4*2 + 4] mov esi, [esp + 4*2 + 4]
@@ -103,10 +43,10 @@ unit_init:
shr ecx, 2 ; div 4 shr ecx, 2 ; div 4
rep movsd rep movsd
xor eax, eax mov eax, 1 ;no zero return - unit init successful
.exit: .exit:
pop edi esi pop edi esi
ret 4 ret 8
server_entry: server_entry:
@@ -193,7 +133,7 @@ server_entry:
invoke IMPORT.destruct_resp ; arg in stack invoke IMPORT.destruct_resp ; arg in stack
.exit: .exit:
pop edi esi pop edi esi
ret 4 ret 8
.send_data: ; eax - ptr to buffer .send_data: ; eax - ptr to buffer
mov edi, eax mov edi, eax
@@ -223,7 +163,9 @@ server_entry:
invoke IMPORT.destruct_resp, edi invoke IMPORT.destruct_resp, edi
jmp .exit jmp .exit
server_close:
ret 4
section '.data' data readable writable align 16 section '.data' data readable writable align 16
@@ -258,7 +200,8 @@ btp_name:
@EXPORT: @EXPORT:
export \ export \
unit_init, 'httpd_init', \ unit_init, 'httpd_init', \
server_entry, 'httpd_serv' server_entry, 'httpd_serv',\
server_close, 'httpd_close'
IMPORT IMPORT_DATA ; IMPORT IMPORT_DATA ;

Binary file not shown.

View File

@@ -258,7 +258,10 @@ file_server:
Get_MIME_Type: Get_MIME_Type:
push esi edi push esi edi
mov eax, [esp + 4*2 + 4] mov eax, [esp + 4*2 + 4]
mov edx, [eax + FILED.path]
mov eax, [eax + FILED.end_path] mov eax, [eax + FILED.end_path]
push eax
sub [esp], edx
mov edx, [GLOBAL_DATA.MIME_types_arr] mov edx, [GLOBAL_DATA.MIME_types_arr]
@@: @@:
mov esi, [edx] mov esi, [edx]
@@ -268,12 +271,16 @@ Get_MIME_Type:
mov edi, eax mov edi, eax
movzx ecx, byte [esi] movzx ecx, byte [esi]
cmp ecx, [esp]
jae @b
inc esi inc esi
sub edi, ecx sub edi, ecx
repe cmpsb repe cmpsb
jne @b jne @b
@@: @@:
mov eax, esi mov eax, esi
pop edi ;clear value in stack
pop edi esi pop edi esi
ret 4 ret 4
.other: .other:

View File

@@ -8,16 +8,18 @@
; ; ; ;
;*****************************************************************************; ;*****************************************************************************;
API_VERSION = 0x05 ; 0.0.5
;include "macros.inc" ;include "macros.inc"
use32 use32
org 0 org 0
db 'MENUET01' db 'MENUET01'
dd 1, START, I_END, MEM, STACKTOP, PATH, 0 dd 1, START, I_END, MEM, STACKTOP, PATH, 0
include 'D:\kos\programs\macros.inc' include "macros.inc"
purge mov,add,sub 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' ;include 'D:\kos\programs\network.inc'
;KOS_APP_START ;KOS_APP_START
@@ -153,36 +155,37 @@ thread_connect:
test eax, eax test eax, eax
jz .err_parse jz .err_parse
; find unit for uri path ; find unit for uri path
cmp dword[GLOBAL_DATA.units], 0 cmp dword[GLOBAL_DATA.modules], 0
jz .no_units jz .no_modules
mov eax, [GLOBAL_DATA.units] mov eax, [GLOBAL_DATA.modules]
.next_unit: .next_unit:
push esi edi push esi edi
mov esi, [esi + CONNECT_DATA.uri_path] mov esi, [esi + CONNECT_DATA.uri_path]
lea edi, [eax + HTTPD_UNIT.uri_path] lea edi, [eax + HTTPD_MODULE.uri_path]
@@: @@:
cmpsb cmpsb
jne @f jne @f
cmp byte[edi - 1], 0 cmp byte[edi - 1], 0
jne @b jne @b
; found unit ; found module
pop edi esi pop edi esi
push esi push dword[eax + HTTPD_MODULE.pdata] ; context of module
call dword[eax + HTTPD_UNIT.httpd_serv] ; call unit function push esi ; coutext of request
call dword[eax + HTTPD_MODULE.httpd_serv] ; call unit function
jmp .end_work jmp .end_work
@@: @@:
pop edi esi pop edi esi
mov eax, [eax] ; HTTPD_UNIT.next mov eax, [eax] ; HTTPD_MODULE.next
test eax, eax ; terminate list test eax, eax ; terminate list
jne .next_unit jne .next_unit
.no_units: .no_modules:
; if not found units, call file_server ; if not found modules, call file_server
call file_server ; esi - struct call file_server ; esi - struct
; end work thread ; end work thread
jmp .end_work jmp .end_work
@@ -232,29 +235,31 @@ import libini,\
default_ini_path: db 'httpd.ini',0 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_section_main: db 'MAIN', 0
ini_key_ip db 'ip',0 ini_key_ip db 'ip',0
ini_key_port db 'port',0 ini_key_port db 'port',0
ini_key_conn db 'conn',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_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 ini_key_mime_file db 'mime_file',0
httpd_unit_init db 'httpd_init',0 httpd_module_init db 'httpd_init',0
httpd_unit_serv db 'httpd_serv',0 httpd_module_serv db 'httpd_serv',0
httpd_module_close db 'httpd_close',0
IMPORT_UNIT: IMPORT_MODULE:
dd httpd_import, GLOBAL_DATA.unit_dir, 0 dd httpd_import, GLOBAL_DATA.modules_dir, 0
httpd_import: httpd_import:
.init dd httpd_unit_init .init dd httpd_module_init
.serv dd httpd_unit_serv .serv dd httpd_module_serv
.close dd httpd_module_close
dd 0 dd 0
EXPORT_DATA: EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA
dd API_VERSION dd API_VERSION
dd .size dd .size
dd netfunc_socket dd netfunc_socket
@@ -277,6 +282,9 @@ EXPORT_DATA:
dd add_http_header dd add_http_header
dd del_http_header dd del_http_header
dd set_http_ver dd set_http_ver
dd find_uri_arg
dd find_header
dd close_server
dd base_response dd base_response
dd GLOBAL_DATA dd GLOBAL_DATA
@@ -298,15 +306,16 @@ srv_sockaddr:
.length = $ - srv_sockaddr .length = $ - srv_sockaddr
GLOBAL_DATA: 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 ; next, prev, ptr of httpd_serv(), uri path
.work_dir rb 1024 ; max size path to work directory .work_dir rb 1024 ; max size path to work directory
.work_dir.size rd 1 ; length string .work_dir.size rd 1 ; length string
.unit_dir rb 1024 .modules_dir rb 1024
.unit_dir.end rd 1 .modules_dir.end rd 1
.MIME_types_arr rd 1 .MIME_types_arr rd 1
; .flags rd 1 .flags rd 1
._module_cmd rd 1
PATH: PATH:
rb 256 rb 256

View File

@@ -15,9 +15,9 @@ work_dir=/sys/http_server/data
; directory for find lib ; directory for find lib
units_dir=/sys/http_units units_dir=/sys/http_units
;mime_file=/sys/network/mime.bin mime_file=/sys/network/mime.bin
;[UNITS] [UNITS]
; list units ; list units
; path = path to lib in units_dir ; path = path to lib in units_dir
;database/sqlite3=sqlite3_serv.obj ;database/sqlite3=sqlite3_serv.obj

View File

@@ -51,7 +51,6 @@
;serv_header: ;serv_header:
; .Accept_Ranges db 'Accept-Ranges: bytes',13,10 ; .Accept_Ranges db 'Accept-Ranges: bytes',13,10
; .connection db 'Connection: close',0
;http_method: ;http_method:
; .get: db 'GET ' ; .get: db 'GET '

19
makefile Normal file
View File

@@ -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

78
module_api.inc Normal file
View File

@@ -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

View File

@@ -1,5 +1,5 @@
# simple_http # simple_httpd
Это небольшой http-сервер для Колибри ОС позволяющий хостить статичные сайты и создавать модули, для динамической генерации отправляемых клиенту данных. Это небольшой http-сервер для Колибри ОС позволяющий хостить статичные сайты и создавать модули, для динамической генерации отправляемых клиенту данных.
Сервер отправляет содержимое файлов без сжатия в соответствии с заданной таблицей ассоциации MIME типа и расширения файла. Сервер отправляет содержимое файлов без сжатия в соответствии с заданной таблицей ассоциации MIME типа и расширения файла.
@@ -15,28 +15,37 @@
- <CODE>conn</CODE> - максимальное количество открытых соединений(по умолчанию 10) - <CODE>conn</CODE> - максимальное количество открытых соединений(по умолчанию 10)
- <CODE>work_dir</CODE> - директория для размещения файлов, отправляемых сервером - <CODE>work_dir</CODE> - директория для размещения файлов, отправляемых сервером
- <CODE>mime_file</CODE> - путь к файлу с таблицей сопоставлениея mime типов и расширений файлов (если не указан, то используется встроенная в сервер таблица сопоставления) - <CODE>mime_file</CODE> - путь к файлу с таблицей сопоставлениея mime типов и расширений файлов (если не указан, то используется встроенная в сервер таблица сопоставления)
- <CODE>unit_dir</CODE> - директория расположения модулей сервера - <CODE>modules_dir</CODE> - директория расположения модулей сервера
В секции <CODE>UNITS</CODE> может находиться множество параметров, имеющих вид <CODE>uri_path=file_name</CODE> где: В секции <CODE>MODULES</CODE> может находиться множество параметров, имеющих вид <CODE>uri_path=file_name;cmdline</CODE> где:
- <CODE>uri_path</CODE> - путь указываемый клиентом во время запроса - <CODE>uri_path</CODE> - путь указываемый клиентом во время запроса
- <CODE>file_name</CODE> - название/путь до файла модуля относительно <CODE>work_dir</CODE> - <CODE>file_name</CODE> - название/путь до файла модуля относительно <CODE>modules_dir</CODE>
- <CODE>cmdline</CODE> - строка параметров, которая передаётся в функцию инициализации модуля. Данное значение не обязательна и может не использоваться.
## API for units ## API for modules
К серверу можно подключить дополнительные модули в виде библиотек со специальными экспортируемыми функциями: К серверу можно подключить дополнительные модули в виде библиотек со специальными экспортируемыми функциями:
- <CODE>uint32_t stdcall httpd_init(IMPORT_DATA* import)</CODE> - <CODE> uint32_t stdcall httpd_init(IMPORT_DATA* import, char* cmdline) </CODE>
Эта функция необходима для передачи модулю необходимых данных, таких как функции работы с сетью, рабочие директории и тд. Эта функция служит для инициализации модуля для каждого связанного с модулем uri . В файле конфигурации для конкретного uri можно добавить командную строку, передаваемую в эту функцию. Например
Если инициализация модуля прошла успешно, функция возвращает 0.
- <CODE>void stdcall httpd_server(CONNECT_DATA* request_data)</CODE> ``` test3=test_unit4.obj; -database="file.sqlite" ```
Эта функция вызывается при получении запроса с uri путём указанном в файле конфигурации для этого модуля. Сервер передаёт в функцию структуру соединения, в которой находятся данные запроса(заголовки, параметры, http метод и версия). На основе этих данных функция может генерировать необходимый ответ.
При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.
Для упрощения многих операций, сервер передаёт в функцию инициализации модуля таблицу некоторых функций, необходимых для работы с сетью, с файловой системой и прочими интерфейсами.
- <CODE> void stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata) </CODE>
Эта функция вызывается сервером при получении запроса с uri путём указанном в файле конфигурации для этого модуля.
Сервер передаёт в функцию контекст запроса, содержащий: аргументы, заголовки, тело запроса, http метод и версию; и значение возвращённое функцией httpd_init.
- <CODE>void stdcall httpd_close(uint32_t pdata) </CODE>
Эта функция вызывается сервером при завершении работы или в процессе управления сервером. Данная функция предназначена для корректного завершения работы модуля и освобождением связанных с ним ресурсов.
## Bugs ## Bugs
- В ходе тестов был обнаружена ошибка отправки "больших" файлов. Это баг сетевого стека. - Сервер не поддерживает работу с файлами, имеющими не ascii символы, так как не производит преобразование uri пути;
- Сервер не имеет интерфейса для управления, что может вызвать трудности в сохранении временных данных модулей при завершении работы;
- В ходе тестов был обнаружена ошибка отправки "больших" файлов. Это баг сетевого стека;
- При длительной работе сервер может начать "подзависать" или перестать отвечать на сообщения. Это баг сетевого стека. - При длительной работе сервер может начать "подзависать" или перестать отвечать на сообщения. Это баг сетевого стека.

View File

@@ -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 next rd 1
prev rd 1 prev rd 1
httpd_close rd 1
httpd_serv rd 1 httpd_serv rd 1
uri_path rb 4096-3*4 pdata rd 1
uri_path rb 4096-5*4
ends ends
struct RESPD struct RESPD
@@ -112,89 +96,101 @@ load_settings:
call load_mime_file call load_mime_file
; units_dir ; 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 test eax, eax
jnz .no_units jnz .no_modules
push edi push edi
mov ecx, 1024 mov ecx, 1024
mov edi, GLOBAL_DATA.unit_dir mov edi, GLOBAL_DATA.modules_dir
xor eax, eax xor eax, eax
repne scasb repne scasb
mov byte[edi-1], '/' mov byte[edi-1], '/'
mov [GLOBAL_DATA.unit_dir.end], edi mov [GLOBAL_DATA.modules_dir.end], edi
pop edi pop edi
; get all units ; get all units
invoke ini.enum_keys, ebp, ini_section_units, .add_unit invoke ini.enum_keys, ebp, ini_section_units, .add_module
.no_units: .no_modules:
xor eax, eax xor eax, eax
ret 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 ; add new item in list
push dword sizeof.HTTPD_UNIT push dword sizeof.HTTPD_MODULE
call Alloc call Alloc
test eax, eax test eax, eax
jz .add_unit.exit jz .add_module.exit
mov ecx, [GLOBAL_DATA.units] mov ecx, [GLOBAL_DATA.modules]
mov [eax + HTTPD_UNIT.next], ecx mov [eax + HTTPD_MODULE.next], ecx
mov dword[eax + HTTPD_UNIT.prev], GLOBAL_DATA.units mov dword[eax + HTTPD_MODULE.prev], GLOBAL_DATA.modules
mov [GLOBAL_DATA.units], eax mov [GLOBAL_DATA.modules], eax
test ecx, ecx test ecx, ecx
jnz @f jnz @f
mov [ecx + HTTPD_UNIT.prev], eax mov [ecx + HTTPD_MODULE.prev], eax
@@: @@:
; copy uri path ; copy uri path
push esi edi push esi edi
mov esi, [esp + 4*2 + 4*3] ; name 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], '/' mov byte[edi - 1], '/'
@@: @@:
movsb movsb
cmp byte[edi - 1], 0 cmp byte[edi - 1], 0
jne @b jne @b
; copy file name ; 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] mov esi, [esp + 4*2 + 4*4]
@@: @@:
movsb movsb
cmp byte[edi - 1], 0 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 pop edi esi
mov esi, eax mov esi, eax
; load library ; load library
push esi push esi
stdcall dll.Load, IMPORT_UNIT stdcall dll.Load, IMPORT_MODULE
pop esi pop esi
test eax, eax test eax, eax
jz @f jz @f
.add_unit.err: .add_module.err:
; error ; error
mov eax, [esi + HTTPD_UNIT.next] ; next mov eax, [esi + HTTPD_MODULE.next] ; next
mov [GLOBAL_DATA.units], eax mov [GLOBAL_DATA.modules], eax
mov dword[eax + HTTPD_UNIT.prev], GLOBAL_DATA.units mov dword[eax + HTTPD_MODULE.prev], GLOBAL_DATA.modules
push esi push esi
call Free call Free
jmp .add_unit.exit jmp .add_module.exit
@@: ; good @@: ; good
; init httpd unit ; init httpd module
push dword[GLOBAL_DATA._module_cmd]
push dword EXPORT_DATA push dword EXPORT_DATA
invoke httpd_import.init invoke httpd_import.init
test eax, eax test eax, eax
jnz .add_unit.err jz .add_module.err
mov [esi + HTTPD_MODULE.pdata], eax
mov eax, [httpd_import.serv] 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.init], httpd_module_init
mov [httpd_import.serv], httpd_unit_serv mov [httpd_import.serv], httpd_module_serv
.add_unit.exit: mov [httpd_import.close], httpd_module_close
.add_module.exit:
ret 16 ret 16

View File

@@ -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) ;RESPD* stdcall create_resp(CONNECT_DATA* session, uint32_t flags)
create_resp: create_resp:
@@ -244,7 +237,7 @@ create_resp:
.exit: .exit:
ret 8 ret 8
;void destruct_resp(RESPD* ptr) ;void stdcall destruct_resp(RESPD* ptr)
destruct_resp: destruct_resp:
stdcall Free, [esp + 4] stdcall Free, [esp + 4]
ret 4 ret 4
@@ -452,3 +445,71 @@ send_resp:
mov eax, -1 mov eax, -1
jmp .exit 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