diff --git a/bin/httpd b/bin/httpd index cb5d053..5e42bd5 100644 Binary files a/bin/httpd and b/bin/httpd differ 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 72ac9a6..48f6046 100644 Binary files a/bin/mime_types.bin and b/bin/mime_types.bin differ diff --git a/bin/modules/srv_control.obj b/bin/modules/srv_control.obj index e853cda..538ee4a 100644 Binary files a/bin/modules/srv_control.obj and b/bin/modules/srv_control.obj differ diff --git a/bin/modules/test_unit.obj b/bin/modules/test_unit.obj index ba5b189..0fbb551 100644 Binary files a/bin/modules/test_unit.obj and b/bin/modules/test_unit.obj differ diff --git a/bin/modules/test_unit4.obj b/bin/modules/test_unit4.obj index 7773ac7..3b52e93 100644 Binary files a/bin/modules/test_unit4.obj and b/bin/modules/test_unit4.obj differ diff --git a/bin/modules/test_unit5.obj b/bin/modules/test_unit5.obj index 5367c5d..5ab89a5 100644 Binary files a/bin/modules/test_unit5.obj and b/bin/modules/test_unit5.obj differ diff --git a/bin/modules/test_unit_2.obj b/bin/modules/test_unit_2.obj index 3c73304..d655097 100644 Binary files a/bin/modules/test_unit_2.obj and b/bin/modules/test_unit_2.obj differ 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 основных раздела: +

    +
  1. + [MAIN] +

    Данный раздел содержит в себе базовые элементы конфигурации, такие как:

    + +
  2. +
  3. + [MODULES] +

    Данный раздел может содержать множество элементов, представленных в виде:
    + uri_path=file_name;cmdline , где

    + +
  4. +
  5. [TLS] +

    Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.

    + +

    Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в + этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается + полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.

    +

    Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не + использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола, + в незащищённой среде передачи данных.

    +
  6. +
+

+ + +
+

Документация на API модулей

+

+ Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически. + По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции: +

+
    +
  1. uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline) +

    Функция для инициализации ресурса(uri_path), ассоциированного с модулем . + В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например + + test3=test_unit4.obj; -database="file.sqlite" + + При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль. +

    +

    Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.

    +
  2. +
  3. void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata) +

    + Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт + в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса. +

    +

    В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста. + Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP. +

    +
  4. +
  5. void __stdcall httpd_close(uint32_t pdata) +

    Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в + модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение, + возвращённое функцией "httpd_init".

    +

    Завершение работы сервера производится вызовом экспортируемой функции "close_server".

    +

    Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на + подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои + данные. После завершения всех модулей сервер полностью завершает свою работу.

    +
  6. +
+

Создание ответа на запрос

+

Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции, + позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос. +

+

Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.

+ +

В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать + до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки. +

+

Обработка данных запроса

+ +

Работа с файлами

+ +

Управление сервером

+ void close_server(); +

Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер + блокирует все новые подключения, позволяя модулям завершить открытые соединения. +

+ +

Дополнительные функции

+ char* __stdcall Get_MIME_Type(FILED* fd); +

Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла. + Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого файла. +

+ + +
+

Дополнительные программы и средства

+

Генератор файла MIME типов

+

Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине + у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm, + позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы. +

+

Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос. + Последовательность передаваемых параметров в макрос следующая: +

    +
  1. Строка с MIME типом, который должен использоваться если не один другой тип не подходит
  2. +
  3. Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf", + а после неё строка с MIME типом. +
  4. +
+

+

Что-то

+ + +
+

Известные баги и особенности

+
    +
  1. Сетевой стек нестабилен и что-то может пойти не так.
  2. +
  3. При отправки больших объёмов данных может быть утеря или изменение порядка пакетов
  4. +
  5. Сервер пока не умеет обрабатывать %XX символы в пути до ресурса
  6. +
  7. Сервер не рассчитан на большие нагрузки
  8. +
  9. Все пути в конфигурации сервера должны быть в ascii и без русских символов
  10. +
  11. Отсутствует поддержка TLS
  12. +
+ + +
+ + + + \ 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 основных раздела: +

    +
  1. + [MAIN] +

    Данный раздел содержит в себе базовые элементы конфигурации, такие как:

    + +
  2. +
  3. + [MODULES] +

    Данный раздел может содержать множество элементов, представленных в виде:
    + uri_path=file_name;cmdline , где

    + +
  4. +
  5. [TLS] +

    Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.

    + +

    Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в + этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается + полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.

    +

    Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не + использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола, + в незащищённой среде передачи данных.

    +
  6. +
+

+ + +
+

Документация на API модулей

+

+ Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически. + По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции: +

+
    +
  1. uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline) +

    Функция для инициализации ресурса(uri_path), ассоциированного с модулем . + В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например + + test3=test_unit4.obj; -database="file.sqlite" + + При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль. +

    +

    Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.

    +
  2. +
  3. void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata) +

    + Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт + в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса. +

    +

    В этой функции модуль производит обработку запроса используя экспортируемые сервером функции и прямой доступ к некоторым полями структуры контекста. + Эти имеющиеся возможности позволяют реализовать максимально гибкую обработку запросов, в том числе для протоколов, производных от http, например RTSP. +

    +
  4. +
  5. void __stdcall httpd_close(uint32_t pdata) +

    Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в + модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение, + возвращённое функцией "httpd_init".

    +

    Завершение работы сервера производится вызовом экспортируемой функции "close_server".

    +

    Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на + подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои + данные. После завершения всех модулей сервер полностью завершает свою работу.

    +
  6. +
+

Создание ответа на запрос

+

Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции, + позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос. +

+

Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.

+ +

В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать + до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки. +

+

Обработка данных запроса

+ +

Работа с файлами

+ +

Управление сервером

+ void close_server(); +

Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер + блокирует все новые подключения, позволяя модулям завершить открытые соединения. +

+ +

Дополнительные функции

+ char* __stdcall Get_MIME_Type(FILED* fd); +

Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла. + Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого файла. +

+ + +
+

Дополнительные программы и средства

+

Генератор файла MIME типов

+

Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине + у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm, + позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы. +

+

Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос. + Последовательность передаваемых параметров в макрос следующая: +

    +
  1. Строка с MIME типом, который должен использоваться если не один другой тип не подходит
  2. +
  3. Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf", + а после неё строка с MIME типом. +
  4. +
+

+

Что-то

+ + +
+

Известные баги и особенности

+
    +
  1. Сетевой стек нестабилен и что-то может пойти не так.
  2. +
  3. При отправки больших объёмов данных может быть утеря или изменение порядка пакетов
  4. +
  5. Сервер пока не умеет обрабатывать %XX символы в пути до ресурса
  6. +
  7. Сервер не рассчитан на большие нагрузки
  8. +
  9. Все пути в конфигурации сервера должны быть в ascii и без русских символов
  10. +
  11. Отсутствует поддержка TLS
  12. +
+ + +
+ + + + \ 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'