reader: add maxparallel feature to limit simultaneous services per reader
This feature allows limiting the number of services that can use a reader
simultaneously, essential for card readers with slot restrictions.
=== NEW CONFIGURATION OPTIONS ===
maxparallel (default: 0 = unlimited)
Maximum number of active services per reader. When reached, the reader
is skipped and other readers are tried (fallover).
paralleltimeout (default: 1000 ms)
Buffer added to the measured ECM interval for slot expiration.
A slot expires when no ECM is received within (measured_interval + timeout).
parallelfactor (default: 1.5)
Multiplier for pending slots to support zapping without blackscreen.
Set to 0 to disable pending slots (strict maxparallel enforcement).
=== ARCHITECTURE ===
Dual-slot system with active and pending services:
- Active slots (size: maxparallel)
Confirmed services actively receiving CWs from this reader.
- Pending slots (size: maxparallel * parallelfactor)
Temporary overflow during channel zapping. Pending services are
promoted to active when slots free up (FIFO), or dropped when
active services need the capacity.
Slot reservation timing:
Slots are reserved when a reader DELIVERS a CW, not when the request
is sent. This prevents readers from blocking capacity for services
they don't end up serving when multiple readers are queried in parallel.
=== BLOCKLIST FOR CLEAN FALLOVER ===
When a pending service is dropped, the client+service combination is
added to a per-reader blocklist. This causes:
- Subsequent ECM requests for blocked combinations to skip this reader
- Clean fallover to other readers without repeated drop cycles
- No log spam from services repeatedly going to pending and getting dropped
Blocklist lifecycle:
- Added: when service is dropped from pending
- Removed: when client zaps to a different service
- Cleared: when an active slot becomes free
=== TYPICAL USE CASE ===
- Reader 1: maxparallel=1 (card allows only 1 service)
- Receiver records Service A on Reader 1, user zaps to Service B
- Service B goes to pending slot (no blackscreen during zap)
- Service A sends ECM -> Service B dropped from pending
- Service B blocklisted on Reader 1 -> falls over to Reader 2
- User stops Service B -> block cleared, Reader 1 available again