Написание модулей
Module versions
---------------
Интерфейс между пользовательскими модулями и kernel-space
TUX-подсистемой зависит от версии .
Версия включает в себя 3 константы : TUX_MAJOR_VERSION,
TUX_MINOR_VERSION, TUX_PATCHLEVEL_VERSION
Поддержка HTTP версий
-----------------------
Поддерживаются версии HTTP 1.0 и 1.1:
typedef enum http_versions {
HTTP_1_0,
HTTP_1_1
} http_version_t;
Версия клиента может быть найдена в req->http_version.
HTTP методы
------------
HTTP-метод со стороны клиента может быть найден в req->http_method:
typedef enum http_methods {
METHOD_NONE,
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
METHOD_PUT
} http_method_t;
TUX actions
-----------
Следующие 'actions' системы TUX перечислены ниже:
enum user_req {
TUX_ACTION_STARTUP = 1,
TUX_ACTION_SHUTDOWN = 2,
TUX_ACTION_STARTTHREAD = 3,
TUX_ACTION_STOPTHREAD = 4,
TUX_ACTION_EVENTLOOP = 5,
TUX_ACTION_GET_OBJECT = 6,
TUX_ACTION_SEND_OBJECT = 7,
TUX_ACTION_READ_OBJECT = 8,
TUX_ACTION_FINISH_REQ = 9,
TUX_ACTION_REGISTER_MODULE = 10,
TUX_ACTION_UNREGISTER_MODULE = 11,
TUX_ACTION_CURRENT_DATE = 12,
MAX_TUX_ACTION
};
TUX_ACTION_STARTTHREAD (3):
- Текущий процесс используется как новый TUX thread.
При этом req->thread_nr должен быть уникальным.
TUX_ACTION_STOPTHREAD (4):
- Де-регистрация текущего TUX thread.
TUX_ACTION_EVENTLOOP (5):
- Модуль дает команду для TUX войти в цикл ожидания.
TUX будет ждать входящий запрос или сигнал .
TUX_ACTION_GET_OBJECT (6):
- Доступ к TUX-обьекту , имеющему в качестве идентификатора
строку req->objectname .
Обычно это файл.
TUX_ACTION_SEND_OBJECT (7):
- Отсылка обьекта на сторону клиента
TUX_ACTION_READ_OBJECT (8):
- Чтение в буфер обьекта , имеющего идентификатор req->object_addr.
TUX_ACTION_FINISH_REQ (9):
- Сигнал для TUX о том , что модуль закончил обработку запроса .
TUX_ACTION_REGISTER_MODULE (10):
- регистрация пользовательского модуля , имеющего
в качестве идентификатора строку req->modulename.
TUX_ACTION_UNREGISTER_MODULE (11):
- Un-регистрация пользовательского модуля
TUX_ACTION_CURRENT_DATE (12):
- Установка новой строки формата day/time для TUX как req->new_date.
TUX и возвращаемые коды
---------------------------------------
Когда пользовательский модуль вызывает TUX , возвращается целое число.
Если оно отрицательное - значит , произошла ошибка .
Положительное число может быть интерпретировано как :
enum http_ret {
TUX_RETURN_USERSPACE_REQUEST = 0,
TUX_RETURN_EXIT = 1,
TUX_RETURN_SIGNAL = 2,
};
TUX_RETURN_USERSPACE_REQUEST:
- новый пользовательский запрос
TUX_RETURN_EXIT:
- Выход TUX
TUX_RETURN_SIGNAL:
- Получен сигнал
Constants
---------
#define MAX_MODULENAME_LEN 16
Максимальная длина имени модуля
#define MAX_URI_LEN 256
Максимальная длина URI
#define MAX_POST_DATA 1024
Максимальная длина входящего буфера
#define MAX_COOKIE_LEN 128
Максимальная длина куки
Структура запроса
---------------------
Структура user-space request - основная для обмена
с kernel-space TUX subsystem.
typedef struct user_req_s {
int version_major;
int version_minor;
int version_patch;
int http_version;
int http_method;
int sock;
int bytes_sent;
int http_status;
unsigned int client_host;
unsigned int objectlen;
char query[MAX_URI_LEN];
char *object_addr;
char objectname[MAX_URI_LEN];
int module_index;
char modulename[MAX_MODULENAME_LEN];
char post_data[MAX_POST_DATA];
char new_date[DATE_LEN];
int cookies_len;
char cookies[MAX_COOKIE_LEN];
int event;
int thread_nr;
void *id;
void *private;
} user_req_t;
Несколько примеров для модулей - простое 'Hello World' :
/* * demo.c: simple 'Hello World' module using TUXAPI. */
#include "tuxmodule.h"
#include < unistd.h>
#include < string.h>
#ifdef TUXAPI_declare
TUXAPI_declare;
#endif
int TUXAPI_handle_events (user_req_t *req)
{
char message [] =
"HTTP/1.1 200\r\n"
"Connection: Keep-Alive\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 34\r\n\r\n"
" Hello WebWorld! :-) ";
write(req->sock, message, strlen(message));
return tux(TUX_ACTION_FINISH_REQ, req);
}
Пример модуля для редиректа :
/* * demo4.c: sample module showing URL-based redirection. */
#include < unistd.h>
#include "tuxmodule.h"
#ifdef TUXAPI_declare
TUXAPI_declare;
#endif
#define REPLY_HEADER "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
#define REPLY_HEADER_LEN (sizeof(REPLY_HEADER)-1)
#define ERROR "GET_OBJECT error.\n"
#define ERROR_LEN (sizeof(ERROR)-1)
#define EXT ".shtml"
#define EXT_LEN (sizeof(EXT)-1)
int TUXAPI_handle_events (user_req_t *req)
{
int ret = TUX_RETURN_USERSPACE_REQUEST;
int len;
len = strlen(req->objectname);
if ((len > EXT_LEN) &&
!memcmp(req->objectname + len - EXT_LEN, EXT, EXT_LEN))
return tux(TUX_ACTION_REDIRECT_REQ, req);
if (!req->objectname[0] && !req->query[0])
return tux(TUX_ACTION_FINISH_CLOSE_REQ, req);
switch (req->event) {
/*
* A new request starts with event code 0.
*/
case 0:
write (req->sock, REPLY_HEADER, REPLY_HEADER_LEN);
req->http_status = 200;
/*
* set req->objectname to the requested object
* in the query string if it exists. This simulates
* simple static GETs. Otherwise just send the
* requested object.
*/
if (req->query[0])
strcpy(req->objectname, req->query);
req->event = 1;
ret = tux(TUX_ACTION_GET_OBJECT, req);
if (ret < 0 || req->error) {
write (req->sock, ERROR, ERROR_LEN);
goto abort;
}
break;
case 1:
if (req->error) {
write (req->sock, ERROR, ERROR_LEN);
goto abort;
}
req->event = 2;
ret = tux(TUX_ACTION_SEND_OBJECT, req);
break;
case 2:
abort:
ret = tux(TUX_ACTION_FINISH_CLOSE_REQ, req);
break;
}
return ret;
}
|
|