From 481c66f38cbeda6597cf6cfbd5645ff530bc1cc2 Mon Sep 17 00:00:00 2001
From: Doczom
Date: Sun, 31 Mar 2024 20:25:00 +0500
Subject: [PATCH] Update to 0.2.3
Update fileserver:
fileserver esing RESPD functions;
Update file functions: added 3 and edit 2 functions;
Added documentation
Fixed first test module.
Added new MIME types
---
bin/httpd | Bin 5693 -> 5656 bytes
bin/httpd.ini | 4 +-
bin/mime_types.bin | Bin 384 -> 1042 bytes
bin/modules/srv_control.obj | Bin 1032 -> 1044 bytes
bin/modules/test_unit.obj | Bin 1767 -> 1806 bytes
bin/modules/test_unit4.obj | Bin 700 -> 712 bytes
bin/modules/test_unit5.obj | Bin 702 -> 714 bytes
bin/modules/test_unit_2.obj | Bin 1830 -> 1842 bytes
bin/server_data/docs/index.htm | 272 +++++++++++++++++++++++++++++++++
doc/index.htm | 272 +++++++++++++++++++++++++++++++++
example/test_unit.asm | 24 ++-
file_server.inc | 179 ++++++----------------
httpd.asm | 29 +++-
httpd_lib.inc | 49 +-----
makefile | 4 +-
module_api.inc | 46 ++++--
settings.inc | 38 +++--
sys_func.inc | 131 +++++++++++++---
utils/mime_types.asm | 69 ++++++---
19 files changed, 850 insertions(+), 267 deletions(-)
create mode 100644 bin/server_data/docs/index.htm
create mode 100644 doc/index.htm
diff --git a/bin/httpd b/bin/httpd
index cb5d05354800afac97f286de8f68cc7948c49bad..5e42bd5a83202746e1ac2a4f64c4352a0bc7f741 100644
GIT binary patch
delta 2448
zcmZuzeQZ-z6u&F4quaW*uy$;?jj4|WWNxhr2Hi|aIv5FT9qU>Y-IR~zG5iX=ii^{B
zJ|Ca&9Lmk
z#&}frj)i3(<11u8|8a0BXrG0&(TX*PT&yLo_sH&{3ebY-@i+9a?1m{XZ}cx;l3L6X
z7kOh@$L$aVM*_zMC+=30>@ps4^F}WpfyE@5>`SZDwaHx75&VXqSVIxzERnPpi5+sY
zmMMMSNM@kux*cQ^qOi$tHgvL#(5392NdfHtPb2HIDdW^m%FPtn!I(Jsw`GAnANK9Y
z;hB5Qkn4s(pvnxnXU>41kT;Lqg{sIKvb0oL5-(f>4Lbz#bof991OY9=?%?{c3QZE>p9halEPUc$^l@W*Zq=-2QjSb1qgpJnVEC#T#&B-??C?d)
zidYGs_zKACyE@u&Pjozd(O5LSZqDgHDO2YmiJ8vQ5=M@hR$m8|J=p8yfG!u&rn|cv|0W^#M_tl^!X84@MthSMBU(!?4P7p;MsN9#Fhl}iUw
zNsFo8)MM7IiE+4Ld?5*SwDYl;(u2svdlxLL9gnL-&+R8uS&K2z2zS3NwQPB1H$*M}
zllX<`mwc&r@6*8fQup4S_U)B?!d`(5^sZz5%)pBAuq#q4q8~*Y`&bxWV0Rd
zM!1R2psJ3)xtfn<%NJ9E(EM*BC01#t=0#)Tpsk$<!8Nv|yH_`VZrUf*TyWE*OUkuF0eOXX<=B{R;)Pfj!e0>m6kn
zQd$qbIcgrJrBCdkSbFe1vd=D|<80j|i|+I9N8KVPsUgwM-fpQj=;_-ETyF~C>!W&>
z^mbddH8r(~v%lO8@{V0HJ7HO|IRAavem=+bLV7^s1Nwu30rV?N{E03-uAQk^6&KHq
zTh@+cCnBpvGcYQwg-9osohZfT={tvCy{WW!adX5IU7jd}`{t%r=GivJj3Y&*$?w2d
zLMVPrxH30qKO+8-^6{f6;DK|QR(uCykyw0~Mk+V6L)8owRbiQ-nVGGGwjB=_QO++y
zfsYNOZo}8Lqg|KeuBJ$vm<<=!)=Spb$u_Yc)zOoZY&(j?#Yx+hTBy6_NK2dOfaq^0
zMHJLF@hm#9O}vH#@kFq?)+i0d=z&Gzg|kyMWe*t28#8TklE`hM1lqQO@;ot1Gt9Nb
zjK%45T&PFmj1uI4&zMm2XkMAlXn0I0LK770ww_-^mQem
z22gJt@y(HGe7yyrwR7ja8`o~Ue`C!9YrELak3szcaMEYY^mkX@w|2vN_1-OP-8~)a
zHf&~FHb2y{ZnJ9dn>KVCPx-ICnq~>jKUy?3XkO5yuooJn$2j7jbLTKF?HJ%d5o1;8
yM*(~}_U(X|0mmh@4EF1>F9s-pU4T}=tX#%?=-zkn7wRX#7Z{=|akjf0ZvFu|JT!Cw
delta 2270
zcmZ`*eN0}8^$=}M|5ub%ycN|z`^qT-L~jv;!V!I=bn$>
zJ@?#m?|TPJJ}4>P;dD1R>uq)&AwiY=*iJq
zbdyz0qZ~;o|05NwdP3Ag8eK>$E_#KBV-=qP8>Py^EJuw*3tBl<)Mz<3p|j8h&Z0X{
ziwu>{Z?OCm`6DXlKK-loz3e0cbLh(SYBu%YB~6QtXGZ6>;9>b@Yu=I;SVc_#5Ys~$
zqkV=vt_d^xy5Y0jm2*xm3=lCbI)g7N*im@1)pq~+!(QNwWU<~D9oKCazn1=pj`JOgVFyHd
z(&Z6uy$sd_{_*jSfjTI=GKIGPs5%CmOo0=|azYz;VfSSwMsp|`l@Cz`hM3WZ%*Z}G
z^JZOSnz53jt&osb^+s4M;j}{{h*#h+7;!@ig6SE=gi9-v9PQV@UpR+z7Pi3$x!^I_
zhsOlMlhs5$_Lrt1Gd;(V5IKuwTrw(E9AgHWX=%bT1HClM`5S&{{AU4rwIFhac58
ziL+RSNEOVewMCln3vU2kjbG5Tme_DGUtTuApi+o_wI0iztJM<5qn6{su$TWw(pHD`A2=RF&1qaKrIQx2|G|{`w
zDY?z5qS-sQOkyC4_~s7)CBY6E)3(20b+N<+(wL+rg#yZ=lC8XE-8&=$lJc8Dym
zLBkLm)zgbfeGg>pK?n=%DhTW{sbfecyY+VtY)2})c!AZTR>3CfS1H|At%B8BN_r+G
zEsZ*=%OTbU*BwP3$$Ph>o2){%e~LOB3B|WU%W~jU%;8+7QttO%pmnBI*Iu^F^GU$$
zo=*WFaaQSUoP-JStJluaKGR11{tI;6v^IksH3_coZ>H0xGW~jvTC(yApJl!eTa6@`
zfp^TP#xU2)t?K=M9&u->x=;=_*%9gH%Iw)O19;hO3s;h0c6Fp%D=RH66Mz5tJd)A-
zjFp_yH0g`zbg>jLOTYO8@x&GRLe65BWOh*AV;e+G67er-ejAF>wX)ZBN^q@D6?aaVIsQ=LXpZkPyKc=3nA3GeI&cb14X3LQ|GG}mxa4IJcW@;m$M!&
zcR+*F(Gm6dY_jkgAn^x0@k>|ZTxWnQZ?+FeQIf9lRvv4&T_^pC
z4;^_aCrxkKR$uQavzOW}Hk*xlb63-sbJoyJIYo3h$3p9Jyp+r34Hnkui@EW2)46~F
zU4;y-1#JYmKrNuVK#zc)q@ldk>(~cl5i{2M`ucWv?&`d|v-F-_U8Ju7Dl5olrlWb?
z^cM5lHS7sv&n|21v0~3uKPb^~ynE~}0BQsEf!+u0
a1$~Dk=HjR1;dDZ3G1g#Yb(Xkgfc_h<5A*H-
diff --git a/bin/httpd.ini b/bin/httpd.ini
index c43bb95..4a81e84 100644
--- a/bin/httpd.ini
+++ b/bin/httpd.ini
@@ -13,7 +13,7 @@ conn=100
; directory for find files
work_dir=/usbhd0/3/server_data
; directory for find units(library)
-modules_dir=/usbhd0/3
+modules_dir=/usbhd0/3/modules
mime_file=/usbhd0/3/mime_types.bin
@@ -23,7 +23,5 @@ mime_file=/usbhd0/3/mime_types.bin
; not uning ' ' in unit_name;cmdline : "path = unit_name ; cmdline" is bad name
test=test_unit.obj
rasp=test_unit_2.obj
-test5=test_unit5.obj
-admin=srv_control.obj;123456
;database/sqlite3=sqlite3_serv.obj
;database/cvs=cvs_table_server.obj
\ No newline at end of file
diff --git a/bin/mime_types.bin b/bin/mime_types.bin
index 72ac9a6a44a288f8d99bd2c2bba8138269fa539f..48f604631e7d3e3a11874a5b84d8759c08b5f2fd 100644
GIT binary patch
literal 1042
zcmZ9LKa12r7>7r975o5#XlrvYNhZ13+ewDZY%XkZ;3wE`U?KJv
zHrfd`b~eIsjotNvSlIbYCVONpp3VFF&HHb%yPt#*-{2Ci;V(S6B}4+p@ER(316z0x
zpWzCA!M)o;9Kd5ZhF5R`6aktlt8>25A5dWNK`b1jtesQ4%nSbp{=xIC;otawu@^(2n3y_{~ss
qGa^Lf_+1l%&?G$Kl)+eX!DxhtilrTE{^MeNpE~o(C(buY8u1TxYCn4b
delta 143
zcmbQl(ZKBF!oa`~0>sHcTnNOiK)eKqcLMPRAifX8?}7Lq5c4uJFvtP1ArLzOaWD`k
zGfv!AKG}&;(xM~JCA3W7#K5z{}=TE8RL_|1(XN!KpKG*NayP#-99QTf&WESfSf}tn+q9p87DU|
L@oc`wq{RpTxGpu&
delta 183
zcmbQj(ZRv#!^p%?zxPe*xrv<0jQ1w$%5&y0GB6YY@uZ2N#*7*hJDnK=CZ1KT4*&|a
z9w^~SYqkh3W&1B00pw>fg#8z_fJlf2WF=>WF)%O${1-I=3jG(g0g~}?hd3BI&t-G~
zB@k*~b{@|#F)(Hb|1atQGR7x^3n&ldfiwaskj~dfx_wkw0{@HZ06B+PHWxDHGH!mw
Hq{RpT34}Dc
diff --git a/bin/modules/test_unit.obj b/bin/modules/test_unit.obj
index ba5b1898e280d4367ef62bf27a1b59376eaa1cb7..0fbb5518082b27992603b643b8718f88e095b3ea 100644
GIT binary patch
delta 734
zcmY+8-z!657{}jp+GeZGuNq}&%CB~@SQ3&XmQapg8-lnvaIP-coG4JHs
z5(j0jJ)}t9D#;wJ9+?QTwAiX@2!?3QmCn?vS3rEyclOx-0N22tRK(t(Wv!<M^nNd`IjMYof@EA)|Uxlc;X}
zsc=7Cf}L?_BjXlJJrHh3Hp7|5+GQQH&R7quN7f7LgY|1EjV4v-WwjeZv7Ru+nrE%D
z)>+%E1J)7if_2Y&XMIB>n0SI8U9HA_C{{MWS%9-)&c-+!j7sAZlOgi!&$jk|M@5-$YJj#vc=PwyxX
zfdA!x!UO(`E&=lYi>?8Z@o|SZ7_u0`{)M^mgo&KWjL#0W3
i;r~U!JmCy=1P>_q0Lc3i$>0W3
e;r~U!JmCy=1P>_q0Lc3M^mkBOYhj7ui!%5yd_F)*kwGcfF#7HmSSafQ
zlxRIrA`y@g&&a@#!NS165b$5r11S1mG+?p@lRcx)CA>hBL4N&yIsLNyxCVNJQ$r()cd{7afc=&%&lgV3|tbr0A
enM8#>fI?Y72owgX0a7lTC7J7)HZNiAV*~(+@g+C_
diff --git a/bin/server_data/docs/index.htm b/bin/server_data/docs/index.htm
new file mode 100644
index 0000000..d4589d4
--- /dev/null
+++ b/bin/server_data/docs/index.htm
@@ -0,0 +1,272 @@
+
+
+
+
+ Simple-httpd
+
+
+ Simple-httpd
+
+ Оглавление:
+
+
+
+
+
+ Описание программы и её возможностей
+
+ Simple-httpd - это небольшой http сервер для Колибри ОС, позволяющий размещать файлы, создавать
+ динамические сайты и различные сетевые ресурсы.
+
+
+
+
+ Установка и настройка
+
+ Для упрощения установки в репозитории находится директория bin, которая представляет из себя сервер, файл конфигурации и
+ некоторое количество демонстрационных модулей. Файл конфигурации в этой директории рассчитан на то, что сервер будет размещён
+ в корне раздела "/usbhd0/3/".
+
+
+ Дальнейшая настройка содержимого директории зависит от значений в файле httpd.ini .
+
+
+ В файле конфигурации можно выделяются 3 основных раздела:
+
+ -
+
[MAIN]
+ Данный раздел содержит в себе базовые элементы конфигурации, такие как:
+
+ ip
IPv4 адрес, на котором будет работать сервер. Параметр обязателен для заполнения
+ port
Порт подключения к серверу. При отсутствии параметра используется порт 80
+ conn
Максимальное количество открытых соединений. При отсутствии параметра используется значение 10
+ work_dir
Директория для размещения статичных файлов сервера, является корнем для uri путей. Параметр обязателен для заполнения
+ mime_file
Путь до файла сопоставления mime типов. Если параметр не указан используется встроенная таблица соответствия.
+ modules_dir
Директория, относительно которой в разделе [MODULES] указываются модули расширения.
+
+
+
+ -
+
[MODULES]
+ Данный раздел может содержать множество элементов, представленных в виде:
+ uri_path=file_name;cmdline
, где
+
+ - uri_path - uri путь ресурса без начального "/"
+ - file_name - путь к файлу модуля, относительно "modules_dir"
+ - cmdline - Строка передаваемая модулю во время инициализации каждого ресурса, ассоциированного с ним
+
+
+ [TLS]
+ Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.
+
+ mbedtls
Полный путь до библиотеки MbedTLS.
+ ca_cer
Полный путь до файла корневого сертификата.
+ srv_crt
Полный путь до файла сертификата сервера.
+ srv_key
Полный путь до файла содержащего секретный ключ сервера
+
+ Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в
+ этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается
+ полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.
+ Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не
+ использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола,
+ в незащищённой среде передачи данных.
+
+
+
+
+
+
+ Документация на API модулей
+
+ Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически.
+ По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции:
+
+
+ uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline)
+ Функция для инициализации ресурса(uri_path), ассоциированного с модулем .
+ В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например
+
+ test3=test_unit4.obj; -database="file.sqlite"
+
+ При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.
+
+ Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.
+
+ void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata)
+
+ Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт
+ в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса.
+
+ В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста.
+ Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP.
+
+
+ void __stdcall httpd_close(uint32_t pdata)
+ Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в
+ модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение,
+ возвращённое функцией "httpd_init".
+ Завершение работы сервера производится вызовом экспортируемой функции "close_server".
+ Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на
+ подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои
+ данные. После завершения всех модулей сервер полностью завершает свою работу.
+
+
+ Создание ответа на запрос
+ Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции,
+ позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос.
+
+ Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.
+
+ RESPD* __stdcall create_resp(CONNECT_DATA* session, uint32_t flags);
+ Функция создаёт объект RESPD, который имеет базовые настройки:
+
+
+ Параметр | Значение |
+
+
+ Статус ответа | "200" |
+ Версия протокола | "HTTP/1.1 " |
+ Content-type | "text/html" |
+
+
+ Также разработчик может указать битовые флаги конфигурации ответа, например следующие:
+
+ FLAG_TRANSFER_CHUNKED
+ Этот флаг выбирает "chunked" тип передачи данных с сервера к клиенту, что позволяет отправлять данные
+ неограниченной или неизвестной длины.
+ FLAG_RAW_STREAM
+ Этот флаг позволяет отправлять тело ответа небольшими пакетами, что можно использовать потоковую передачу
+ данных поверх http протокола, например для реализации интернет радио
+ FLAG_NO_CACHE_CONTROL
+ Этот флаг указывает, что в ответе не будет дефолтного заголовка "Cache-Control"
+ FLAG_KEEP_ALIVE
+ Этот флаг указывает, что в ответе будет дефолтный заголовок "Connection: keep-alive"
+
+
+ void __stdcall destruct_resp(RESPD* ptr);
+ Функция производит удаление объекта RESPD.
+
+ void __stdcall set_http_status(RESPD* ptr, uint32_t status);
+ Функция производит изменение статуса ответа. Статус записывается в виде строки вида "201 " упакованной в dword(0x20313032).
+
+ void __stdcall set_http_ver(RESPD* ptr, char* version, uint32_t length);
+ Функция производит изменение версии, отправляемой в ответе. Версия должна иметь вид строки, например "RTSP/1.1"
+
+ uint32_t __stdcall add_http_header(RESPD* ptr, char* ptr_header, uint32_t length);
+ Функция производит добавление новых заголовков в виде стоки. Функция не производит проверки содержимого строки.
+
+ uint32_t __stdcall del_http_header(RESPD* ptr, char* ptr_header);
+ Функция производит удаление дополнительного заголовка. Память под строку никак не изменяется.
+
+ uint32_t __stdcall begin_send_resp(RESPD* ptr, uint64_t content_length);
+ Функция производит отправку HTTP строки статуса и заголовков для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM.
+
+ uint32_t __stdcall send_resp(RESPD* ptr, char* content, uint32_t length);
+ Функция производит отправку http ответа целиком или его части для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM .
+
+ uint32_t __stdcall finish_send_resp(RESPD* ptr);
+ Функция производит завершение отправки данных для флагов FLAG_TRANSFER_CHUNKED
+
+
+ В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать
+ до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки.
+
+ Обработка данных запроса
+
+ char* __stdcall find_uri_arg(CONNECT_DATA* session, char* key);
+ Функция производит поиск аргумента uri строки по его названию. Если аргумент найден, то возвращается указатель на
+ строку с его значением, иначе ноль
+
+ char* __stdcall find_header(CONNECT_DATA* session, char* key);
+ Функция производит поиск http заголовка по его названию. Если аргумент найден, то возвращается указатель на
+ строку с его значением, иначе ноль
+
+ Для получения остальной информации, такой как: метод запроса, версии протокола, фрагмент uri строки и тело сообщения;
+ используется доступ к структуре CONNECT_DATA. Описание этой структуры есть в файле modules_api.inc репозитория.
+
+ Работа с файлами
+
+ void __stdcall FileInitFILED(FILED* buffer, char* path);
+ Функция производит инициализацию структуры FILED для её использования в файловых операциях.
+
+ FS_STATUS __stdcall FileInfo(char* path, void* buffer);
+ Функция производит чтение информации о файле в буфер по его пути и возвращает код ответа файловой системы.
+ Если возвращён 0 - операция выполнена успешно, иначе возникла ошибка.
+
+
+ uint32_t __stdcall FileRead(FILED* file, void* buffer, uint32_t size);
+ Функция производит чтение части файла и автоматически увеличивает смещение чтение на количество прочитанных байт.
+ По завершению чтения функция вернёт количество прочитанных байт в буфер, при ошибках чтение это значение равно нулю.
+
+
+ void __stdcall FileSetOffset(FILED* file, uint64_t offset);
+ Функция изменяет смещения чтения из файла.
+
+ uint32_t __stdcall FileReadOfName(char* path, void* buffer, uint32_t size)
+ Функция производит чтение файла по его названию начиная с нулевого смещения. Может использоваться для работы с небольшими
+ файлами с различными настройками модуля. Функция возвращает количество прочитанных байт, если же возвращён 0, то вероятно
+ произошла ошибка чтения.
+
+
+
+ Управление сервером
+ void close_server();
+ Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер
+ блокирует все новые подключения, позволяя модулям завершить открытые соединения.
+
+
+ Дополнительные функции
+ char* __stdcall Get_MIME_Type(FILED* fd);
+ Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла.
+ Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого файла.
+
+
+
+
+ Дополнительные программы и средства
+ Генератор файла MIME типов
+ Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине
+ у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm,
+ позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы.
+
+ Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос.
+ Последовательность передаваемых параметров в макрос следующая:
+
+ - Строка с MIME типом, который должен использоваться если не один другой тип не подходит
+ - Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf",
+ а после неё строка с MIME типом.
+
+
+
+ Что-то
+
+
+
+ Известные баги и особенности
+
+ - Сетевой стек нестабилен и что-то может пойти не так.
+ - При отправки больших объёмов данных может быть утеря или изменение порядка пакетов
+ - Сервер пока не умеет обрабатывать %XX символы в пути до ресурса
+ - Сервер не рассчитан на большие нагрузки
+ - Все пути в конфигурации сервера должны быть в ascii и без русских символов
+ - Отсутствует поддержка TLS
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/index.htm b/doc/index.htm
new file mode 100644
index 0000000..d4589d4
--- /dev/null
+++ b/doc/index.htm
@@ -0,0 +1,272 @@
+
+
+
+
+ Simple-httpd
+
+
+ Simple-httpd
+
+ Оглавление:
+
+
+
+
+
+ Описание программы и её возможностей
+
+ Simple-httpd - это небольшой http сервер для Колибри ОС, позволяющий размещать файлы, создавать
+ динамические сайты и различные сетевые ресурсы.
+
+
+
+
+ Установка и настройка
+
+ Для упрощения установки в репозитории находится директория bin, которая представляет из себя сервер, файл конфигурации и
+ некоторое количество демонстрационных модулей. Файл конфигурации в этой директории рассчитан на то, что сервер будет размещён
+ в корне раздела "/usbhd0/3/".
+
+
+ Дальнейшая настройка содержимого директории зависит от значений в файле httpd.ini .
+
+
+ В файле конфигурации можно выделяются 3 основных раздела:
+
+ -
+
[MAIN]
+ Данный раздел содержит в себе базовые элементы конфигурации, такие как:
+
+ ip
IPv4 адрес, на котором будет работать сервер. Параметр обязателен для заполнения
+ port
Порт подключения к серверу. При отсутствии параметра используется порт 80
+ conn
Максимальное количество открытых соединений. При отсутствии параметра используется значение 10
+ work_dir
Директория для размещения статичных файлов сервера, является корнем для uri путей. Параметр обязателен для заполнения
+ mime_file
Путь до файла сопоставления mime типов. Если параметр не указан используется встроенная таблица соответствия.
+ modules_dir
Директория, относительно которой в разделе [MODULES] указываются модули расширения.
+
+
+
+ -
+
[MODULES]
+ Данный раздел может содержать множество элементов, представленных в виде:
+ uri_path=file_name;cmdline
, где
+
+ - uri_path - uri путь ресурса без начального "/"
+ - file_name - путь к файлу модуля, относительно "modules_dir"
+ - cmdline - Строка передаваемая модулю во время инициализации каждого ресурса, ассоциированного с ним
+
+
+ [TLS]
+ Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.
+
+ mbedtls
Полный путь до библиотеки MbedTLS.
+ ca_cer
Полный путь до файла корневого сертификата.
+ srv_crt
Полный путь до файла сертификата сервера.
+ srv_key
Полный путь до файла содержащего секретный ключ сервера
+
+ Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в
+ этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается
+ полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.
+ Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не
+ использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола,
+ в незащищённой среде передачи данных.
+
+
+
+
+
+
+ Документация на API модулей
+
+ Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически.
+ По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции:
+
+
+ uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline)
+ Функция для инициализации ресурса(uri_path), ассоциированного с модулем .
+ В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например
+
+ test3=test_unit4.obj; -database="file.sqlite"
+
+ При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.
+
+ Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.
+
+ void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata)
+
+ Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт
+ в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса.
+
+ В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста.
+ Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP.
+
+
+ void __stdcall httpd_close(uint32_t pdata)
+ Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в
+ модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение,
+ возвращённое функцией "httpd_init".
+ Завершение работы сервера производится вызовом экспортируемой функции "close_server".
+ Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на
+ подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои
+ данные. После завершения всех модулей сервер полностью завершает свою работу.
+
+
+ Создание ответа на запрос
+ Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции,
+ позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос.
+
+ Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.
+
+ RESPD* __stdcall create_resp(CONNECT_DATA* session, uint32_t flags);
+ Функция создаёт объект RESPD, который имеет базовые настройки:
+
+
+ Параметр | Значение |
+
+
+ Статус ответа | "200" |
+ Версия протокола | "HTTP/1.1 " |
+ Content-type | "text/html" |
+
+
+ Также разработчик может указать битовые флаги конфигурации ответа, например следующие:
+
+ FLAG_TRANSFER_CHUNKED
+ Этот флаг выбирает "chunked" тип передачи данных с сервера к клиенту, что позволяет отправлять данные
+ неограниченной или неизвестной длины.
+ FLAG_RAW_STREAM
+ Этот флаг позволяет отправлять тело ответа небольшими пакетами, что можно использовать потоковую передачу
+ данных поверх http протокола, например для реализации интернет радио
+ FLAG_NO_CACHE_CONTROL
+ Этот флаг указывает, что в ответе не будет дефолтного заголовка "Cache-Control"
+ FLAG_KEEP_ALIVE
+ Этот флаг указывает, что в ответе будет дефолтный заголовок "Connection: keep-alive"
+
+
+ void __stdcall destruct_resp(RESPD* ptr);
+ Функция производит удаление объекта RESPD.
+
+ void __stdcall set_http_status(RESPD* ptr, uint32_t status);
+ Функция производит изменение статуса ответа. Статус записывается в виде строки вида "201 " упакованной в dword(0x20313032).
+
+ void __stdcall set_http_ver(RESPD* ptr, char* version, uint32_t length);
+ Функция производит изменение версии, отправляемой в ответе. Версия должна иметь вид строки, например "RTSP/1.1"
+
+ uint32_t __stdcall add_http_header(RESPD* ptr, char* ptr_header, uint32_t length);
+ Функция производит добавление новых заголовков в виде стоки. Функция не производит проверки содержимого строки.
+
+ uint32_t __stdcall del_http_header(RESPD* ptr, char* ptr_header);
+ Функция производит удаление дополнительного заголовка. Память под строку никак не изменяется.
+
+ uint32_t __stdcall begin_send_resp(RESPD* ptr, uint64_t content_length);
+ Функция производит отправку HTTP строки статуса и заголовков для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM.
+
+ uint32_t __stdcall send_resp(RESPD* ptr, char* content, uint32_t length);
+ Функция производит отправку http ответа целиком или его части для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM .
+
+ uint32_t __stdcall finish_send_resp(RESPD* ptr);
+ Функция производит завершение отправки данных для флагов FLAG_TRANSFER_CHUNKED
+
+
+ В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать
+ до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки.
+
+ Обработка данных запроса
+
+ char* __stdcall find_uri_arg(CONNECT_DATA* session, char* key);
+ Функция производит поиск аргумента uri строки по его названию. Если аргумент найден, то возвращается указатель на
+ строку с его значением, иначе ноль
+
+ char* __stdcall find_header(CONNECT_DATA* session, char* key);
+ Функция производит поиск http заголовка по его названию. Если аргумент найден, то возвращается указатель на
+ строку с его значением, иначе ноль
+
+ Для получения остальной информации, такой как: метод запроса, версии протокола, фрагмент uri строки и тело сообщения;
+ используется доступ к структуре CONNECT_DATA. Описание этой структуры есть в файле modules_api.inc репозитория.
+
+ Работа с файлами
+
+ void __stdcall FileInitFILED(FILED* buffer, char* path);
+ Функция производит инициализацию структуры FILED для её использования в файловых операциях.
+
+ FS_STATUS __stdcall FileInfo(char* path, void* buffer);
+ Функция производит чтение информации о файле в буфер по его пути и возвращает код ответа файловой системы.
+ Если возвращён 0 - операция выполнена успешно, иначе возникла ошибка.
+
+
+ uint32_t __stdcall FileRead(FILED* file, void* buffer, uint32_t size);
+ Функция производит чтение части файла и автоматически увеличивает смещение чтение на количество прочитанных байт.
+ По завершению чтения функция вернёт количество прочитанных байт в буфер, при ошибках чтение это значение равно нулю.
+
+
+ void __stdcall FileSetOffset(FILED* file, uint64_t offset);
+ Функция изменяет смещения чтения из файла.
+
+ uint32_t __stdcall FileReadOfName(char* path, void* buffer, uint32_t size)
+ Функция производит чтение файла по его названию начиная с нулевого смещения. Может использоваться для работы с небольшими
+ файлами с различными настройками модуля. Функция возвращает количество прочитанных байт, если же возвращён 0, то вероятно
+ произошла ошибка чтения.
+
+
+
+ Управление сервером
+ void close_server();
+ Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер
+ блокирует все новые подключения, позволяя модулям завершить открытые соединения.
+
+
+ Дополнительные функции
+ char* __stdcall Get_MIME_Type(FILED* fd);
+ Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла.
+ Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого файла.
+
+
+
+
+ Дополнительные программы и средства
+ Генератор файла MIME типов
+ Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине
+ у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm,
+ позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы.
+
+ Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос.
+ Последовательность передаваемых параметров в макрос следующая:
+
+ - Строка с MIME типом, который должен использоваться если не один другой тип не подходит
+ - Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf",
+ а после неё строка с MIME типом.
+
+
+
+ Что-то
+
+
+
+ Известные баги и особенности
+
+ - Сетевой стек нестабилен и что-то может пойти не так.
+ - При отправки больших объёмов данных может быть утеря или изменение порядка пакетов
+ - Сервер пока не умеет обрабатывать %XX символы в пути до ресурса
+ - Сервер не рассчитан на большие нагрузки
+ - Все пути в конфигурации сервера должны быть в ascii и без русских символов
+ - Отсутствует поддержка TLS
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/test_unit.asm b/example/test_unit.asm
index efb2e85..5acb181 100644
--- a/example/test_unit.asm
+++ b/example/test_unit.asm
@@ -33,7 +33,6 @@ unit_init:
xor eax, eax
push esi edi
mov esi, [esp + 4*2 + 4]
- mov [import_httpd], esi
cmp dword[esi + IMPORT_DATA.version], API_VERSION
jne .exit
@@ -68,7 +67,7 @@ server_entry:
cmp dword[edx], 'new'
je .no_del
- cmp dword[edx], 'del'
+ ;cmp dword[edx], 'del'
mov dword[text_message], ' '
mov dword[text_message + 4], ' '
@@ -117,7 +116,6 @@ server_entry:
rep movsd
pop edi esi
- mov [esi + CONNECT_DATA.buffer_response], eax
; copy message
mov ecx, [text_message]
mov [eax + sceleton_resp.message], ecx
@@ -150,12 +148,24 @@ server_entry:
; set httpcode
mov dword[edi + sceleton_resp.code], '200 '
; send http message
+ push dword FLAG_RAW_STREAM
+ push esi
+ call [IMPORT.create_resp]
- push dword 0 ; flags
+ test eax, eax
+ jz .exit
+
+ mov esi, eax
push sceleton_resp.size
push edi
- push dword[esi + CONNECT_DATA.socket]
- call [IMPORT.netfunc_send]
+ push eax
+ call [IMPORT.send_resp]
+
+ push esi
+ call [IMPORT.destruct_resp]
+
+ push edi
+ call [IMPORT.Free]
board_input 'send'
.exit:
@@ -173,8 +183,6 @@ _10: dd 10
count_call dd 0
-import_httpd: dd 0
-
sceleton_resp:
db 'HTTP/1.0 '
.code = $ - sceleton_resp
diff --git a/file_server.inc b/file_server.inc
index 33fad47..688a1d2 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 = 1400*23;64*1024
file_server:
@@ -36,13 +36,9 @@ file_server:
; 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
+ mov eax, esi
;; copy work_dir
mov esi, GLOBAL_DATA.work_dir
mov edi, edx
@@ -55,24 +51,22 @@ file_server:
cmp byte[esi - 1], 0
jne @b
- mov eax, edi
- dec eax
pop edi esi
- mov [edi + FILED.end_path], eax
+ ; init FILED
+ mov edi, edx
+ sub edi, sizeof.FILED; edi <- struct FILED
+ stdcall FileInitFILED, edi, edx
;; 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
+ stdcall FileInfo, edx, eax
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'
@@ -89,135 +83,61 @@ file_server:
jne .err_http_501
.send_file:
- ; create http response (set 200 code, MINE type and length of body)
- ;; alloc 33 kib
- push dword SIZE_FILE_BUFFER
- call Alloc
+ ; edi -> FILED
+ ; edi-40 ->FILEINFO
+ ; esi -> CONNECT_DATA
+ stdcall create_resp, esi, FLAG_NO_CONTENT_TYPE\
+ + FLAG_RAW_STREAM
test eax, eax
- jz .err_http_501 ; error memory
+ jz .err_http_501
+ mov ebp, eax
- push esi
- push edi
- push eax ; save pointer for Free
+ stdcall Alloc, SIZE_FILE_BUFFER
+ test eax, eax
+ jz .err_http_501_1
- mov esi, base_response
- mov ecx, response.body
- mov edi, [esp]
+ ; Add content type header
+ push eax esi edi
+ mov esi, default_http_cont_type
+ mov edi, eax
+ mov ecx, default_http_cont_type.length
rep movsb
- mov edi, [esp]
- mov dword[edi + response.code], '200 '
-
- mov dword[edi + response.connection], 'keep'
- mov dword[edi + response.connection + 4], '-ali'
- mov word[edi + response.connection + 8], 've'
-
-
- push dword[esp + 4] ; <-FILED
- call Get_MIME_Type
+ mov dword[eax + default_http_cont_type.value], ' '
+ mov dword[eax + default_http_cont_type.value + 4], ' '
+ mov dword[eax + default_http_cont_type.value + 8], ' '
+ lea edi, [eax + default_http_cont_type.value]
- add edi, response.content_type
+ stdcall Get_MIME_Type, [esp]
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
+ pop edi esi ;!!!!! "pop eax" not runing
- 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
+ mov eax, [esp]
+ stdcall add_http_header, ebp, eax, default_http_cont_type.length-2 ; skip \n\r
+ ;cmp eax, -1 ; error can`t running in this function(max 64 addition headers)
- pop eax
- add byte[ecx + 1], al
- ;xor edx, edx
- ;test eax, eax
- ;jne .div100
- pop eax
- xor edx, edx
+ stdcall begin_send_resp, ebp, [edi - 40 + 32], [edi - 40 + 36]
+ ;cmp eax, -1
+.send_block_file:
+ mov eax, [esp] ; allocated buffer
+ stdcall FileRead, edi, eax, SIZE_FILE_BUFFER
test eax, eax
- jne .div1000
+ jz .finish_send_file
- ;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 ecx, [esp]
+ stdcall send_resp, ebp, ecx, eax
+ ;cmp eax, -1
+ jmp .send_block_file
- mov dword[ebx + FILED.offset], 0
- mov dword[ebx + FILED.offset + 4], 0
- mov [ebx + FILED.buffer], edi
- mov [ebx + FILED.size], SIZE_FILE_BUFFER
-.send_response_body:
- ; read 32 kib to file
- push ebx
- call FileRead
- test eax, eax
- jz @f
- cmp eax, 6
+.finish_send_file:
+ stdcall Free
+ stdcall finish_send_resp, ebp
+ stdcall destruct_resp, ebp
- mov [0], eax
- jne .exit_free
-@@:
- ; send this block data
- push dword 0 ; flags
- push SIZE_FILE_BUFFER
- 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], SIZE_FILE_BUFFER
- adc [ebx + FILED.offset + 4], 0
-
- jmp @b
-
-.exit_free:
- push edi
- call Free
ret
.send_options:
@@ -230,9 +150,6 @@ file_server:
ret
-.err_not_found_1:
- push edi
- call Free
.err_not_found:
; send error 404
push dword 0 ; flags
@@ -242,7 +159,8 @@ file_server:
call netfunc_send
ret
-
+.err_http_501_1:
+ stdcall Free, ebp
.err_http_501:
; send error 501
push dword 0 ; flags
@@ -253,7 +171,6 @@ file_server:
ret
-
; char* stdcall Get_MIME_Type(FILED* fd); //path is ASCIIZ string
Get_MIME_Type:
push esi edi
diff --git a/httpd.asm b/httpd.asm
index cdaa59e..7075c66 100644
--- a/httpd.asm
+++ b/httpd.asm
@@ -4,7 +4,7 @@
; ;
; httpd - Simple http server for Kolibri OS. ;
; ;
-; Version 0.2.2, 10 March 2024 ;
+; Version 0.2.3, 31 March 2024 ;
; ;
;*****************************************************************************;
@@ -41,6 +41,7 @@ START:
jz @f
mov ecx, PATH
+ ; TODO: add check ""
@@:
; get settings
@@ -96,7 +97,7 @@ START:
.sock_err:
mcall -1
-
+;-----------------------------------------------------------------------------
thread_connect:
sub esp, sizeof.CONNECT_DATA
@@ -256,6 +257,11 @@ ini_key_work_dir db 'work_dir',0
ini_key_modules_dir db 'modules_dir',0
ini_key_mime_file db 'mime_file',0
+ini_key_mbedtls_obj db 'mbedtls',0
+ini_key_ca_cer db 'ca_cer',0
+ini_key_srv_crt db 'srv_crt',0
+ini_key_srv_key db 'srv_key',0
+
httpd_module_init db 'httpd_init',0
httpd_module_serv db 'httpd_serv',0
httpd_module_close db 'httpd_close',0
@@ -279,12 +285,16 @@ EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA
dd netfunc_listen
dd netfunc_recv
dd netfunc_send
- dd FileInfo
- dd FileRead
dd Alloc
dd Free
dd parse_http_query ; no stdcall
+ dd FileInitFILED
+ dd FileInfo
+ dd FileRead
+ dd FileSetOffset
+ dd FileReadOfName
+
dd send_resp
dd create_resp
dd destruct_resp
@@ -292,13 +302,14 @@ EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA
dd add_http_header
dd del_http_header
dd set_http_ver
- dd find_uri_arg
- dd find_header
- dd close_server
dd begin_send_resp
dd finish_send_resp
- dd base_response
+ dd find_uri_arg
+ dd find_header
+ dd Get_MIME_Type
+ dd close_server
+
dd GLOBAL_DATA
.size = $ - EXPORT_DATA ; (count func)*4 + size(api ver) + 4
dd 0
@@ -307,6 +318,8 @@ EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA
;UDATA
srv_stop: rd 1 ; set 1 for skip new connections
srv_shutdown: rd 1 ; set 1 for ending working server
+srv_tls_enable rd 1 ; set 1 for enable TLS mode working
+
srv_backlog: rd 1 ; maximum number of simultaneous open connections
srv_socket: rd 1
diff --git a/httpd_lib.inc b/httpd_lib.inc
index ad97635..1ecdb82 100644
--- a/httpd_lib.inc
+++ b/httpd_lib.inc
@@ -52,22 +52,6 @@
;serv_header:
; .Accept_Ranges db 'Accept-Ranges: bytes',13,10
-;http_method:
-; .get: db 'GET '
-; .head: db 'HEAD'
-; .post: db 'POST'
-; .put: db 'PUT '
-; .patch db 'PATCH'
-
-;error_404:
-; db ''
-; db 'Error 404'
-; db ''
-; db 'Error 404
'
-; db 'The server could not find the requested page.
'
-; db ''
-; db '',0
-
;http_err_response:
; db 'HTTP/1.1 '
;.code = $ - http_err_response
@@ -97,7 +81,9 @@ default_http_cont_encod:
.length = $ - default_http_cont_encod
default_http_cont_type:
- db 'Content-type: text/html', 13, 10
+ db 'Content-type: '
+.value = $ - default_http_cont_type
+ db 'text/html ', 13, 10;
.length = $ - default_http_cont_type
default_http_cache_ctl:
@@ -153,35 +139,6 @@ http_response_options:
.size = $ - http_response_options
-
-
-base_response:
-response:
- db 'HTTP/1.1 '
-.code = $ - response
- db '000 ',13, 10
- db 'Server: simple-httpd/0.3.0', 13, 10
- db 'Cache-Control: no-cache', 13, 10
- db 'Content-Encoding: '
-.content_encod = $ - response
- db 'identity', 13, 10
-; db 'Date: '
-;.date: db 'Sun, 30 Oct 2022 09:29:13 GMT',13, 10
- db 'Content-length: '
-.content_len = $ - response
- db '0000000000000000000000', 13, 10
- db 'Content-type: '
-.content_type = $ - response
- db 'text/html ', 13, 10;
- ;'text/html; charset=utf-8'
- db 'Connection: '
-.connection = $ - response
- db 'close ', 13, 10
- ; 'keep-alive'
-.end_headers = $ - response ; for adding new headers
- db 13, 10
-.body = $ - response ; offset for add http body in simple response
-
; min HTTP request size
; "GET / HTTP/1.1" - 18 byte
min_http_size = 18
diff --git a/makefile b/makefile
index f5d9b19..52abb78 100644
--- a/makefile
+++ b/makefile
@@ -5,7 +5,7 @@ examples=$(wildcard example/*.asm)
examples_obj=$(patsubst %.asm,%.obj,$(examples))
-all: build-main build-mime $(examples_obj)
+all: build-main build-mime $(examples_obj) copy_docs
build-main:
@@ -17,3 +17,5 @@ build-mime:
example/%.obj: example/%.asm
fasm $< $(OUTPUT_MODULES)/$(notdir $(basename $@)).obj
+copy_docs:
+ cp -R doc/* $(OUTPUT_DIR)/server_data/docs
\ No newline at end of file
diff --git a/module_api.inc b/module_api.inc
index be27f10..2837cd2 100644
--- a/module_api.inc
+++ b/module_api.inc
@@ -27,18 +27,28 @@ struct CONNECT_DATA ; 16*4 = 64 bytes
end_buffer_request dd 0 ; для парсера
buffer_response dd 0 ; pointer to buffwr for resp message
http_method dd 0 ; указатель на строку
- http_verion dd 0 ; указатель на строку
+ http_verion dd 0 ; pointer to the asciiz string with protocol version
num_headers dd 0 ; number items in REQUEST_DATA
- http_headers dd 0 ; указатель на массив REQUEST_DATA
+ http_headers dd 0 ; pointer to array REQUEST_DATA of HTTP headers
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_arg dd 0 ; pointer to the REQUEST_DATA array of string uri arguments
uri_fragment dd 0 ; указатель на строку
message_body dd 0 ; указатель на тело http запроса
ends
+struct FILED
+ opcode rd 1
+ offset rd 2
+ size rd 1
+ buffer rd 1
+ rb 1
+ path rd 1
+ end_path rd 1
+ends
+
struct IMPORT_DATA
version rd 1 ; dword for check api
@@ -50,11 +60,21 @@ struct IMPORT_DATA
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
+ ;---------------------------------------------------------------------
+ FileInitFILED rd 1
+ ;void stdcall FileInitFILED(FILED* buffer, char* path);
+ FileInfo rd 1
+ ;FS_STATUS stdcall FileInfo(char* path, void* buffer);
+ FileRead rd 1
+ ;uint32_t stdcall FileRead(FILED* file, void* buffer, uint32_t size);
+ FileSetOffset rd 1
+ ;void stdcall FileSetOffset(FILED* file, uint64_t offset);
+ FileReadOfName rd 1
+ ;uint32_t stdcall FileReadOfName(char* path, void* buffer, uint32_t size);
+ ;---------------------------------------------------------------------
send_resp rd 1
; send_resp(RESPD* ptr, char* content, uint32_t length);
create_resp rd 1
@@ -72,17 +92,19 @@ struct IMPORT_DATA
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();
begin_send_resp rd 1
;uint32_t begin_send_resp(RESPD* ptr, uint64_t content_length);
finish_send_resp rd 1
;uint32_t finish_send_resp(RESPD* ptr);
+ ;---------------------------------------------------------------------
+ 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);
+ get_mime_type rd 1
+ ;char* stdcall Get_MIME_Type(FILED* fd); //path is ASCIIZ string
+ 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/settings.inc b/settings.inc
index 22f6a25..c1e8000 100644
--- a/settings.inc
+++ b/settings.inc
@@ -40,6 +40,7 @@ load_settings:
mov dword[srv_stop], 0
mov dword[srv_shutdown], 0
+ mov dword[srv_tls_enable], 0
sub esp, 16
mov esi, esp
@@ -71,7 +72,17 @@ load_settings:
mov word[srv_sockaddr], AF_INET4
- invoke ini.get_int, ebp, ini_section_main, ini_key_port, 80 ; standart port
+ invoke ini.enum_keys, ebp, ini_section_tls, .add_module.exit
+ test eax, eax
+ jnz @f
+ mov dword[srv_tls_enable], 1
+@@:
+ mov eax, 80
+ cmp dword[srv_tls_enable], 0
+ je @f
+ mov eax, 443
+@@:
+ invoke ini.get_int, ebp, ini_section_main, ini_key_port, eax ; standart port
xchg al, ah
mov [srv_sockaddr.port], ax
@@ -217,32 +228,28 @@ load_mime_file:
pop eax
mov esi, eax
- lea ecx, [eax + sizeof.FILED + 40]
- mov [esi + FILED.path], ecx
- invoke ini.get_str, ebp, ini_section_main, ini_key_mime_file, ecx, 1024, 0
+ invoke ini.get_str, ebp, ini_section_main, ini_key_mime_file, esi, 1024, 0
test eax, eax
jnz .no_file
- lea ecx, [esi + sizeof.FILED]
- mov [esi + FILED.buffer], ecx
- stdcall FileInfo, esi
+ sub esp, 40
+ stdcall FileInfo, esi, esp
test eax, eax
jnz .no_file
- mov ecx, [esi + sizeof.FILED + 32]
+ mov ecx, [esp + 32]
stdcall Alloc, ecx
test eax, eax
jz .no_file
- mov ecx, [esi + sizeof.FILED + 32]
+ mov ecx, [esp + 32]
mov edi, eax
- mov [esi + FILED.buffer], eax
- mov [esi + FILED.size], ecx
- mov [esi + FILED.offset], 0
- mov dword[esi + FILED.offset + 4], 0
- stdcall FileRead, esi
+
+ stdcall FileReadOfName, esi, edi, ecx
test eax, eax
- jnz .error_read
+ jz .error_read
+
+ add esp, 40
mov dword[GLOBAL_DATA.MIME_types_arr], edi
mov eax, edi
@@ -258,6 +265,7 @@ load_mime_file:
.error_read:
stdcall Free, edi
.no_file:
+ add esp, 40
stdcall Free, esi
.err:
mov dword[GLOBAL_DATA.MIME_types_arr], STD_MIME_TYPE_ARR
diff --git a/sys_func.inc b/sys_func.inc
index 5070cdc..6b4acc8 100644
--- a/sys_func.inc
+++ b/sys_func.inc
@@ -187,36 +187,117 @@ Free:
pop ebx
ret 4
+;-----------------------------------------------------------------------------
-struct FILED
- opcode rd 1
- offset rd 2
- size rd 1
- buffer rd 1
- rb 1
- path rd 1
- end_path rd 1
-ends
-
-;NTSTATUS stdcall FileInfo(FILED* file)
+;FS_STATUS stdcall FileInfo(char* path, void* buffer)
FileInfo:
+ mov ecx, [esp + 4]
+ mov edx, [esp + 8]
push ebx
- mov ebx, [esp + 4*1 + 4]
- mov dword[ebx], 5 ; file info
- mov dword[ebx + FILED.offset + 4], 0 ; zero flag
+ sub esp, sizeof.FILED
+ mov dword[esp + FILED.opcode], 5 ; file info
+ mov dword[esp + FILED.offset + 4], 0 ; zero flag
+ mov dword[esp + FILED.buffer], edx
+ mov byte[esp + FILED.path - 1], 0
+ mov dword[esp + FILED.path], ecx
+ mov ebx, esp
mcall 70
+ add esp, sizeof.FILED
pop ebx
- ret 4
-;NTSATTUS stdcall FileRead(FILED* file)
+ ret 8
+
+; void stdcall FileInitFILED(void* buffer, char* path)
+FileInitFILED:
+ push ecx edi
+ mov edi, [esp + 4*2 + 4]
+ mov ecx, sizeof.FILED
+ xor eax, eax
+ rep stosb
+ mov eax, [esp + 4*2 + 4]
+ mov ecx, [esp + 4*2 + 8]
+ mov [eax + FILED.path], ecx
+ dec ecx
+@@:
+ inc ecx
+ cmp byte[ecx], 0
+ jne @b
+
+ mov [eax + FILED.end_path], ecx
+ pop edi ecx
+ ret 8
+
+;uint32_t stdcall FileRead(FILED* file, void* buffer, uint32_t size)
FileRead:
+
+ mov eax, [esp + 4]
+ mov ecx, [esp + 8]
+ mov edx, [esp + 12]
+
push ebx
- mov ebx, [esp + 4*1 + 4]
- mov dword[ebx], 0 ; read file
+ mov [eax + FILED.opcode], 0
+ mov [eax + FILED.size], edx
+ mov [eax + FILED.buffer], ecx
+
+ mov ebx, eax
mcall 70
+
+ test eax, eax
+ jz @f
+ cmp eax, 6 ; EOF
+ je @f
+ xor ebx, ebx
+@@:
+ mov eax, ebx
+
pop ebx
- ret 4
+ mov ecx, [esp + 4]
+ add [ecx + FILED.offset], eax
+ adc [ecx + FILED.offset], 0
+
+ ret 12
+;void stdcall FileSetOffset(FILED* file, uint64_t offset)
+FileSetOffset:
+ push ecx
+ mov eax, [esp + 4]
+ mov ecx, [esp + 8]
+ mov [eax + FILED.offset], ecx
+ mov ecx, [esp + 12]
+ mov [eax + FILED.offset + 4], ecx
+ pop ecx
+ ret 12
+
+;uint32_t stdcall FileReadOfName(char* path, void* buffer, uint32_t size)
+FileReadOfName:
+ mov ecx, [esp + 4]
+ mov edx, [esp + 8]
+ mov eax, [esp + 12]
+ push ebx
+ sub esp, sizeof.FILED
+ mov dword[esp + FILED.opcode], 0
+ mov dword[esp + FILED.offset], 0
+ mov dword[esp + FILED.offset + 4], 0
+ mov dword[esp + FILED.size], eax
+ mov dword[esp + FILED.buffer], edx
+ mov byte[esp + FILED.path - 1], 0
+ mov dword[esp + FILED.path], ecx
+ mov ebx, esp
+ mcall 70
+ test eax, eax
+ jz @f
+ cmp eax, 6 ; EOF
+ je @f
+ xor ebx, ebx
+@@:
+ mov eax, ebx
+ add esp, sizeof.FILED
+ pop ebx
+ ret 12
+
+
+
+;-----------------------------------------------------------------------------
;RESPD* stdcall create_resp(CONNECT_DATA* session, uint32_t flags)
@@ -355,7 +436,6 @@ send_resp:
.chunked:
- ; TODO
mov eax, -1
mov ecx, [esp + 4*3 + 8] ; ptr
test ecx, ecx
@@ -388,8 +468,8 @@ send_resp:
call netfunc_send
add esp, 2+8
- cmp eax, -1
- jz .exit
+ ;cmp eax, -1
+ ;jz .exit
; send content
mov ecx, [esp + 4*3 + 8] ; ptr
@@ -401,8 +481,8 @@ send_resp:
push dword[eax + CONNECT_DATA.socket]
call netfunc_send
- cmp eax, -1
- jz .exit
+ ;cmp eax, -1
+ ;jz .exit
; send db 13, 10
push word 0x0a0d
@@ -415,6 +495,7 @@ send_resp:
push dword[eax + CONNECT_DATA.socket]
call netfunc_send
+ add esp, 2
pop ebp edi esi
ret 12
@@ -712,7 +793,7 @@ finish_send_resp:
.exit:
ret 4
-
+;-----------------------------------------------------------------------------
;void close_server()
; TODO: added free HTTPD_MODULE structures
close_server:
diff --git a/utils/mime_types.asm b/utils/mime_types.asm
index 2e11578..481cc84 100644
--- a/utils/mime_types.asm
+++ b/utils/mime_types.asm
@@ -9,7 +9,6 @@ macro table arg3, [arg1,arg2] {
common
local ..other
dd ..other
- ; size = ($ - ) / 8
forward
..x db ..x_end-..x - 1, arg1
..x_end db arg2, 0
@@ -20,20 +19,54 @@ macro table arg3, [arg1,arg2] {
}
-table 'application/octet-stream' ,\
- '.html', 'text/html' ,\
- '.htm', 'text/html' ,\
- '.css', 'text/css' ,\
- '.js', 'text/javascript' ,\
- '.txt', 'text/plain; charset=utf-8' ,\
- '.pdf', 'application/pdf' ,\
- '.json', 'application/json' ,\
- '.png', 'image/png' ,\
- '.mp3', 'audio/mpeg' ,\
- '.mp4', 'video/mp4' ,\
- '.gif', 'image/gif' ,\
- '.webp', 'image/webp' ,\
- '.svg', 'image/svg+xml' ,\
- '.apng', 'image/apng' ,\
- '.jpeg', 'image/jpeg' ,\
- '.jpg','image/jpeg'
+table 'application/octet-stream' ,\
+ '.html', 'text/html' ,\
+ '.htm', 'text/html' ,\
+ '.css', 'text/css' ,\
+ '.js', 'text/javascript' ,\
+ '.txt', 'text/plain; charset=utf-8' ,\
+ '.pdf', 'application/pdf' ,\
+ '.rtf', 'application/rtf' ,\
+ '.json', 'application/json' ,\
+ '.xml', 'application/xml' ,\
+ '.ics', 'text/calendar' ,\
+ '.cvs', 'text/csv' ,\
+ \
+ '.gz', 'application/gzip' ,\
+ '.zip', 'application/zip' ,\
+ '.7z', 'application/x-7z-compressed' ,\
+ '.bz', 'application/x-bzip' ,\
+ '.bz2', 'application/x-bzip2' ,\
+ '.tar', 'application/x-tar' ,\
+ \
+ '.woff', 'font/woff' ,\
+ '.woff2', 'font/woff2' ,\
+ '.tff', 'font/ttf' ,\
+ '.otf', 'font/otf' ,\
+ \
+ '.mp3', 'audio/mpeg' ,\
+ '.mid', 'audio/midi' ,\
+ '.midi', 'audio/midi' ,\
+ '.wav', 'audio/wav' ,\
+ '.weba', 'audio/webm' ,\
+ '.opus', 'audio/opus' ,\
+ '.oga', 'audio/ogg' ,\
+ \
+ '.mp4', 'video/mp4' ,\
+ '.avi', 'video/x-msvideo' ,\
+ '.mpeg', 'video/mpeg' ,\
+ '.webm', 'video/webm' ,\
+ '.ogv', 'video/ogg' ,\
+ '.mkv', 'application/x-matroska' ,\
+ \
+ '.png', 'image/png' ,\
+ '.bmp', 'image/bmp' ,\
+ '.gif', 'image/gif' ,\
+ '.avif', 'image/avif' ,\
+ '.webp', 'image/webp' ,\
+ '.svg', 'image/svg+xml' ,\
+ '.apng', 'image/apng' ,\
+ '.tif', 'image/tiff' ,\
+ '.tiff', 'image/tiff' ,\
+ '.jpeg', 'image/jpeg' ,\
+ '.jpg', 'image/jpeg'