Configuration¶
The platform is configured through TOML files parsed by tomlplusplus. There is one file per role under config/, each driving a different subset of modules. The path is supplied to the server binary via -i. Utils::setup parses the file once at startup and exposes typed accessors UTILS::instance()->get_d(section, key) (integer) and get_s(section, key) (string).
File Layout¶
config/
├── prepaid.toml # Prepaid OCS role
├── cdr_loader.toml # CDR ingestion role
├── billing1.toml # Billing role for bill-cycle 1
├── billing2.toml # Billing role for bill-cycle 2
├── billing3.toml # Billing role for bill-cycle 3
├── billing4.toml # Billing role for bill-cycle 4
├── prepaid_mass_rating.toml # Developer-only mass rating role
├── crm.toml # CRM gRPC role
├── stats.toml # Stats handler role
├── bill_formatter.toml # PDF bill formatter role
├── cdr_loader.toml # CDR ingestion (alias also above)
├── cdr_generator.toml # Tool config — bin/cdr_generator
└── diameter_client.toml # Tool config — bin/diameter_client
The cdr_generator.toml and diameter_client.toml files configure standalone tools, not the server binary itself.
Common Sections¶
These sections appear (with the same semantics) in nearly every role's TOML.
[modules]¶
Boolean (0/1) gate per platform module. Read by main.cpp. The license feature mask still has final say, but [modules] is what enables the wiring at all:
[modules]
billing = 0
prepaid = 1
prepaid_mass_rating = 0
cdr_loader = 0
stats = 0
crm = 0
bill_formatter = 0
The reference role files each enable exactly one module (with the exception of prepaid_mass_rating.toml, which enables both billing and prepaid_mass_rating).
[system]¶
[system]
thread_pool_size = 8
timestamp_format = "%Y-%m-%d %H:%M:%S"
time_zone = "Europe/Bucharest"
ssl = 0 # only present in prepaid.toml; reserved for the prepaid acceptor
thread_pool_size is consumed by THREAD_POOL::instance()->init(size) in main.cpp. timestamp_format is used for both Utils::to_datetime and Utils::from_datetime.
[db]¶
[db]
username = "macbook"
password = "..."
host = "localhost"
port = 33060 # MySQL X DevAPI default port
database = "billing"
poolsize = 15
Every role connects to the same MySQL instance via mysqlcppconnx (X DevAPI). Each worker thread opens its own session — poolsize is currently advisory; X DevAPI manages session pooling internally.
[logging]¶
See Logging for full semantics.
[app]¶
[app]
operator_id = 3
free_units_functionality = 1
initial_delay = 0
interval = 60
activity_heartbeat_stale_s = 600
activity_heartbeat_interval_subs = 10
operator_id filters reference-data queries to the active operator. free_units_functionality toggles free-unit accounting in the rater. initial_delay and interval are passed to ACE_Reactor::schedule_timer for the timer-driven handlers (CDR loader, billing, stats, bill formatter); units are seconds.
activity_heartbeat_stale_s is the watchdog threshold consulted by BillingHandler::handle_timeout (see Postpaid Billing). A PROCESSING activity whose heartbeat_at is older than this many seconds is presumed dead and is transitioned to ACTIVITY_STATUS_ERROR on the next tick. The default of 600 seconds is generous so a long bill run on limited hardware does not trip a false positive; setting it to 0 disables the watchdog entirely.
activity_heartbeat_interval_subs is the cadence at which DB_layer::billCycle refreshes the heartbeat inside its per-subscriber loop. One beat per ten subscribers (the default) keeps heartbeat_at comfortably fresh without hammering the database; setting it to 0 heartbeats only at the start and end of the run.
[license]¶
Required in every role. Validated before any module is initialised.
Role-Specific Sections¶
prepaid.toml¶
The DIAMETER acceptor listens here. The [system].ssl flag is reserved for an SSL-wrapped DIAMETER mode that requires __SSL_MODE__ to be defined at compile time; the default build is non-SSL.
billing*.toml¶
BillingHandler::setBillcycle is called with this value. Activities whose bill-cycle does not match are silently rejected by the running process, so each bill-cycle has at most one process draining it.
cdr_loader.toml¶
[cdr]
cdr_path = "/.../server.micro.bss/cdr"
cdr_prefix = "data"
new_cdr_path = "/.../cdr/new"
processed_cdr_path = "/.../cdr/processed"
error_cdr_path = "/.../cdr/error"
duplicate_cdr_path = "/.../cdr/duplicate"
new_cdr_extension = ".cdr"
processed_cdr_extension = ".done"
error_cdr_extension = ".error"
duplicate_cdr_extension = ".duplicate"
new_cdr_path is polled on every tick. Files matching new_cdr_extension are processed and renamed with the appropriate suffix. Files whose CDR id is already present in the offline table land in duplicate_cdr_path with the .duplicate suffix rather than error/ — a re-presented CDR is expected upstream-mediation behaviour, not an error. The paths are absolute; on a fresh deployment the update_toml.sh helper rewrites them to point at the deployment prefix.
cdr_generator.toml¶
[generator]
gen_voice_min = 3
gen_voice_max = 30
gen_data_min = 1024
gen_data_max = 10240
gen_sms_units = 1
gen_mms_units = 1
gen_date_start = "2025-06-01 00:00:00"
gen_date_end = "2026-02-01 00:00:00"
gen_b_number = "40747498888"
Used by bin/cdr_generator to drive synthetic load.
crm.toml¶
[server]
port = 50051
host = "0.0.0.0"
[tls]
cert_path = "certs/server.crt"
key_path = "certs/server.key"
ca_cert_path = "certs/ca.crt"
allow_insecure = 0
[jwt]
secret = "your-secret-key-change-this-in-production"
issuer = "crm-server"
audience = "crm-api"
tls.allow_insecure defaults to 0; the gRPC server refuses to start in cleartext unless explicitly authorised. The shipped jwt.secret is a placeholder — replace before deployment.
bill_formatter.toml¶
[bill_formatter]
template_dir = "./html"
output_dir = "./invoices"
billcycle = -1
year = -1
month = -1
-1 on the period filters means no filter; the formatter picks up any bill with status BILL_STATUS_NEW. The three filter fields are present for future scoping (e.g. running a one-shot formatter for a single archived month) but not currently consulted by BillFormatterHandler.
diameter_client.toml¶
See Prepaid Charging. Drives the bin/diameter_client load tester: connection target, execution mode, MSISDN pools, per-service ranges, and event-type distribution.
stats.toml¶
stats.toml enables only the stats module and inherits the common timer fields from [app]. StatsHandler::handle_timeout queries the database aggregates and writes the four stat rows backing the CRM dashboard charts.
Updating Paths after Deployment¶
scripts/update_toml.sh <new_root> rewrites the absolute paths embedded in TOML files (log paths, CDR directories, SSL paths) to match the runtime deployment prefix. It is invoked automatically by scripts/install.sh install and by unpack.sh after a tarball deployment, so operators rarely need to edit TOML by hand.