Out
-аргументы в IDL-описании не рекомендуется использовать для возврата сущности-клиенту кодов логических ошибок, возникающих в результате обработки запроса сущностью-сервером. Вместо этого рекомендуется использовать error
-аргументы.
Логическая ошибка – это ошибка, которая возникла при обработке запроса сущностью-сервером и должна быть возвращена сущности-клиенту. Например, если сущность-клиент пытается открыть несуществующий файл, сервер файловой системы возвращает логическую ошибку. Внутренние ошибки сущности-сервера, такие как нехватка памяти или выполнение недопустимой инструкции, не являются логическими ошибками.
Использование error
-аргументов позволяет:
out
-аргументы методов в сообщении-ответе от сущности-сервера к сущности-клиенту в случае возврата ошибки. Вместо этого, при необходимости вернуть код ошибки, сообщение-ответ будет содержать только error
-аргументы.Язык IDL и компилятор NK предоставляют два способа использования error
-аргументов:
Этот способ используется компилятором NK по умолчанию.
При использовании этого способа методы интерфейсов могут иметь не более одного error
-аргумента типа UInt16
. Значения возвращаемого error
-аргумента метода упаковываются в код возврата соответствующего клиентского интерфейсного метода.
Для использования этого способа необходимо использовать параметр --extended-errors
компилятора NK.
При использовании этого способа методы интерфейса могут иметь несколько error
-аргументов любого типа. Значения возвращаемых error
-аргументов метода содержатся во внутренних полях структуры сообщения-ответа.
Типы и макросы для работы с ошибками содержатся в файле /opt/KasperskyOS-Community-Edition-<version>/toolchain/include/nk/types.h
Упрощенная обработка ошибок
При использовании упрощенной обработки ошибок методы интерфейсов могут иметь не более одного error
-аргумента типа UInt16
с именем status
.
В случае ошибки:
NK_ELOGIC_MAKE()
для упаковки кода ошибки и возвращать результат его работы.nk_err_t
. Для проверки на наличие в нем логических и транспортных ошибок используются макросы NK_ELOGIC_CHECK()
и NK_ETRANSPORT_CHECK()
соответственно.В случае успешной обработки запроса:
out
-аргументам поля сообщения-ответа и вернуть NK_EOK
.NK_EOK
.Например, рассмотрим IDL-описание интерфейса, содержащего один метод:
Connection.idl
typedef UInt16 ErrorCode
// пример кода ошибки
const ErrorCode ESendFailed = 10;
interface {
Send(in Handle handle,
in Packet packet,
out UInt32 sentLen,
// метод Send имеет один error-аргумент status типа UInt16
error ErrorCode status
);
}
Реализация серверной сущности:
server.c
...
// реализация метода Send
nk_err_t Send_impl(struct Connection *self,
const struct Connection_Send_req *req,
const struct nk_arena* req_arena,
struct Connection_Send_res* res,
struct nk_arena* res_arena)
{
if (...) {
// в случае успешной обработки запроса помещаем результат в out-аргумент и возвращаем NK_EOK
res->sentLen = value;
return NK_EOK;
} else {
// в случае ошибки возвращаем результат работы макроса NK_ELOGIC_MAKE
return NK_ELOGIC_MAKE(Connection_ESendFailed);
}
Реализация клиентской сущности:
client.c
// значения возвращаемого error-аргумента метода упаковываются в код возврата соответствующего клиентского интерфейсного метода
nk_err_t ret = Connection_Send(ctx,
&req, &req_arena,
&res, NK_NULL);
if (ret == NK_EOK) {
// если ошибок нет, res содержит значения out-аргументов
return res.sentLen;
} else {
if (NK_ELOGIC_CHECK(ret)) {
// обрабатываем логическую ошибку
} else {
// обрабатываем транспортную ошибку
}
}
Расширенная обработка ошибок
При использовании расширенной обработки ошибок методы интерфейсов могут иметь более одного error
аргумента любого типа.
В случае ошибки:
nk_err_reset()
, чтобы выставить в сообщении-ответе флаг ошибки;error
-аргументам поля сообщения-ответа;NK_EOK
.NK_EOK
, если транспортной ошибки нет. Для проверки наличия в сообщении-ответе логических ошибок используется макрос nk_msg_check_err()
. При этом значения возвращаемых error
-аргументов метода содержатся во внутренних полях структуры сообщения-ответа.В случае успешной обработки запроса:
out
-аргументам поля сообщения-ответа и вернуть NK_EOK
.NK_EOK
.Например, рассмотрим IDL-описание интерфейса, содержащего один метод:
Connection.idl
typedef UInt16 ErrorCode
interface {
Send(in Handle handle,
in Packet packet,
out UInt32 sentLen,
// метод Send имеет один error-аргумент status типа UInt16
error ErrorCode status
);
}
При этом union
-тип, сгенерированный компилятором NK для фиксированной части сообщения-ответа для этого метода, содержит как out
-аргументы, так и error
-аргументы:
Connection.idl.h
...
struct Connection_Send_res {
union {
struct {
struct nk_message base_;
nk_uint32_t sentLen;
};
struct {
struct nk_message base_;
nk_uint32_t sentLen;
} res_;
struct kl_Connection_Send_err {
struct nk_message base_;
nk_uint16_t status
} err_;
};
};
...
Реализация серверной сущности:
server.c
...
// реализация метода Send
nk_err_t Send_impl(struct Connection *self,
const struct Connection_Send_req *req,
const struct nk_arena* req_arena,
struct Connection_Send_res* res,
struct nk_arena* res_arena)
{
if (...) {
// в случае успешной обработки запроса помещаем результат в out-аргумент и возвращаем NK_EOK
res->sentLen = value;
return NK_EOK;
} else {
// в случае ошибки вызываем макрос nk_err_reset(), чтобы выставить флаг ошибки в сообщении-ответе
nk_err_reset(res)
// заполняем поля err-аргументов в структуре res->err_
res->err_.status = 10;
// возвращаем NK_EOK
return NK_EOK;
}
Реализация клиентской сущности:
client.c
nk_err_t ret = Connection_Send(ctx,
&req, &req_arena,
&res, NK_NULL);
if (ret == NK_EOK) {
if (nk_msg_check_err(res)) {
// обрабатываем логическую ошибку
// значения возвращаемых error-аргументов метода содержится во внутренних полях структуры сообщения-ответа
return res.err_.status;
} else {
// если ошибок нет, res содержит значения out-аргументов
return res.sentLen;
}
} else {
// обрабатываем транспортную ошибку
}
В начало