-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Every operation follows the same path:
Client → Interface → Core Router → ACL Check → Module Handler → Response
┌─────────┐ ┌─────────┐ ┌─────────┐
│ CLI │ │ HTTP │ │ SSH │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└───────┬───────┴───────┬───────┘
│ │
┌───────▼───────────────▼───────┐
│ Core Engine │
│ ┌─────────────────────────┐ │
│ │ Path Router (FNV1a) │ │
│ │ O(1) hash lookup │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ ACL Check │ │
│ │ user.groups ∩ │ │
│ │ path.labels ≠ ∅ │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ Module Dispatch │ │
│ │ setjmp + handler() │ │
│ └─────────────────────────┘ │
└───────────────────────────────┘
│ │ │
┌───────┘ │ └───────┐
┌────▼────┐ ┌─────▼─────┐ ┌────▼────┐
│ mod_web │ │ mod_cache │ │ mod_iot │
└─────────┘ └───────────┘ └─────────┘
| Component | File | Purpose |
|---|---|---|
| Main | src/main.c |
Entry point, arg parsing, signal handling, event loop |
| Path Router | src/core/core_path.c |
FNV-1a hash table, path registration, wildcard fallback |
| Module Loader | src/core/core_module.c |
dlopen/dlsym, reference counting, hot-reload |
| Message System | src/core/core_message.c |
Message creation, routing, method dispatch |
| ACL Engine | src/core/core_auth.c |
Users, groups, labels, token management |
| Event System | src/core/core_events.c |
Pub/Sub, pattern matching, ACL-controlled subscriptions |
| Storage | src/core/core_storage.c |
Multi-backend fan-out writes, priority reads |
| Store | src/core/core_store.c |
File-based persistence (always enabled) |
| Config | src/core/core_config.c |
Config parsing, /config/* path interface |
| Wire Protocol | src/core/core_wire.c |
PORTAL02 binary serialization for federation |
| Hash Table | src/core/core_hashtable.c |
Generic hash table used by router and cache |
| Logging | src/core/core_log.c |
Multi-level logging, file rotation |
| Handlers | src/core/core_handlers.c |
Built-in internal path handlers |
| Instance | src/core/portal_instance.c |
Core state management, multi-instance support |
| Pub/Sub | src/core/core_pubsub.c |
Event subscription and emission engine |
Paths are hashed with FNV-1a for O(1) lookup:
uint32_t hash = 2166136261u; // FNV offset basis
for (const char *p = path; *p; p++) {
hash ^= (uint8_t)*p;
hash *= 16777619u; // FNV prime
}
return hash & (table_size - 1); // table_size is power of 2Lookup order:
- Exact match in hash table
- Walk path backwards stripping segments, try wildcard
*at each level - Return 404 NOT_FOUND
User Path
┌──────────────┐ ┌──────────────┐
│ groups: │ │ labels: │
│ - admin │ │ - admin │
│ - ops │ │ - security │
└──────┬───────┘ └──────┬───────┘
│ │
└────────┬─────────┘
│
intersection
{admin} ≠ ∅
│
ACCESS GRANTED
Special rules:
- User with group
*→ superuser, access everything - Path with no labels → public, anyone can access
- Path with label
admin→ only users with groupadmin
static jmp_buf crash_buf;
static volatile sig_atomic_t crash_signal = 0;
static void crash_handler(int sig) {
crash_signal = sig;
longjmp(crash_buf, 1);
}
// In message dispatch:
signal(SIGSEGV, crash_handler);
signal(SIGFPE, crash_handler);
if (setjmp(crash_buf) == 0) {
rc = mod->handle(core, msg, resp); // module code runs here
} else {
// module crashed — core is safe
resp->status = 500;
mod->stats.crashes++;
core_log(LOG_ERROR, "Module %s crashed: signal %d", mod->name, crash_signal);
}
signal(SIGSEGV, SIG_DFL);
signal(SIGFPE, SIG_DFL); Module SET /config/key = value
│
┌──────────▼──────────┐
│ Storage Engine │
│ (fan-out write) │
└──┬──────┬──────┬────┘
│ │ │
┌───────▼┐ ┌───▼────┐ ┌▼────────┐
│ File │ │ SQLite │ │PostgreSQL│
│(always)│ │ (WAL) │ │ (async) │
└────────┘ └────────┘ └──────────┘
Module GET /config/key
│
┌──────────▼──────────┐
│ Storage Engine │
│ (priority read) │
└──────────┬──────────┘
│
PostgreSQL → SQLite → File
(first success wins)
Three subscription patterns:
-
Exact:
/events/iot/device_added— matches only this event -
Wildcard:
/events/iot/*— matches all events under/events/iot/ -
Global:
*— matches every event in the system
Events are ACL-controlled. A subscriber can only receive events whose labels intersect with the subscriber's groups.
Binary format for federation:
┌────────┬────────┬──────────┬───────────┬──────────────┐
│ MAGIC │ VERSION│ MSG_TYPE │ BODY_LEN │ BODY │
│ 4 bytes│ 2 bytes│ 1 byte │ 4 bytes │ variable │
│"PRT\0" │ 0x0002 │ 0x01=msg │ uint32 BE │ serialized │
└────────┴────────┴──────────┴───────────┴──────────────┘
Key authentication: SHA-256 challenge-response handshake, shared federation key.
Top Level System — GPL-2.0 | Website | Repository
mod_cli · mod_web · mod_node · mod_ssh · mod_config_sqlite · mod_config_psql
mod_cache · mod_kv · mod_shm · mod_queue · mod_websocket · mod_mqtt · mod_email · mod_file
mod_logic · mod_logic_lua · mod_logic_python · mod_logic_c · mod_logic_pascal
mod_metrics · mod_health · mod_sysinfo · mod_process · mod_log · mod_audit · mod_cron · mod_scheduler · mod_worker · mod_backup
mod_proxy · mod_dns · mod_http_client · mod_webhook · mod_api_gateway · mod_tunnel · mod_acme
mod_firewall · mod_crypto · mod_ldap · mod_validator
mod_iot · mod_gpio · mod_serial
mod_xz · mod_gzip · mod_template · mod_admin