mirror of
https://github.com/Doczom/simple-httpd.git
synced 2025-09-22 15:13:50 +02:00
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
This commit is contained in:
@@ -13,7 +13,7 @@ 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)
|
||||||
modules_dir=/usbhd0/3
|
modules_dir=/usbhd0/3/modules
|
||||||
|
|
||||||
mime_file=/usbhd0/3/mime_types.bin
|
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
|
; 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
|
||||||
test5=test_unit5.obj
|
|
||||||
admin=srv_control.obj;123456
|
|
||||||
;database/sqlite3=sqlite3_serv.obj
|
;database/sqlite3=sqlite3_serv.obj
|
||||||
;database/cvs=cvs_table_server.obj
|
;database/cvs=cvs_table_server.obj
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
272
bin/server_data/docs/index.htm
Normal file
272
bin/server_data/docs/index.htm
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta lang="ru">
|
||||||
|
<title>Simple-httpd</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Simple-httpd</h1>
|
||||||
|
|
||||||
|
<h2>Оглавление:</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#about">Описание программы и её возможностей</a></li>
|
||||||
|
<li><a href="#install">Установка и настройка</a></li>
|
||||||
|
<li><a href="#api">Документация на API модулей</a></li>
|
||||||
|
<li><a href="#other-soft">Дополнительные программы и средства </a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#MIME-macro">Генерация файла MIME типов</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#Bugs">Известные баги и особенности</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<!-- Описание -->
|
||||||
|
<h2 id="about">Описание программы и её возможностей</h2>
|
||||||
|
<p>
|
||||||
|
Simple-httpd - это небольшой http сервер для Колибри ОС, позволяющий размещать файлы, создавать
|
||||||
|
динамические сайты и различные сетевые ресурсы.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<!-- Установка -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="install">Установка и настройка</h2>
|
||||||
|
<p>
|
||||||
|
Для упрощения установки в репозитории находится директория bin, которая представляет из себя сервер, файл конфигурации и
|
||||||
|
некоторое количество демонстрационных модулей. Файл конфигурации в этой директории рассчитан на то, что сервер будет размещён
|
||||||
|
в корне раздела "/usbhd0/3/".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Дальнейшая настройка содержимого директории зависит от значений в файле httpd.ini .
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
В файле конфигурации можно выделяются 3 основных раздела:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<code>[MAIN]</code>
|
||||||
|
<p> Данный раздел содержит в себе базовые элементы конфигурации, такие как:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>ip</code><p> IPv4 адрес, на котором будет работать сервер. Параметр обязателен для заполнения </p></li>
|
||||||
|
<li><code>port</code><p> Порт подключения к серверу. При отсутствии параметра используется порт 80</p></li>
|
||||||
|
<li><code>conn</code><p> Максимальное количество открытых соединений. При отсутствии параметра используется значение 10</p></li>
|
||||||
|
<li><code>work_dir</code><p> Директория для размещения статичных файлов сервера, является корнем для uri путей. Параметр обязателен для заполнения </p></li>
|
||||||
|
<li><code>mime_file</code><p> Путь до файла сопоставления mime типов. Если параметр не указан используется встроенная таблица соответствия.</p></li>
|
||||||
|
<li><code>modules_dir</code><p> Директория, относительно которой в разделе [MODULES] указываются модули расширения.</p></li>
|
||||||
|
<li><code></code><p> </p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>[MODULES]</code>
|
||||||
|
<p> Данный раздел может содержать множество элементов, представленных в виде: <br>
|
||||||
|
<code>uri_path=file_name;cmdline</code> , где </p>
|
||||||
|
<ul>
|
||||||
|
<li><b>uri_path</b> - uri путь ресурса без начального "/" </li>
|
||||||
|
<li><b>file_name</b> - путь к файлу модуля, относительно "modules_dir"</li>
|
||||||
|
<li><b>cmdline</b> - Строка передаваемая модулю во время инициализации каждого ресурса, ассоциированного с ним</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><code>[TLS]</code>
|
||||||
|
<p>Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>mbedtls</code><p> Полный путь до библиотеки MbedTLS.</p></li>
|
||||||
|
<li><code>ca_cer</code><p> Полный путь до файла корневого сертификата.</p></li>
|
||||||
|
<li><code>srv_crt</code><p> Полный путь до файла сертификата сервера.</p></li>
|
||||||
|
<li><code>srv_key</code><p> Полный путь до файла содержащего секретный ключ сервера</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в
|
||||||
|
этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается
|
||||||
|
полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.</p>
|
||||||
|
<p>Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не
|
||||||
|
использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола,
|
||||||
|
в незащищённой среде передачи данных.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- АПИ модулей -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="api">Документация на API модулей</h2>
|
||||||
|
<p>
|
||||||
|
Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически.
|
||||||
|
По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li><code>uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline)</code>
|
||||||
|
<p> Функция для инициализации ресурса(uri_path), ассоциированного с модулем .
|
||||||
|
В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например
|
||||||
|
|
||||||
|
<code> test3=test_unit4.obj; -database="file.sqlite" </code>
|
||||||
|
|
||||||
|
При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.
|
||||||
|
</p>
|
||||||
|
<p> Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata)</code>
|
||||||
|
<p>
|
||||||
|
Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт
|
||||||
|
в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса.
|
||||||
|
</p>
|
||||||
|
<p> В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста.
|
||||||
|
Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall httpd_close(uint32_t pdata)</code>
|
||||||
|
<p> Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в
|
||||||
|
модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение,
|
||||||
|
возвращённое функцией "httpd_init".</p>
|
||||||
|
<p> Завершение работы сервера производится вызовом экспортируемой функции "close_server".</p>
|
||||||
|
<p> Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на
|
||||||
|
подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои
|
||||||
|
данные. После завершения всех модулей сервер полностью завершает свою работу.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h3>Создание ответа на запрос</h3>
|
||||||
|
<p> Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции,
|
||||||
|
позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос.
|
||||||
|
</p>
|
||||||
|
<p>Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>RESPD* __stdcall create_resp(CONNECT_DATA* session, uint32_t flags);</code>
|
||||||
|
<p> Функция создаёт объект RESPD, который имеет базовые настройки:</p>
|
||||||
|
<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Параметр</th><th>Значение</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Статус ответа</th><th>"200"</th> </tr>
|
||||||
|
<tr><th>Версия протокола</th><th>"HTTP/1.1 "</th></tr>
|
||||||
|
<tr><th>Content-type</th><th>"text/html"</th></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> Также разработчик может указать битовые флаги конфигурации ответа, например следующие:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>FLAG_TRANSFER_CHUNKED</code>
|
||||||
|
<p>Этот флаг выбирает "chunked" тип передачи данных с сервера к клиенту, что позволяет отправлять данные
|
||||||
|
неограниченной или неизвестной длины. </p></li>
|
||||||
|
<li><code>FLAG_RAW_STREAM</code>
|
||||||
|
<p>Этот флаг позволяет отправлять тело ответа небольшими пакетами, что можно использовать потоковую передачу
|
||||||
|
данных поверх http протокола, например для реализации интернет радио</p></li>
|
||||||
|
<li><code>FLAG_NO_CACHE_CONTROL</code>
|
||||||
|
<p>Этот флаг указывает, что в ответе не будет дефолтного заголовка "Cache-Control"</p></li>
|
||||||
|
<li><code>FLAG_KEEP_ALIVE</code>
|
||||||
|
<p>Этот флаг указывает, что в ответе будет дефолтный заголовок "Connection: keep-alive"</p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall destruct_resp(RESPD* ptr);</code>
|
||||||
|
<p>Функция производит удаление объекта RESPD.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall set_http_status(RESPD* ptr, uint32_t status); </code>
|
||||||
|
<p>Функция производит изменение статуса ответа. Статус записывается в виде строки вида "201 " упакованной в dword(0x20313032).</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall set_http_ver(RESPD* ptr, char* version, uint32_t length);</code>
|
||||||
|
<p>Функция производит изменение версии, отправляемой в ответе. Версия должна иметь вид строки, например "RTSP/1.1"</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall add_http_header(RESPD* ptr, char* ptr_header, uint32_t length);</code>
|
||||||
|
<p>Функция производит добавление новых заголовков в виде стоки. Функция не производит проверки содержимого строки.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall del_http_header(RESPD* ptr, char* ptr_header);</code>
|
||||||
|
<p>Функция производит удаление дополнительного заголовка. Память под строку никак не изменяется.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall begin_send_resp(RESPD* ptr, uint64_t content_length); </code>
|
||||||
|
<p>Функция производит отправку HTTP строки статуса и заголовков для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall send_resp(RESPD* ptr, char* content, uint32_t length); </code>
|
||||||
|
<p>Функция производит отправку http ответа целиком или его части для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM .</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall finish_send_resp(RESPD* ptr);</code>
|
||||||
|
<p>Функция производит завершение отправки данных для флагов FLAG_TRANSFER_CHUNKED</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать
|
||||||
|
до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки.
|
||||||
|
</p>
|
||||||
|
<h3>Обработка данных запроса </h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>char* __stdcall find_uri_arg(CONNECT_DATA* session, char* key); </code>
|
||||||
|
<p>Функция производит поиск аргумента uri строки по его названию. Если аргумент найден, то возвращается указатель на
|
||||||
|
строку с его значением, иначе ноль</p>
|
||||||
|
</li>
|
||||||
|
<li><code>char* __stdcall find_header(CONNECT_DATA* session, char* key);</code>
|
||||||
|
<p>Функция производит поиск http заголовка по его названию. Если аргумент найден, то возвращается указатель на
|
||||||
|
строку с его значением, иначе ноль</p>
|
||||||
|
</li>
|
||||||
|
<p>Для получения остальной информации, такой как: метод запроса, версии протокола, фрагмент uri строки и тело сообщения;
|
||||||
|
используется доступ к структуре CONNECT_DATA. Описание этой структуры есть в файле modules_api.inc репозитория.</p>
|
||||||
|
</ul>
|
||||||
|
<h3>Работа с файлами</h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>void __stdcall FileInitFILED(FILED* buffer, char* path);</code>
|
||||||
|
<p> Функция производит инициализацию структуры FILED для её использования в файловых операциях.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>FS_STATUS __stdcall FileInfo(char* path, void* buffer);</code>
|
||||||
|
<p> Функция производит чтение информации о файле в буфер по его пути и возвращает код ответа файловой системы.
|
||||||
|
Если возвращён 0 - операция выполнена успешно, иначе возникла ошибка.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall FileRead(FILED* file, void* buffer, uint32_t size);</code>
|
||||||
|
<p> Функция производит чтение части файла и автоматически увеличивает смещение чтение на количество прочитанных байт.
|
||||||
|
По завершению чтения функция вернёт количество прочитанных байт в буфер, при ошибках чтение это значение равно нулю.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall FileSetOffset(FILED* file, uint64_t offset);</code>
|
||||||
|
<p> Функция изменяет смещения чтения из файла. </p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall FileReadOfName(char* path, void* buffer, uint32_t size)</code>
|
||||||
|
<p> Функция производит чтение файла по его названию начиная с нулевого смещения. Может использоваться для работы с небольшими
|
||||||
|
файлами с различными настройками модуля. Функция возвращает количество прочитанных байт, если же возвращён 0, то вероятно
|
||||||
|
произошла ошибка чтения.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Управление сервером</h3>
|
||||||
|
<code>void close_server();</code>
|
||||||
|
<p> Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер
|
||||||
|
блокирует все новые подключения, позволяя модулям завершить открытые соединения.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Дополнительные функции</h3>
|
||||||
|
<code>char* __stdcall Get_MIME_Type(FILED* fd);</code>
|
||||||
|
<p> Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла.
|
||||||
|
Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого <a href="#MIME-macro">файла</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Дополнительные средства -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="other-soft">Дополнительные программы и средства</h2>
|
||||||
|
<h3 id="MIME-macro">Генератор файла MIME типов</h3>
|
||||||
|
<p>Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине
|
||||||
|
у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm,
|
||||||
|
позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы.
|
||||||
|
</p>
|
||||||
|
<p> Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос.
|
||||||
|
Последовательность передаваемых параметров в макрос следующая:
|
||||||
|
<ol>
|
||||||
|
<li>Строка с MIME типом, который должен использоваться если не один другой тип не подходит</li>
|
||||||
|
<li>Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf",
|
||||||
|
а после неё строка с MIME типом.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<h3>Что-то</h3>
|
||||||
|
|
||||||
|
<!-- Баги -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="Bugs">Известные баги и особенности</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Сетевой стек нестабилен и что-то может пойти не так.</li>
|
||||||
|
<li>При отправки больших объёмов данных может быть утеря или изменение порядка пакетов</li>
|
||||||
|
<li>Сервер пока не умеет обрабатывать %XX символы в пути до ресурса</li>
|
||||||
|
<li>Сервер не рассчитан на большие нагрузки</li>
|
||||||
|
<li>Все пути в конфигурации сервера должны быть в ascii и без русских символов</li>
|
||||||
|
<li>Отсутствует поддержка TLS</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<!-- Авторы -->
|
||||||
|
<hr>
|
||||||
|
<footer id="Autor">
|
||||||
|
<p>Автор: Махаил Фролов aka Doczom</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
272
doc/index.htm
Normal file
272
doc/index.htm
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta lang="ru">
|
||||||
|
<title>Simple-httpd</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Simple-httpd</h1>
|
||||||
|
|
||||||
|
<h2>Оглавление:</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#about">Описание программы и её возможностей</a></li>
|
||||||
|
<li><a href="#install">Установка и настройка</a></li>
|
||||||
|
<li><a href="#api">Документация на API модулей</a></li>
|
||||||
|
<li><a href="#other-soft">Дополнительные программы и средства </a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#MIME-macro">Генерация файла MIME типов</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#Bugs">Известные баги и особенности</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<!-- Описание -->
|
||||||
|
<h2 id="about">Описание программы и её возможностей</h2>
|
||||||
|
<p>
|
||||||
|
Simple-httpd - это небольшой http сервер для Колибри ОС, позволяющий размещать файлы, создавать
|
||||||
|
динамические сайты и различные сетевые ресурсы.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<!-- Установка -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="install">Установка и настройка</h2>
|
||||||
|
<p>
|
||||||
|
Для упрощения установки в репозитории находится директория bin, которая представляет из себя сервер, файл конфигурации и
|
||||||
|
некоторое количество демонстрационных модулей. Файл конфигурации в этой директории рассчитан на то, что сервер будет размещён
|
||||||
|
в корне раздела "/usbhd0/3/".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Дальнейшая настройка содержимого директории зависит от значений в файле httpd.ini .
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
В файле конфигурации можно выделяются 3 основных раздела:
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<code>[MAIN]</code>
|
||||||
|
<p> Данный раздел содержит в себе базовые элементы конфигурации, такие как:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>ip</code><p> IPv4 адрес, на котором будет работать сервер. Параметр обязателен для заполнения </p></li>
|
||||||
|
<li><code>port</code><p> Порт подключения к серверу. При отсутствии параметра используется порт 80</p></li>
|
||||||
|
<li><code>conn</code><p> Максимальное количество открытых соединений. При отсутствии параметра используется значение 10</p></li>
|
||||||
|
<li><code>work_dir</code><p> Директория для размещения статичных файлов сервера, является корнем для uri путей. Параметр обязателен для заполнения </p></li>
|
||||||
|
<li><code>mime_file</code><p> Путь до файла сопоставления mime типов. Если параметр не указан используется встроенная таблица соответствия.</p></li>
|
||||||
|
<li><code>modules_dir</code><p> Директория, относительно которой в разделе [MODULES] указываются модули расширения.</p></li>
|
||||||
|
<li><code></code><p> </p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>[MODULES]</code>
|
||||||
|
<p> Данный раздел может содержать множество элементов, представленных в виде: <br>
|
||||||
|
<code>uri_path=file_name;cmdline</code> , где </p>
|
||||||
|
<ul>
|
||||||
|
<li><b>uri_path</b> - uri путь ресурса без начального "/" </li>
|
||||||
|
<li><b>file_name</b> - путь к файлу модуля, относительно "modules_dir"</li>
|
||||||
|
<li><b>cmdline</b> - Строка передаваемая модулю во время инициализации каждого ресурса, ассоциированного с ним</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><code>[TLS]</code>
|
||||||
|
<p>Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>mbedtls</code><p> Полный путь до библиотеки MbedTLS.</p></li>
|
||||||
|
<li><code>ca_cer</code><p> Полный путь до файла корневого сертификата.</p></li>
|
||||||
|
<li><code>srv_crt</code><p> Полный путь до файла сертификата сервера.</p></li>
|
||||||
|
<li><code>srv_key</code><p> Полный путь до файла содержащего секретный ключ сервера</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в
|
||||||
|
этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается
|
||||||
|
полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.</p>
|
||||||
|
<p>Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не
|
||||||
|
использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола,
|
||||||
|
в незащищённой среде передачи данных.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- АПИ модулей -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="api">Документация на API модулей</h2>
|
||||||
|
<p>
|
||||||
|
Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически.
|
||||||
|
По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li><code>uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline)</code>
|
||||||
|
<p> Функция для инициализации ресурса(uri_path), ассоциированного с модулем .
|
||||||
|
В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например
|
||||||
|
|
||||||
|
<code> test3=test_unit4.obj; -database="file.sqlite" </code>
|
||||||
|
|
||||||
|
При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.
|
||||||
|
</p>
|
||||||
|
<p> Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata)</code>
|
||||||
|
<p>
|
||||||
|
Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт
|
||||||
|
в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса.
|
||||||
|
</p>
|
||||||
|
<p> В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста.
|
||||||
|
Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall httpd_close(uint32_t pdata)</code>
|
||||||
|
<p> Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в
|
||||||
|
модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение,
|
||||||
|
возвращённое функцией "httpd_init".</p>
|
||||||
|
<p> Завершение работы сервера производится вызовом экспортируемой функции "close_server".</p>
|
||||||
|
<p> Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на
|
||||||
|
подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои
|
||||||
|
данные. После завершения всех модулей сервер полностью завершает свою работу.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h3>Создание ответа на запрос</h3>
|
||||||
|
<p> Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции,
|
||||||
|
позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос.
|
||||||
|
</p>
|
||||||
|
<p>Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>RESPD* __stdcall create_resp(CONNECT_DATA* session, uint32_t flags);</code>
|
||||||
|
<p> Функция создаёт объект RESPD, который имеет базовые настройки:</p>
|
||||||
|
<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Параметр</th><th>Значение</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Статус ответа</th><th>"200"</th> </tr>
|
||||||
|
<tr><th>Версия протокола</th><th>"HTTP/1.1 "</th></tr>
|
||||||
|
<tr><th>Content-type</th><th>"text/html"</th></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> Также разработчик может указать битовые флаги конфигурации ответа, например следующие:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>FLAG_TRANSFER_CHUNKED</code>
|
||||||
|
<p>Этот флаг выбирает "chunked" тип передачи данных с сервера к клиенту, что позволяет отправлять данные
|
||||||
|
неограниченной или неизвестной длины. </p></li>
|
||||||
|
<li><code>FLAG_RAW_STREAM</code>
|
||||||
|
<p>Этот флаг позволяет отправлять тело ответа небольшими пакетами, что можно использовать потоковую передачу
|
||||||
|
данных поверх http протокола, например для реализации интернет радио</p></li>
|
||||||
|
<li><code>FLAG_NO_CACHE_CONTROL</code>
|
||||||
|
<p>Этот флаг указывает, что в ответе не будет дефолтного заголовка "Cache-Control"</p></li>
|
||||||
|
<li><code>FLAG_KEEP_ALIVE</code>
|
||||||
|
<p>Этот флаг указывает, что в ответе будет дефолтный заголовок "Connection: keep-alive"</p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall destruct_resp(RESPD* ptr);</code>
|
||||||
|
<p>Функция производит удаление объекта RESPD.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall set_http_status(RESPD* ptr, uint32_t status); </code>
|
||||||
|
<p>Функция производит изменение статуса ответа. Статус записывается в виде строки вида "201 " упакованной в dword(0x20313032).</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall set_http_ver(RESPD* ptr, char* version, uint32_t length);</code>
|
||||||
|
<p>Функция производит изменение версии, отправляемой в ответе. Версия должна иметь вид строки, например "RTSP/1.1"</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall add_http_header(RESPD* ptr, char* ptr_header, uint32_t length);</code>
|
||||||
|
<p>Функция производит добавление новых заголовков в виде стоки. Функция не производит проверки содержимого строки.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall del_http_header(RESPD* ptr, char* ptr_header);</code>
|
||||||
|
<p>Функция производит удаление дополнительного заголовка. Память под строку никак не изменяется.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall begin_send_resp(RESPD* ptr, uint64_t content_length); </code>
|
||||||
|
<p>Функция производит отправку HTTP строки статуса и заголовков для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall send_resp(RESPD* ptr, char* content, uint32_t length); </code>
|
||||||
|
<p>Функция производит отправку http ответа целиком или его части для флагов FLAG_TRANSFER_CHUNKED и FLAG_RAW_STREAM .</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall finish_send_resp(RESPD* ptr);</code>
|
||||||
|
<p>Функция производит завершение отправки данных для флагов FLAG_TRANSFER_CHUNKED</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать
|
||||||
|
до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки.
|
||||||
|
</p>
|
||||||
|
<h3>Обработка данных запроса </h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>char* __stdcall find_uri_arg(CONNECT_DATA* session, char* key); </code>
|
||||||
|
<p>Функция производит поиск аргумента uri строки по его названию. Если аргумент найден, то возвращается указатель на
|
||||||
|
строку с его значением, иначе ноль</p>
|
||||||
|
</li>
|
||||||
|
<li><code>char* __stdcall find_header(CONNECT_DATA* session, char* key);</code>
|
||||||
|
<p>Функция производит поиск http заголовка по его названию. Если аргумент найден, то возвращается указатель на
|
||||||
|
строку с его значением, иначе ноль</p>
|
||||||
|
</li>
|
||||||
|
<p>Для получения остальной информации, такой как: метод запроса, версии протокола, фрагмент uri строки и тело сообщения;
|
||||||
|
используется доступ к структуре CONNECT_DATA. Описание этой структуры есть в файле modules_api.inc репозитория.</p>
|
||||||
|
</ul>
|
||||||
|
<h3>Работа с файлами</h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>void __stdcall FileInitFILED(FILED* buffer, char* path);</code>
|
||||||
|
<p> Функция производит инициализацию структуры FILED для её использования в файловых операциях.</p>
|
||||||
|
</li>
|
||||||
|
<li><code>FS_STATUS __stdcall FileInfo(char* path, void* buffer);</code>
|
||||||
|
<p> Функция производит чтение информации о файле в буфер по его пути и возвращает код ответа файловой системы.
|
||||||
|
Если возвращён 0 - операция выполнена успешно, иначе возникла ошибка.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall FileRead(FILED* file, void* buffer, uint32_t size);</code>
|
||||||
|
<p> Функция производит чтение части файла и автоматически увеличивает смещение чтение на количество прочитанных байт.
|
||||||
|
По завершению чтения функция вернёт количество прочитанных байт в буфер, при ошибках чтение это значение равно нулю.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li><code>void __stdcall FileSetOffset(FILED* file, uint64_t offset);</code>
|
||||||
|
<p> Функция изменяет смещения чтения из файла. </p>
|
||||||
|
</li>
|
||||||
|
<li><code>uint32_t __stdcall FileReadOfName(char* path, void* buffer, uint32_t size)</code>
|
||||||
|
<p> Функция производит чтение файла по его названию начиная с нулевого смещения. Может использоваться для работы с небольшими
|
||||||
|
файлами с различными настройками модуля. Функция возвращает количество прочитанных байт, если же возвращён 0, то вероятно
|
||||||
|
произошла ошибка чтения.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Управление сервером</h3>
|
||||||
|
<code>void close_server();</code>
|
||||||
|
<p> Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер
|
||||||
|
блокирует все новые подключения, позволяя модулям завершить открытые соединения.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Дополнительные функции</h3>
|
||||||
|
<code>char* __stdcall Get_MIME_Type(FILED* fd);</code>
|
||||||
|
<p> Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла.
|
||||||
|
Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого <a href="#MIME-macro">файла</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Дополнительные средства -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="other-soft">Дополнительные программы и средства</h2>
|
||||||
|
<h3 id="MIME-macro">Генератор файла MIME типов</h3>
|
||||||
|
<p>Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине
|
||||||
|
у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm,
|
||||||
|
позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы.
|
||||||
|
</p>
|
||||||
|
<p> Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос.
|
||||||
|
Последовательность передаваемых параметров в макрос следующая:
|
||||||
|
<ol>
|
||||||
|
<li>Строка с MIME типом, который должен использоваться если не один другой тип не подходит</li>
|
||||||
|
<li>Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf",
|
||||||
|
а после неё строка с MIME типом.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<h3>Что-то</h3>
|
||||||
|
|
||||||
|
<!-- Баги -->
|
||||||
|
<hr>
|
||||||
|
<h2 id="Bugs">Известные баги и особенности</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Сетевой стек нестабилен и что-то может пойти не так.</li>
|
||||||
|
<li>При отправки больших объёмов данных может быть утеря или изменение порядка пакетов</li>
|
||||||
|
<li>Сервер пока не умеет обрабатывать %XX символы в пути до ресурса</li>
|
||||||
|
<li>Сервер не рассчитан на большие нагрузки</li>
|
||||||
|
<li>Все пути в конфигурации сервера должны быть в ascii и без русских символов</li>
|
||||||
|
<li>Отсутствует поддержка TLS</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<!-- Авторы -->
|
||||||
|
<hr>
|
||||||
|
<footer id="Autor">
|
||||||
|
<p>Автор: Махаил Фролов aka Doczom</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -33,7 +33,6 @@ unit_init:
|
|||||||
xor eax, eax
|
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
|
|
||||||
|
|
||||||
cmp dword[esi + IMPORT_DATA.version], API_VERSION
|
cmp dword[esi + IMPORT_DATA.version], API_VERSION
|
||||||
jne .exit
|
jne .exit
|
||||||
@@ -68,7 +67,7 @@ server_entry:
|
|||||||
cmp dword[edx], 'new'
|
cmp dword[edx], 'new'
|
||||||
je .no_del
|
je .no_del
|
||||||
|
|
||||||
cmp dword[edx], 'del'
|
;cmp dword[edx], 'del'
|
||||||
|
|
||||||
mov dword[text_message], ' '
|
mov dword[text_message], ' '
|
||||||
mov dword[text_message + 4], ' '
|
mov dword[text_message + 4], ' '
|
||||||
@@ -117,7 +116,6 @@ server_entry:
|
|||||||
rep movsd
|
rep movsd
|
||||||
pop edi esi
|
pop edi esi
|
||||||
|
|
||||||
mov [esi + CONNECT_DATA.buffer_response], eax
|
|
||||||
; copy message
|
; copy message
|
||||||
mov ecx, [text_message]
|
mov ecx, [text_message]
|
||||||
mov [eax + sceleton_resp.message], ecx
|
mov [eax + sceleton_resp.message], ecx
|
||||||
@@ -150,12 +148,24 @@ server_entry:
|
|||||||
; set httpcode
|
; set httpcode
|
||||||
mov dword[edi + sceleton_resp.code], '200 '
|
mov dword[edi + sceleton_resp.code], '200 '
|
||||||
; send http message
|
; 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 sceleton_resp.size
|
||||||
push edi
|
push edi
|
||||||
push dword[esi + CONNECT_DATA.socket]
|
push eax
|
||||||
call [IMPORT.netfunc_send]
|
call [IMPORT.send_resp]
|
||||||
|
|
||||||
|
push esi
|
||||||
|
call [IMPORT.destruct_resp]
|
||||||
|
|
||||||
|
push edi
|
||||||
|
call [IMPORT.Free]
|
||||||
|
|
||||||
board_input 'send'
|
board_input 'send'
|
||||||
.exit:
|
.exit:
|
||||||
@@ -173,8 +183,6 @@ _10: dd 10
|
|||||||
|
|
||||||
count_call dd 0
|
count_call dd 0
|
||||||
|
|
||||||
import_httpd: dd 0
|
|
||||||
|
|
||||||
sceleton_resp:
|
sceleton_resp:
|
||||||
db 'HTTP/1.0 '
|
db 'HTTP/1.0 '
|
||||||
.code = $ - sceleton_resp
|
.code = $ - sceleton_resp
|
||||||
|
177
file_server.inc
177
file_server.inc
@@ -1,7 +1,7 @@
|
|||||||
; This is a module for processing standard requests to get a file along
|
; This is a module for processing standard requests to get a file along
|
||||||
; a path that does not belong to another module.
|
; a path that does not belong to another module.
|
||||||
|
|
||||||
SIZE_FILE_BUFFER = 64*1024
|
SIZE_FILE_BUFFER = 1400*23;64*1024
|
||||||
|
|
||||||
file_server:
|
file_server:
|
||||||
|
|
||||||
@@ -37,12 +37,8 @@ file_server:
|
|||||||
; for code stack
|
; for code stack
|
||||||
lea edx, [esp - 6*1024 - 4096] ; edx <- buffer for full path
|
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
|
push esi edi
|
||||||
|
mov eax, esi
|
||||||
;; copy work_dir
|
;; copy work_dir
|
||||||
mov esi, GLOBAL_DATA.work_dir
|
mov esi, GLOBAL_DATA.work_dir
|
||||||
mov edi, edx
|
mov edi, edx
|
||||||
@@ -55,24 +51,22 @@ file_server:
|
|||||||
cmp byte[esi - 1], 0
|
cmp byte[esi - 1], 0
|
||||||
jne @b
|
jne @b
|
||||||
|
|
||||||
mov eax, edi
|
|
||||||
dec eax
|
|
||||||
pop edi esi
|
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)
|
;; check file info (skip of directory and if syscall return error)
|
||||||
lea eax, [edi - 40] ; buffer for file info
|
lea eax, [edi - 40] ; buffer for file info
|
||||||
mov [edi + FILED.buffer], eax
|
|
||||||
|
|
||||||
push edi
|
stdcall FileInfo, edx, eax
|
||||||
call FileInfo
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .err_not_found
|
jnz .err_not_found
|
||||||
|
|
||||||
test dword[edi - 40], 11000b ; check dir OR disk partition
|
test dword[edi - 40], 11000b ; check dir OR disk partition
|
||||||
jnz .err_not_found
|
jnz .err_not_found
|
||||||
|
|
||||||
|
|
||||||
; check method OPTIONS
|
; check method OPTIONS
|
||||||
mov ecx, [esi + CONNECT_DATA.http_method]
|
mov ecx, [esi + CONNECT_DATA.http_method]
|
||||||
cmp dword[ecx], 'OPTI'
|
cmp dword[ecx], 'OPTI'
|
||||||
@@ -89,135 +83,61 @@ file_server:
|
|||||||
jne .err_http_501
|
jne .err_http_501
|
||||||
|
|
||||||
.send_file:
|
.send_file:
|
||||||
; create http response (set 200 code, MINE type and length of body)
|
; edi -> FILED
|
||||||
;; alloc 33 kib
|
; edi-40 ->FILEINFO
|
||||||
push dword SIZE_FILE_BUFFER
|
; esi -> CONNECT_DATA
|
||||||
call Alloc
|
stdcall create_resp, esi, FLAG_NO_CONTENT_TYPE\
|
||||||
|
+ FLAG_RAW_STREAM
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_http_501 ; error memory
|
jz .err_http_501
|
||||||
|
mov ebp, eax
|
||||||
|
|
||||||
push esi
|
stdcall Alloc, SIZE_FILE_BUFFER
|
||||||
push edi
|
test eax, eax
|
||||||
push eax ; save pointer for Free
|
jz .err_http_501_1
|
||||||
|
|
||||||
mov esi, base_response
|
; Add content type header
|
||||||
mov ecx, response.body
|
push eax esi edi
|
||||||
mov edi, [esp]
|
mov esi, default_http_cont_type
|
||||||
|
mov edi, eax
|
||||||
|
mov ecx, default_http_cont_type.length
|
||||||
rep movsb
|
rep movsb
|
||||||
|
|
||||||
mov edi, [esp]
|
mov dword[eax + default_http_cont_type.value], ' '
|
||||||
mov dword[edi + response.code], '200 '
|
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]
|
||||||
|
|
||||||
mov dword[edi + response.connection], 'keep'
|
stdcall Get_MIME_Type, [esp]
|
||||||
mov dword[edi + response.connection + 4], '-ali'
|
|
||||||
mov word[edi + response.connection + 8], 've'
|
|
||||||
|
|
||||||
|
|
||||||
push dword[esp + 4] ; <-FILED
|
|
||||||
call Get_MIME_Type
|
|
||||||
|
|
||||||
add edi, response.content_type
|
|
||||||
mov esi, eax
|
mov esi, eax
|
||||||
@@:
|
@@:
|
||||||
movsb
|
movsb
|
||||||
cmp byte[esi], 0
|
cmp byte[esi], 0
|
||||||
jne @b
|
jne @b
|
||||||
|
pop edi esi ;!!!!! "pop eax" not runing
|
||||||
|
|
||||||
|
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 edi ; buffer on 32 kib
|
stdcall begin_send_resp, ebp, [edi - 40 + 32], [edi - 40 + 36]
|
||||||
pop ebx ; FD
|
;cmp eax, -1
|
||||||
pop esi ; CONNECT_DATA
|
.send_block_file:
|
||||||
|
mov eax, [esp] ; allocated buffer
|
||||||
; copy length
|
stdcall FileRead, edi, eax, SIZE_FILE_BUFFER
|
||||||
mov edx, [ebx - 40 + 36]
|
|
||||||
mov eax, [ebx - 40 + 32]
|
|
||||||
lea ecx, [edi + response.content_len + 21]
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jne @f
|
jz .finish_send_file
|
||||||
test edx, edx
|
|
||||||
jz .err_not_found_1
|
|
||||||
@@:
|
|
||||||
cmp edx, 1000 ; 999*4 - max length of file
|
|
||||||
jae .err_not_found_1
|
|
||||||
; edx:eax ecx - end char in string '000000'
|
|
||||||
.div1000:
|
|
||||||
div dword[_DIV_1000_]
|
|
||||||
push eax
|
|
||||||
|
|
||||||
mov eax, edx
|
mov ecx, [esp]
|
||||||
xor edx, edx
|
stdcall send_resp, ebp, ecx, eax
|
||||||
;.div100:
|
;cmp eax, -1
|
||||||
div dword[_DIV_100_]
|
jmp .send_block_file
|
||||||
push eax
|
|
||||||
|
|
||||||
mov eax, edx
|
.finish_send_file:
|
||||||
xor edx, edx
|
stdcall Free
|
||||||
div dword[_DIV_10_]
|
stdcall finish_send_resp, ebp
|
||||||
add byte[ecx], dl
|
stdcall destruct_resp, ebp
|
||||||
add byte[ecx - 1], al
|
|
||||||
sub ecx, 3
|
|
||||||
|
|
||||||
pop eax
|
|
||||||
add byte[ecx + 1], al
|
|
||||||
;xor edx, edx
|
|
||||||
;test eax, eax
|
|
||||||
;jne .div100
|
|
||||||
pop eax
|
|
||||||
xor edx, edx
|
|
||||||
test eax, eax
|
|
||||||
jne .div1000
|
|
||||||
|
|
||||||
;send_response_header
|
|
||||||
push dword 0 ; flags
|
|
||||||
push response.body
|
|
||||||
push edi
|
|
||||||
push dword[esi + CONNECT_DATA.socket]
|
|
||||||
call netfunc_send
|
|
||||||
cmp eax, -1
|
|
||||||
je .exit_free
|
|
||||||
|
|
||||||
mov dword[ebx + FILED.offset], 0
|
|
||||||
mov dword[ebx + FILED.offset + 4], 0
|
|
||||||
mov [ebx + FILED.buffer], edi
|
|
||||||
mov [ebx + FILED.size], SIZE_FILE_BUFFER
|
|
||||||
.send_response_body:
|
|
||||||
; read 32 kib to file
|
|
||||||
push ebx
|
|
||||||
call FileRead
|
|
||||||
test eax, eax
|
|
||||||
jz @f
|
|
||||||
cmp eax, 6
|
|
||||||
|
|
||||||
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
|
ret
|
||||||
|
|
||||||
.send_options:
|
.send_options:
|
||||||
@@ -230,9 +150,6 @@ file_server:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.err_not_found_1:
|
|
||||||
push edi
|
|
||||||
call Free
|
|
||||||
.err_not_found:
|
.err_not_found:
|
||||||
; send error 404
|
; send error 404
|
||||||
push dword 0 ; flags
|
push dword 0 ; flags
|
||||||
@@ -242,7 +159,8 @@ file_server:
|
|||||||
call netfunc_send
|
call netfunc_send
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
.err_http_501_1:
|
||||||
|
stdcall Free, ebp
|
||||||
.err_http_501:
|
.err_http_501:
|
||||||
; send error 501
|
; send error 501
|
||||||
push dword 0 ; flags
|
push dword 0 ; flags
|
||||||
@@ -253,7 +171,6 @@ file_server:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
; char* stdcall Get_MIME_Type(FILED* fd); //path is ASCIIZ string
|
; char* stdcall Get_MIME_Type(FILED* fd); //path is ASCIIZ string
|
||||||
Get_MIME_Type:
|
Get_MIME_Type:
|
||||||
push esi edi
|
push esi edi
|
||||||
|
29
httpd.asm
29
httpd.asm
@@ -4,7 +4,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; httpd - Simple http server for Kolibri OS. ;
|
; 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
|
jz @f
|
||||||
|
|
||||||
mov ecx, PATH
|
mov ecx, PATH
|
||||||
|
; TODO: add check ""
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
; get settings
|
; get settings
|
||||||
@@ -96,7 +97,7 @@ START:
|
|||||||
.sock_err:
|
.sock_err:
|
||||||
mcall -1
|
mcall -1
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
|
||||||
thread_connect:
|
thread_connect:
|
||||||
sub esp, sizeof.CONNECT_DATA
|
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_modules_dir db 'modules_dir',0
|
||||||
ini_key_mime_file db 'mime_file',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_init db 'httpd_init',0
|
||||||
httpd_module_serv db 'httpd_serv',0
|
httpd_module_serv db 'httpd_serv',0
|
||||||
httpd_module_close db 'httpd_close',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_listen
|
||||||
dd netfunc_recv
|
dd netfunc_recv
|
||||||
dd netfunc_send
|
dd netfunc_send
|
||||||
dd FileInfo
|
|
||||||
dd FileRead
|
|
||||||
dd Alloc
|
dd Alloc
|
||||||
dd Free
|
dd Free
|
||||||
dd parse_http_query ; no stdcall
|
dd parse_http_query ; no stdcall
|
||||||
|
|
||||||
|
dd FileInitFILED
|
||||||
|
dd FileInfo
|
||||||
|
dd FileRead
|
||||||
|
dd FileSetOffset
|
||||||
|
dd FileReadOfName
|
||||||
|
|
||||||
dd send_resp
|
dd send_resp
|
||||||
dd create_resp
|
dd create_resp
|
||||||
dd destruct_resp
|
dd destruct_resp
|
||||||
@@ -292,13 +302,14 @@ EXPORT_DATA: ; in modules for this table using struct IMPORT_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 begin_send_resp
|
dd begin_send_resp
|
||||||
dd finish_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
|
dd GLOBAL_DATA
|
||||||
.size = $ - EXPORT_DATA ; (count func)*4 + size(api ver) + 4
|
.size = $ - EXPORT_DATA ; (count func)*4 + size(api ver) + 4
|
||||||
dd 0
|
dd 0
|
||||||
@@ -307,6 +318,8 @@ EXPORT_DATA: ; in modules for this table using struct IMPORT_DATA
|
|||||||
;UDATA
|
;UDATA
|
||||||
srv_stop: rd 1 ; set 1 for skip new connections
|
srv_stop: rd 1 ; set 1 for skip new connections
|
||||||
srv_shutdown: rd 1 ; set 1 for ending working server
|
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_backlog: rd 1 ; maximum number of simultaneous open connections
|
||||||
|
|
||||||
srv_socket: rd 1
|
srv_socket: rd 1
|
||||||
|
@@ -52,22 +52,6 @@
|
|||||||
;serv_header:
|
;serv_header:
|
||||||
; .Accept_Ranges db 'Accept-Ranges: bytes',13,10
|
; .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 '<html>'
|
|
||||||
; db '<title>Error 404</title>'
|
|
||||||
; db '<center>'
|
|
||||||
; db 'Error 404 <br>'
|
|
||||||
; db 'The server could not find the requested page.<br><br>'
|
|
||||||
; db '</center>'
|
|
||||||
; db '</html>',0
|
|
||||||
|
|
||||||
;http_err_response:
|
;http_err_response:
|
||||||
; db 'HTTP/1.1 '
|
; db 'HTTP/1.1 '
|
||||||
;.code = $ - http_err_response
|
;.code = $ - http_err_response
|
||||||
@@ -97,7 +81,9 @@ default_http_cont_encod:
|
|||||||
.length = $ - default_http_cont_encod
|
.length = $ - default_http_cont_encod
|
||||||
|
|
||||||
default_http_cont_type:
|
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
|
.length = $ - default_http_cont_type
|
||||||
|
|
||||||
default_http_cache_ctl:
|
default_http_cache_ctl:
|
||||||
@@ -153,35 +139,6 @@ http_response_options:
|
|||||||
.size = $ - 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
|
; min HTTP request size
|
||||||
; "GET / HTTP/1.1" - 18 byte
|
; "GET / HTTP/1.1" - 18 byte
|
||||||
min_http_size = 18
|
min_http_size = 18
|
||||||
|
4
makefile
4
makefile
@@ -5,7 +5,7 @@ examples=$(wildcard example/*.asm)
|
|||||||
examples_obj=$(patsubst %.asm,%.obj,$(examples))
|
examples_obj=$(patsubst %.asm,%.obj,$(examples))
|
||||||
|
|
||||||
|
|
||||||
all: build-main build-mime $(examples_obj)
|
all: build-main build-mime $(examples_obj) copy_docs
|
||||||
|
|
||||||
|
|
||||||
build-main:
|
build-main:
|
||||||
@@ -17,3 +17,5 @@ build-mime:
|
|||||||
example/%.obj: example/%.asm
|
example/%.obj: example/%.asm
|
||||||
fasm $< $(OUTPUT_MODULES)/$(notdir $(basename $@)).obj
|
fasm $< $(OUTPUT_MODULES)/$(notdir $(basename $@)).obj
|
||||||
|
|
||||||
|
copy_docs:
|
||||||
|
cp -R doc/* $(OUTPUT_DIR)/server_data/docs
|
@@ -27,18 +27,28 @@ struct CONNECT_DATA ; 16*4 = 64 bytes
|
|||||||
end_buffer_request dd 0 ; для парсера
|
end_buffer_request dd 0 ; для парсера
|
||||||
buffer_response dd 0 ; pointer to buffwr for resp message
|
buffer_response dd 0 ; pointer to buffwr for resp message
|
||||||
http_method dd 0 ; указатель на строку
|
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
|
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_scheme dd 0 ; указатель на схему
|
||||||
uri_authority dd 0 ; pointer to struct ?
|
uri_authority dd 0 ; pointer to struct ?
|
||||||
uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров)
|
uri_path dd 0 ; указатель на декодированный путь к ресурсу(без параметров)
|
||||||
num_uri_args 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 ; указатель на строку
|
uri_fragment dd 0 ; указатель на строку
|
||||||
message_body dd 0 ; указатель на тело http запроса
|
message_body dd 0 ; указатель на тело http запроса
|
||||||
ends
|
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
|
struct IMPORT_DATA
|
||||||
version rd 1 ; dword for check api
|
version rd 1 ; dword for check api
|
||||||
@@ -50,11 +60,21 @@ struct IMPORT_DATA
|
|||||||
netfunc_listen rd 1
|
netfunc_listen rd 1
|
||||||
netfunc_recv rd 1
|
netfunc_recv rd 1
|
||||||
netfunc_send rd 1
|
netfunc_send rd 1
|
||||||
FileInfo rd 1
|
|
||||||
FileRead rd 1
|
|
||||||
Alloc rd 1
|
Alloc rd 1
|
||||||
Free rd 1
|
Free rd 1
|
||||||
parse_http_query rd 1 ; not standart calling, not using this function
|
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 rd 1
|
||||||
; send_resp(RESPD* ptr, char* content, uint32_t length);
|
; send_resp(RESPD* ptr, char* content, uint32_t length);
|
||||||
create_resp rd 1
|
create_resp rd 1
|
||||||
@@ -72,17 +92,19 @@ struct IMPORT_DATA
|
|||||||
set_http_ver rd 1
|
set_http_ver rd 1
|
||||||
; void set_http_ver(RESPD* ptr, char* version, uint32_t length);
|
; void set_http_ver(RESPD* ptr, char* version, uint32_t length);
|
||||||
; example: 'RTSP/1.1'
|
; 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
|
begin_send_resp rd 1
|
||||||
;uint32_t begin_send_resp(RESPD* ptr, uint64_t content_length);
|
;uint32_t begin_send_resp(RESPD* ptr, uint64_t content_length);
|
||||||
finish_send_resp rd 1
|
finish_send_resp rd 1
|
||||||
;uint32_t finish_send_resp(RESPD* ptr);
|
;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
|
GLOBAL_DATA rd 1
|
||||||
ends
|
ends
|
38
settings.inc
38
settings.inc
@@ -40,6 +40,7 @@ load_settings:
|
|||||||
|
|
||||||
mov dword[srv_stop], 0
|
mov dword[srv_stop], 0
|
||||||
mov dword[srv_shutdown], 0
|
mov dword[srv_shutdown], 0
|
||||||
|
mov dword[srv_tls_enable], 0
|
||||||
|
|
||||||
sub esp, 16
|
sub esp, 16
|
||||||
mov esi, esp
|
mov esi, esp
|
||||||
@@ -71,7 +72,17 @@ load_settings:
|
|||||||
|
|
||||||
mov word[srv_sockaddr], AF_INET4
|
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
|
xchg al, ah
|
||||||
mov [srv_sockaddr.port], ax
|
mov [srv_sockaddr.port], ax
|
||||||
|
|
||||||
@@ -217,32 +228,28 @@ load_mime_file:
|
|||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
mov esi, eax
|
mov esi, eax
|
||||||
lea ecx, [eax + sizeof.FILED + 40]
|
invoke ini.get_str, ebp, ini_section_main, ini_key_mime_file, esi, 1024, 0
|
||||||
mov [esi + FILED.path], ecx
|
|
||||||
invoke ini.get_str, ebp, ini_section_main, ini_key_mime_file, ecx, 1024, 0
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .no_file
|
jnz .no_file
|
||||||
|
|
||||||
lea ecx, [esi + sizeof.FILED]
|
sub esp, 40
|
||||||
mov [esi + FILED.buffer], ecx
|
stdcall FileInfo, esi, esp
|
||||||
stdcall FileInfo, esi
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .no_file
|
jnz .no_file
|
||||||
|
|
||||||
mov ecx, [esi + sizeof.FILED + 32]
|
mov ecx, [esp + 32]
|
||||||
stdcall Alloc, ecx
|
stdcall Alloc, ecx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .no_file
|
jz .no_file
|
||||||
|
|
||||||
mov ecx, [esi + sizeof.FILED + 32]
|
mov ecx, [esp + 32]
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
mov [esi + FILED.buffer], eax
|
|
||||||
mov [esi + FILED.size], ecx
|
stdcall FileReadOfName, esi, edi, ecx
|
||||||
mov [esi + FILED.offset], 0
|
|
||||||
mov dword[esi + FILED.offset + 4], 0
|
|
||||||
stdcall FileRead, esi
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_read
|
jz .error_read
|
||||||
|
|
||||||
|
add esp, 40
|
||||||
|
|
||||||
mov dword[GLOBAL_DATA.MIME_types_arr], edi
|
mov dword[GLOBAL_DATA.MIME_types_arr], edi
|
||||||
mov eax, edi
|
mov eax, edi
|
||||||
@@ -258,6 +265,7 @@ load_mime_file:
|
|||||||
.error_read:
|
.error_read:
|
||||||
stdcall Free, edi
|
stdcall Free, edi
|
||||||
.no_file:
|
.no_file:
|
||||||
|
add esp, 40
|
||||||
stdcall Free, esi
|
stdcall Free, esi
|
||||||
.err:
|
.err:
|
||||||
mov dword[GLOBAL_DATA.MIME_types_arr], STD_MIME_TYPE_ARR
|
mov dword[GLOBAL_DATA.MIME_types_arr], STD_MIME_TYPE_ARR
|
||||||
|
131
sys_func.inc
131
sys_func.inc
@@ -187,36 +187,117 @@ Free:
|
|||||||
pop ebx
|
pop ebx
|
||||||
ret 4
|
ret 4
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
|
||||||
struct FILED
|
;FS_STATUS stdcall FileInfo(char* path, void* buffer)
|
||||||
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)
|
|
||||||
FileInfo:
|
FileInfo:
|
||||||
|
mov ecx, [esp + 4]
|
||||||
|
mov edx, [esp + 8]
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, [esp + 4*1 + 4]
|
sub esp, sizeof.FILED
|
||||||
mov dword[ebx], 5 ; file info
|
mov dword[esp + FILED.opcode], 5 ; file info
|
||||||
mov dword[ebx + FILED.offset + 4], 0 ; zero flag
|
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
|
mcall 70
|
||||||
|
add esp, sizeof.FILED
|
||||||
pop ebx
|
pop ebx
|
||||||
ret 4
|
ret 8
|
||||||
;NTSATTUS stdcall FileRead(FILED* file)
|
|
||||||
|
; 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:
|
FileRead:
|
||||||
|
|
||||||
|
mov eax, [esp + 4]
|
||||||
|
mov ecx, [esp + 8]
|
||||||
|
mov edx, [esp + 12]
|
||||||
|
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, [esp + 4*1 + 4]
|
mov [eax + FILED.opcode], 0
|
||||||
mov dword[ebx], 0 ; read file
|
mov [eax + FILED.size], edx
|
||||||
|
mov [eax + FILED.buffer], ecx
|
||||||
|
|
||||||
|
mov ebx, eax
|
||||||
mcall 70
|
mcall 70
|
||||||
|
|
||||||
|
test eax, eax
|
||||||
|
jz @f
|
||||||
|
cmp eax, 6 ; EOF
|
||||||
|
je @f
|
||||||
|
xor ebx, ebx
|
||||||
|
@@:
|
||||||
|
mov eax, ebx
|
||||||
|
|
||||||
pop 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)
|
;RESPD* stdcall create_resp(CONNECT_DATA* session, uint32_t flags)
|
||||||
@@ -355,7 +436,6 @@ send_resp:
|
|||||||
|
|
||||||
|
|
||||||
.chunked:
|
.chunked:
|
||||||
; TODO
|
|
||||||
mov eax, -1
|
mov eax, -1
|
||||||
mov ecx, [esp + 4*3 + 8] ; ptr
|
mov ecx, [esp + 4*3 + 8] ; ptr
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
@@ -388,8 +468,8 @@ send_resp:
|
|||||||
call netfunc_send
|
call netfunc_send
|
||||||
add esp, 2+8
|
add esp, 2+8
|
||||||
|
|
||||||
cmp eax, -1
|
;cmp eax, -1
|
||||||
jz .exit
|
;jz .exit
|
||||||
|
|
||||||
; send content
|
; send content
|
||||||
mov ecx, [esp + 4*3 + 8] ; ptr
|
mov ecx, [esp + 4*3 + 8] ; ptr
|
||||||
@@ -401,8 +481,8 @@ send_resp:
|
|||||||
push dword[eax + CONNECT_DATA.socket]
|
push dword[eax + CONNECT_DATA.socket]
|
||||||
call netfunc_send
|
call netfunc_send
|
||||||
|
|
||||||
cmp eax, -1
|
;cmp eax, -1
|
||||||
jz .exit
|
;jz .exit
|
||||||
|
|
||||||
; send db 13, 10
|
; send db 13, 10
|
||||||
push word 0x0a0d
|
push word 0x0a0d
|
||||||
@@ -415,6 +495,7 @@ send_resp:
|
|||||||
push dword[eax + CONNECT_DATA.socket]
|
push dword[eax + CONNECT_DATA.socket]
|
||||||
call netfunc_send
|
call netfunc_send
|
||||||
|
|
||||||
|
add esp, 2
|
||||||
pop ebp edi esi
|
pop ebp edi esi
|
||||||
ret 12
|
ret 12
|
||||||
|
|
||||||
@@ -712,7 +793,7 @@ finish_send_resp:
|
|||||||
.exit:
|
.exit:
|
||||||
ret 4
|
ret 4
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
;void close_server()
|
;void close_server()
|
||||||
; TODO: added free HTTPD_MODULE structures
|
; TODO: added free HTTPD_MODULE structures
|
||||||
close_server:
|
close_server:
|
||||||
|
@@ -9,7 +9,6 @@ macro table arg3, [arg1,arg2] {
|
|||||||
common
|
common
|
||||||
local ..other
|
local ..other
|
||||||
dd ..other
|
dd ..other
|
||||||
; <20><><EFBFBD> size = ($ - <20><><EFBFBD><EFBFBD><EFBFBD>) / 8
|
|
||||||
forward
|
forward
|
||||||
..x db ..x_end-..x - 1, arg1
|
..x db ..x_end-..x - 1, arg1
|
||||||
..x_end db arg2, 0
|
..x_end db arg2, 0
|
||||||
@@ -27,13 +26,47 @@ table 'application/octet-stream' ,\
|
|||||||
'.js', 'text/javascript' ,\
|
'.js', 'text/javascript' ,\
|
||||||
'.txt', 'text/plain; charset=utf-8' ,\
|
'.txt', 'text/plain; charset=utf-8' ,\
|
||||||
'.pdf', 'application/pdf' ,\
|
'.pdf', 'application/pdf' ,\
|
||||||
|
'.rtf', 'application/rtf' ,\
|
||||||
'.json', 'application/json' ,\
|
'.json', 'application/json' ,\
|
||||||
'.png', 'image/png' ,\
|
'.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' ,\
|
'.mp3', 'audio/mpeg' ,\
|
||||||
|
'.mid', 'audio/midi' ,\
|
||||||
|
'.midi', 'audio/midi' ,\
|
||||||
|
'.wav', 'audio/wav' ,\
|
||||||
|
'.weba', 'audio/webm' ,\
|
||||||
|
'.opus', 'audio/opus' ,\
|
||||||
|
'.oga', 'audio/ogg' ,\
|
||||||
|
\
|
||||||
'.mp4', 'video/mp4' ,\
|
'.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' ,\
|
'.gif', 'image/gif' ,\
|
||||||
|
'.avif', 'image/avif' ,\
|
||||||
'.webp', 'image/webp' ,\
|
'.webp', 'image/webp' ,\
|
||||||
'.svg', 'image/svg+xml' ,\
|
'.svg', 'image/svg+xml' ,\
|
||||||
'.apng', 'image/apng' ,\
|
'.apng', 'image/apng' ,\
|
||||||
|
'.tif', 'image/tiff' ,\
|
||||||
|
'.tiff', 'image/tiff' ,\
|
||||||
'.jpeg', 'image/jpeg' ,\
|
'.jpeg', 'image/jpeg' ,\
|
||||||
'.jpg', 'image/jpeg'
|
'.jpg', 'image/jpeg'
|
||||||
|
Reference in New Issue
Block a user