Inicio / TLS / API del núcleo

Referencia de la API del núcleo

Referencia completa de todos los tipos, métodos, códigos de estado y punteros de función disponibles para los módulos. Incluye un solo header: portal/portal.h

Un solo header. Todo lo que un module necesita se expone a través de portal/portal.h. La API del core es intencionalmente pequeña — cada puntero de función en portal_core_t existe porque un module no puede hacer su trabajo sin él.

1. Tipos

portal_header_t — Par clave-valor

La unidad fundamental para los metadatos de un mensaje. Los headers transportan información auxiliar junto al body.

typedef struct {
    char *key;
    char *value;
} portal_header_t;

portal_labels_t — Conjunto de etiquetas

Las etiquetas controlan el acceso a los path. Un path puede requerir una o más etiquetas; solo los usuarios autenticados (o módulos) cuyo token contenga etiquetas coincidentes pueden acceder a él.

typedef struct {
    char  labels[PORTAL_MAX_LABELS][PORTAL_MAX_LABEL_LEN];
    int   count;
} portal_labels_t;
FunciónFirmaDescripción
portal_labels_add(portal_labels_t *set, const char *label)Añadir una etiqueta al conjunto
portal_labels_remove(portal_labels_t *set, const char *label)Eliminar una etiqueta del conjunto
portal_labels_has(portal_labels_t *set, const char *label)Comprobar si una etiqueta existe en el conjunto
portal_labels_intersects(portal_labels_t *a, portal_labels_t *b)Comprobar si dos conjuntos comparten alguna etiqueta
portal_labels_clear(portal_labels_t *set)Eliminar todas las etiquetas del conjunto

portal_msg_t — El mensaje universal

Cada petición, comando, evento y suscripción fluye a través de esta única estructura. Esto es la Ley 2 en código.

typedef struct {
    uint64_t          id;
    char             *path;
    uint8_t           method;
    uint16_t          header_count;
    portal_header_t  *headers;
    void             *body;
    size_t            body_len;
    portal_ctx_t     *ctx;    // auth + trace
} portal_msg_t;
FunciónFirmaDescripción
portal_msg_alloc(void)Asignar un nuevo mensaje vacío
portal_msg_free(portal_msg_t *msg)Liberar el mensaje y toda la memoria asociada
portal_msg_set_path(portal_msg_t *msg, const char *path)Establecer el path de destino
portal_msg_set_method(portal_msg_t *msg, uint8_t method)Establecer el método (GET, SET, CALL...)
portal_msg_set_body(portal_msg_t *msg, const void *data, size_t len)Establecer el body (copia los datos)
portal_msg_add_header(portal_msg_t *msg, const char *key, const char *value)Añadir un header clave-valor

portal_resp_t — Respuesta

Devuelta por las llamadas síncronas de send. Contiene un código de estado, headers opcionales y un body.

typedef struct {
    uint16_t          status;
    uint16_t          header_count;
    portal_header_t  *headers;
    void             *body;
    size_t            body_len;
} portal_resp_t;
FunciónFirmaDescripción
portal_resp_alloc(void)Asignar una nueva respuesta vacía
portal_resp_free(portal_resp_t *resp)Liberar la respuesta y toda la memoria asociada
portal_resp_set_status(portal_resp_t *resp, uint16_t status)Establecer el código de estado
portal_resp_set_body(portal_resp_t *resp, const void *data, size_t len)Establecer el body de la respuesta (copia los datos)

portal_ctx_t — Contexto del mensaje

Adjunto a cada mensaje. Contiene las credenciales de autenticación y la información de trazabilidad distribuida. El core lo rellena automáticamente — los módulos lo leen pero nunca lo falsifican.

typedef struct {
    portal_auth_t   auth;     // user + token + labels
    portal_trace_t  trace;    // trace_id, parent_id, timestamp_us, hops
    char           *source_node;
    char           *source_module;
} portal_ctx_t;

2. Métodos

Siete métodos cubren todos los patrones de interacción posibles. Cada mensaje lleva exactamente uno.

ConstanteValorDescripción
PORTAL_METHOD_GET0x01Leer un recurso, sin efectos secundarios
PORTAL_METHOD_SET0x02Crear o actualizar un recurso
PORTAL_METHOD_CALL0x03Ejecutar una acción
PORTAL_METHOD_EVENT0x04Notificación sin esperar respuesta
PORTAL_METHOD_SUB0x05Suscribirse a eventos en un path
PORTAL_METHOD_UNSUB0x06Cancelar la suscripción a eventos
PORTAL_METHOD_META0x07Consultar metadatos del path (modo de acceso, etiquetas, propietario)

3. Códigos de estado

Inspirados en HTTP pero reducidos a lo esencial. Cada respuesta lleva exactamente un código de estado.

CódigoConstanteSignificado
200PORTAL_OKÉxito
201PORTAL_CREATEDRecurso creado
202PORTAL_ACCEPTEDPetición aceptada, procesamiento asíncrono
400PORTAL_BAD_REQUESTMensaje malformado o parámetros inválidos
401PORTAL_UNAUTHORIZEDAutenticación requerida o token inválido
403PORTAL_FORBIDDENAutenticado pero etiquetas insuficientes
404PORTAL_NOT_FOUNDEl path no existe
409PORTAL_CONFLICTRecurso bloqueado o conflicto de versión
500PORTAL_INTERNAL_ERRORFallo en el module
503PORTAL_UNAVAILABLEModule no cargado o nodo inalcanzable

4. API del core (portal_core_t)

Cada module recibe un puntero portal_core_t al cargarse. Esta es la única interfaz del module con el sistema. Toda interacción con el core, otros módulos, eventos, almacenamiento y configuración pasa a través de estos punteros de función.

La Ley 3 en la práctica. El core no hace nada — pero proporciona a los módulos todo lo que necesitan. Cada puntero de función a continuación existe porque un module no puede hacer su trabajo sin él.

Gestión de path

Puntero de funciónFirmaDescripción
path_register(core, const char *path, const char *module_name)Registrar un path perteneciente a este module
path_unregister(core, const char *path)Liberar un path previamente registrado
path_set_access(core, const char *path, uint8_t mode)Establecer el modo de acceso: READ, WRITE o RW (Ley 8)
path_add_label(core, const char *path, const char *label)Requerir esta etiqueta para acceder al path
path_remove_label(core, const char *path, const char *label)Eliminar una restricción de etiqueta del path

Enrutamiento de mensajes

Puntero de funciónFirmaDescripción
send(core, portal_msg_t *msg, portal_resp_t *resp)Enviar un mensaje a cualquier path, local o remoto. Bloquea hasta recibir respuesta.

Consultas de módulos

Puntero de funciónFirmaDescripción
module_loaded(core, const char *name)Comprobar si un module está actualmente cargado y disponible

Event loop

Puntero de funciónFirmaDescripción
fd_add(core, int fd, uint32_t events, callback, userdata)Registrar un descriptor de archivo para E/S asíncrona (Ley 13)
fd_del(core, int fd)Eliminar un descriptor de archivo del event loop
timer_add(core, uint64_t interval, callback, userdata)Registrar un temporizador periódico (intervalo en milisegundos)

Eventos

Puntero de funciónFirmaDescripción
event_register(core, const char *path, const char *description, portal_labels_t *labels)Declarar un evento que este module puede emitir
event_unregister(core, const char *path)Eliminar una declaración de evento
event_emit(core, const char *path, const void *data, size_t len)Disparar un evento a todos los suscriptores (Ley 10)

Pub/Sub

Puntero de funciónFirmaDescripción
subscribe(core, const char *pattern, handler, userdata)Suscribirse a eventos que coincidan con un patrón de path
unsubscribe(core, const char *pattern, handler)Cancelar la suscripción de un handler previamente registrado

Almacenamiento

Puntero de funciónFirmaDescripción
storage_register(core, portal_storage_provider_t *provider)Registrar un backend de almacenamiento (clave-valor, SQL, etc.)

Configuración

Puntero de funciónFirmaDescripción
config_get(core, const char *module, const char *key)Leer un valor de configuración de un module (Ley 11)

Registro de log

Puntero de funciónFirmaDescripción
log(core, uint8_t level, const char *module, const char *fmt, ...)Escribir una entrada de log en el nivel especificado

Niveles de log:

ConstanteValorUso
PORTAL_LOG_ERROR0Fallos que requieren atención inmediata
PORTAL_LOG_WARN1Condiciones inesperadas pero recuperables
PORTAL_LOG_INFO2Mensajes operacionales normales
PORTAL_LOG_DEBUG3Información de diagnóstico detallada
PORTAL_LOG_TRACE4Trazado por mensaje, alto volumen

Bloqueo de recursos

Los recursos físicos (puertos serie, GPIO, dispositivos IoT) requieren acceso exclusivo. Estas funciones implementan la Ley 14 — bloqueo automático en la primera escritura, keepalive y liberación automática tras inactividad.

Puntero de funciónFirmaDescripción
resource_lock(core, const char *resource, const char *owner)Adquirir bloqueo exclusivo sobre un recurso
resource_unlock(core, const char *resource, const char *owner)Liberar un bloqueo retenido
resource_keepalive(core, const char *resource, const char *owner)Reiniciar el temporizador de inactividad de 60 segundos
resource_locked(core, const char *resource)Comprobar si un recurso está actualmente bloqueado
resource_owner(core, const char *resource)Devolver el propietario actual del bloqueo (o NULL)

5. Constantes

Límites

ConstanteValorDescripción
PORTAL_MAX_PATH_LEN1024Longitud máxima del path en bytes
PORTAL_MAX_MODULE_NAME64Longitud máxima del nombre de module
PORTAL_MAX_MODULES256Máximo de módulos cargados simultáneamente
PORTAL_MAX_HEADERS32Máximo de headers por mensaje
PORTAL_MAX_EVENTS64Máximo de eventos por module
PORTAL_MAX_LABELS32Máximo de etiquetas por conjunto
PORTAL_MAX_LABEL_LEN64Longitud máxima de la cadena de etiqueta

Modos de acceso

ConstanteValorDescripción
PORTAL_ACCESS_READ0x01El path acepta solo GET y META
PORTAL_ACCESS_WRITE0x02El path acepta solo SET y CALL
PORTAL_ACCESS_RW0x03El path acepta todos los métodos

6. Path internos del core

El core registra estos path al iniciar. Están siempre disponibles, incluso sin módulos cargados.

/core — Estado del core

PathMétodoDescripción
/core/statusGETDevuelve tiempo de actividad, versión y número de módulos cargados
/core/modulesGETListar todos los módulos cargados y su estado
/core/modules/{name}GETDetalles de un module específico
/core/modules/{name}/loadCALLCargar un module en tiempo de ejecución (Ley 5)
/core/modules/{name}/unloadCALLDescargar un module en tiempo de ejecución
/core/modules/{name}/reloadCALLRecargar un module (descarga + carga)
/core/pathsGETListar todos los path registrados con sus modos de acceso
/core/config/{module}/{key}GETLeer un valor de configuración de un module
/core/config/{module}/{key}SETActualizar un valor de configuración de un module
/core/log/levelGETNivel de log global actual
/core/log/levelSETCambiar el nivel de log global en tiempo de ejecución

/auth — Autenticación

PathMétodoDescripción
/auth/loginCALLAutenticar con usuario + contraseña, devuelve un token
/auth/logoutCALLInvalidar el token actual
/auth/verifyCALLVerificar un token y devolver sus etiquetas

/users — Gestión de usuarios

PathMétodoDescripción
/usersGETListar todos los usuarios
/users/{id}GETObtener detalles del usuario
/users/{id}SETCrear o actualizar un usuario
/users/{id}/labelsGETObtener el conjunto de etiquetas del usuario
/users/{id}/labelsSETReemplazar el conjunto de etiquetas del usuario

/groups — Gestión de grupos

PathMétodoDescripción
/groupsGETListar todos los grupos
/groups/{id}GETObtener detalles del grupo y lista de miembros
/groups/{id}SETCrear o actualizar un grupo
/groups/{id}/membersGETListar miembros del grupo
/groups/{id}/membersSETAñadir o eliminar miembros

/events — Registro de eventos

PathMétodoDescripción
/eventsGETListar todos los eventos registrados
/events/{path}GETObtener descripción del evento, etiquetas y número de suscriptores
/events/{path}SUBSuscribirse a un evento
/events/{path}UNSUBCancelar la suscripción a un evento

7. Patrones de comunicación

Petición / Respuesta

El patrón síncrono estándar. Un module envía un mensaje y se bloquea hasta que el module de destino responde. Se utiliza para GET, SET, CALL y META.

portal_msg_t  *msg  = portal_msg_alloc();
portal_resp_t *resp = portal_resp_alloc();

portal_msg_set_path(msg, "/local/db/users/1");
portal_msg_set_method(msg, PORTAL_METHOD_GET);

int rc = core->send(core, msg, resp);

if (rc == PORTAL_OK && resp->status == PORTAL_OK) {
    // resp->body contains the user record
    process_user(resp->body, resp->body_len);
}

portal_msg_free(msg);
portal_resp_free(resp);

Disparar y olvidar (Eventos)

Un productor de eventos emite datos a un path. Todos los suscriptores los reciben de forma asíncrona. El productor no espera y no sabe quién (o si alguien) los recibió. Se utiliza con PORTAL_METHOD_EVENT.

// Producer: emit an event
const char *payload = "{\"temp\":22.5,\"unit\":\"C\"}";
core->event_emit(core, "/local/iot/sensor/temperature",
                 payload, strlen(payload));

// Consumer: subscribe to events (registered once, usually in module_load)
static void on_temperature(const char *path,
                            const void *data, size_t len,
                            void *userdata) {
    core->log(core, PORTAL_LOG_INFO, "dashboard",
              "temperature update: %.*s", (int)len, (const char *)data);
}

core->subscribe(core, "/local/iot/sensor/*", on_temperature, NULL);
Patrón o coincidencia exacta. La función subscribe acepta patrones glob. /local/iot/sensor/* coincide con cualquier evento bajo ese prefijo. Las rutas exactas también funcionan.