← Inicio

📋 Changelog

Candela Softcam — historial completo de versiones
R42 Cóndor actual Mayo 2026

AES-128 IPTV, MultiPID y QuickECM

  • AES-128 IPTV - nuevo módulo src/crypto/aes_iptv.c/h: soporte completo de descifrado AES-128 para streams IPTV y OTT. El fichero candela.aeskeys mapea SRVID a clave estática en hex (AES-128-CBC, ECB, CTR o auto-detección) o a URL HTTP/HTTPS donde se fetchea la clave en tiempo real (estándar HLS EXT-X-KEY). Si no hay entrada para un canal, el pipeline ECM normal resuelve la CW sin cambios. El motor CSA ya soportaba DVB-CISSA (AES-128-CBC con IV de TS) y AES-CTR para OTT; este módulo añade la capa de configuración y el fetcher HTTP/HTTPS. Compatible con todos los targets (Linux, Windows/MinGW, MIPS, ARM).
  • MultiPID - descifrado paralelo de todos los CA PIDs de la PMT: nuevo campo multipid_mode en candela.json. Cuando está activo (default off), Candela parsea todos los descriptores CA de la PMT (hasta 8) en lugar de solo el primero, y lanza ECMs a todos los sistemas CA en paralelo para cada canal. La primera CW válida que llega se entrega al receptor. Útil en canales con múltiples CA simultáneos (cable/IPTV multisistema). Toggle en la pestaña CSA del WebIF.
  • QuickECM - timeout por CAID configurable: nueva tabla quickecm[] en configuración que permite definir intervalo y timeout de respuesta ECM específicos por CAID. Por defecto (0) el sistema usa el timeout global/adaptativo existente (ETO + client_timeout). Útil para operadores con ciclo ECM no estándar (muy rápido o muy lento). Configurable por tabla en la pestaña CSA del WebIF.

Diagnóstico ECM ampliado - CW, ECM PID y actividad EMM

  • Estado CW por canal en tiempo real: nueva card en la pestaña Diagnóstico que muestra, para cada canal cifrado activo, la CW even (key 00) y CW odd (key 01) en hexadecimal y la edad de la CW en segundos. La edad se colorea en verde (<8s), naranja (8-12s) y rojo (>12s) para detectar de un vistazo cuándo una CW lleva demasiado tiempo sin rotar y el canal está a punto de cortarse. Endpoint GET /api/diag/cw_state.
  • ECM PID por canal: el PID del flujo ECM extraído de la PMT DVB se almacena ahora en el contexto de demux y se incluye en la respuesta de /api/diag/cw_state. Permite identificar qué sistema de acceso condicional está activo para cada canal y detectar cambios de PID en canales multiplex.
  • Actividad EMM por CAID: nueva card con tabla de EMMs recibidas agrupadas por CAID. Muestra el total acumulado, la tasa estimada por minuto y el tiempo transcurrido desde la última EMM. La tasa se colorea en verde (<3/min), naranja (3-10/min) y rojo (>10/min) para detectar renovaciones forzadas o actividad inusual del sistema CA. Endpoint GET /api/diag/emm_stats.

Análisis en tiempo real - sparklines, hit rate y eventos

  • Sparkline de latencia por reader: cada lector (NewCamd cliente, MGcamd cliente y hardware) almacena ahora un ring buffer de las últimas 20 latencias medidas. La pestaña Diagnóstico muestra una mini-gráfica SVG por reader con color adaptativo (verde/naranja/rojo) según la latencia media. Endpoint GET /api/diag/reader_latency.
  • Hit rate de resolución ECM: contadores globales de ECMs resueltas por caché, local, red P2P, lector ocupado y denegadas. Barras proporcionales con porcentaje en tiempo real. Endpoint GET /api/diag/stats. Coste: 5 contadores atómicos, sin impacto medible.
  • Eventos del sistema: ring buffer de 200 eventos con timestamp: canal acumulando denegaciones, lector saturado, peer conectado/desconectado, CW inválida. Endpoint GET /api/diag/events. Coste: ~20 KB fijos en RAM.

Rendimiento WebIF y compatibilidad de build

  • LZ4 reemplaza LZO en assets WebIF: los activos estáticos (HTML, JS, CSS, traducciones) se almacenan comprimidos con LZ4 en el header generado. LZ4 es más rápido que LZO en descompresión y no requiere inicialización en tiempo de ejecución. La generación del header webif_assets.h vía gen_web_assets.py usa ahora lz4_compress_tool compilado desde lz4/lz4.c. CMakeLists, Makefile y el script Python actualizados completamente.
  • zlib nivel 1 (compresión ultrarápida): el gzip de respuestas HTTP baja de nivel 6 a nivel 1. La penalización de primera carga (descompresión de LZ4 + gzip) se reduce ~6x. El resultado queda cacheado en RAM; las recargas posteriores no tienen coste adicional.
  • Bug Windows - configuración al vuelo perdida tras F5: en Windows, api_get_config() usaba fopen("r") (modo texto). El conteo de bytes vía ftell incluía los \r\n, pero fread los convertía a \n, dejando bytes basura al final del JSON. El navegador lanzaba SyntaxError, configObj quedaba vacío y todos los campos del WebIF aparecían desactivados. Corregido a fopen("rb") y buf[bytes_leidos] = '\0'.
  • 403 en mosc_list cuando Forense desactivado: fetchMoscState() en app.js se lanzaba incondicionalmente al montar el panel. En instalaciones sin forense activo generaba un 403 visible en consola. Ahora la llamada se guarda con if (this.configObj.enable_forensics).
  • Compatibilidad GCC 4.5 - ARM MCA, x86 legacy y MIPS uClibc: #pragma GCC diagnostic push/pop estaba dentro de la función nc_recv_msg(). GCC < 4.6 no permite el pragma dentro de funciónes y aborta la compilación. Movido a nivel de fichero en newcamd_common.c cubriendo ambas funciónes DES desde fuera.
  • Makefile - regla $(OBJDIR)/lz4/lz4.o añadida: la migración minilzo->lz4 estaba incompleta en el Makefile: faltaba la regla de compilación del objeto. Sin ella make no sabía cómo compilar lz4/lz4.c y la vinculación fallaba. Corregido junto con los includes, sources y patsubst.
  • build_libs.sh - detección de punteros Git LFS en zlib: en toolchains OpenWrt donde libz.a es un puntero LFS y no un archivo real, build_zlib() detectaba el fichero con -f y saltaba la compilación. El enlazador fallaba luego con file format not recognized. Ahora se verifica con ar t que el archivo es un archivador válido antes de saltarse la compilación.

Panel de seguridad - acciones masivas

  • Botón "Marcar todos leídos": marca de una vez todos los eventos de seguridad como leídos sin tener que hacerlo uno a uno. Endpoint POST /api/security/events/read_all.
  • Botón "Bloquear todos": añade al jail todos los IPs con eventos de seguridad pendientes. Distinto del botón de desbloquear todos (para IPs ya en lista negra). Endpoint POST /api/security/events/block_all.
  • Traducciones completas de ambos botónes en los 6 idiomas del WebIF (es/en/de/fr/it/pt).

Nueva pestaña Diagnóstico ECM

  • Vista unificada de todos los canales activos: cruza datos del DVBAPI (demux) con el histórico de ECM por canal. Los canales FTA, TDT, IPTV, multicast y unicast sin CA aparecen marcados como "fta" junto a los canales cifrados con su estado ECM. Ya no queda ningún canal activo sin visibilidad.
  • Diagnóstico ECM por canal (causa raíz automática): para cada canal cifrado muestra el último resultado de la petición ECM (ok_cache, ok_local, reader_ocupado, denegado, pendiente_red), la fuente que lo resolvió (caché, local, newcamd, mgcamd, red) y la causa deducida automáticamente (lector al límite, filtrado, sin lector local, etc.). Contadores acumulados de éxitos, busy, denegados y pendientes. Endpoint GET /api/diag/channels.
  • Carga de lectores por SID: tabla que muestra cuántos SIDs (canales) tiene activos cada lector local en cada momento, con barra de uso en porcentaje respecto al máximo configurado. Si MCRR está activo, desglosa por reader. Endpoint GET /api/diag/readers.
  • Modo preview y sugerencias P:/I: : cuando el modo preview está activo, Candela acumula resultados por CAID:PROVID:SRVID y genera sugerencias de reglas sin aplicarlas: P: CAID:PROVID SRVID para canales que siempre resuelven localmente o en caché, I: CAID:PROVID SRVID para canales siempre denegados, y etiqueta "revisar" para los inestables. Endpoint GET /api/diag/suggestions, reset vía POST /api/diag/suggestions/reset.
  • 22 claves de traducción nuevas en los 6 idiomas para toda la pestaña Diagnóstico.

Auditoría ECM/CW - fiabilidad en todas las plataformas

  • Conflicto de checksum DVB-CSA1 resuelto: la coexistencia de dos formatos de checksum (byte[0]/byte[8] en cw_validate_and_fix y bytes 3/7/11/15 en cw_fix_checksum) causaba corrupción del byte de datos [0] y del checksum [3] al aplicarse en cascada. Eliminado el segundo pase redundante en dvbapi_send_cw; cw_fix_checksum ya se aplica en ecm_handler.c antes de que la CW llegue al DVBAPI.
  • Compatibilidad Windows/MinGW en ecm_handler.c y config.c: includes POSIX (unistd.h) protegidos con guardas #ifndef _WIN32 con fallback a process.h y #define getpid _getpid. Build MinGW64 sin errores.
  • traffic_ring_head declarado volatile en candela_proto.c para evitar UB en acceso concurrente desde hilos distintos sin barrera de memoria.

Enrutamiento ECM por latencia automática en todas las fuentes

  • Selección de fuente por latencia media (EMA) en lectores NewCamd cliente: cuando hay varias líneas NewCamd conectadas que sirven el mismo CAID:PROVID, Candela elige automáticamente la que tenga menor latencia media histórica. Antes siempre usaba la primera conectada. La latencia se mide desde el envío de la ECM hasta la recepción de la CW y se actualiza con fórmula EMA (70 % histórico, 30 % muestra nueva) en cada respuesta correcta. Sin datos previos el reader se considera de alta latencia hasta que acumule al menos una medición.
  • Selección por latencia en lectores MGcamd cliente: mismo mecanismo aplicado a las conexiónes MGcamd. El reader con menor avg_latency_ms recibe siempre la ECM primero entre los compatibles con el CAID.
  • Orden por latencia en lectores de tarjeta hardware: cuando hay varios lectores físicos compatibles con el CAID y MCRR está desactivado, los lectores se ordenan por avg_latency_ms ascendente antes de intentarlos. El más rápido históricamente se intenta primero; el resto actúan como failover en orden de velocidad. Cuando MCRR está activo se respeta su asignación determinista por SRVID.
  • Medición de latencia en lectores hardware: nuevo campo avg_latency_ms en hw_reader_t. Se registra el tiempo real de cada ciclo APDU con CLOCK_MONOTONIC y se actualiza en cada descifrado éxitoso (incluyendo el flujo de dos pasos SECA ins3c/ins3a).
  • Uniformidad total entre fuentes: la prioridad por latencia aplica de forma homogénea a hardware físico, NewCamd cliente y MGcamd cliente. Los peers P2P Candela ya disponían de este mecanismo (scoring AMPE/HLS con card_map[k].avg_latency_ms). Con esta actualización todas las fuentes locales y remotas se rigen por el mismo criterio.

AMPE - Multi-Path ECM sin límite de peers

  • Eliminado el tope de 3 en ecm_multipath: el parámetro ya acepta cualquier valor entero positivo. Antes estaba limitado a un máximo de 3 en config.c y en el watchdog; ambas restricciones han sido eliminadas. Los arrays de selección internos (best_idxs, best_scores) son ahora del tamaño de MAX_ACTIVE_PEERS (256) para acomodar cualquier configuración.
  • Modo ilimitado con valor 0: ecm_multipath = 0 envía la ECM a todos los peers elegibles simultáneamente (misma semántica que antes pero sin cota). Útil en nodos de alta disponibilidad que quieren máxima redundancia sin configurar un número exacto de peers.
  • Valor por defecto cambiado de 1 a 3: instalaciones nuevas arrancan con AMPE activo envíando a los 3 mejores peers en paralelo. Las instalaciones existentes que tenían ecm_multipath: 1 conservan su valor.
  • Control WebIF actualizado: el selector de opciones fijas (1/2/3) se ha sustituido por un campo numérico libre con rango 0-64. El tooltip describe el nuevo comportamiento del modo 0 y del rango ampliado.

Límite de propagación de tarjeta por distancia (card_hop_limit)

  • Nuevo parámetro card_hop_limit: límite global de hop aceptado al recibir el card_map de un peer P2P. Una tarjeta cuyo campo hop sea mayor que el límite configurado se descarta directamente: no se almacena, no se usa y no se reenvía a otros peers. Permite controlar con precisión a cuántos saltos de distancia puede llegar una tarjeta compartida.
  • Semántica: 0 = sin límite (comportamiento anterior), 1 = solo tarjetas directas (hop 0 y 1), N = hasta N saltos. El límite absoluto de propagación anómala (hop > 10) se mantiene independientemente de este parámetro.
  • Control WebIF: campo numérico en la sección AMPE junto a ecm_multipath. Rango 0-10. Hint contextual explicando el efecto de cada valor.
  • Traducciones completas en los 6 idiomas del WebIF.

Motor de prioridad candela.prio (ALLOW/SKIP)

  • Nuevo fichero de reglas candela.prio: motor de enrutamiento ECM por CAID:PROVID[:SRVID] con formato propio de Candela. Dos tipos de regla: ALLOW prioriza el canal y activa modo lista blanca si existe alguna regla ALLOW (las ECM que no coincidan con ningúna se rechazan), y SKIP descarta incondicionalmente la ECM sin consultar lector ni red. Comodines: omitir SRVID aplica la regla a cualquier servicio del CAID:PROVID; PROVID 000000 coincide con cualquier proveedor.
  • Módulo src/protocol/ecm_routing.c/h: implementación completa del parser, evaluador de reglas, add/remove atómico (reconstrucción del fichero sin corrupción), recarga en caliente sin reinicio del daemon. Hasta 512 reglas simultáneas. Thread-safe con mutex dedicado. Compatible con todos los targets: Linux, Windows/MinGW, MIPS, ARM.
  • Integración en el motor ECM: las reglas SKIP y la lista blanca ALLOW se evalúan en is_request_allowed() antes que los filtros por usuario. Una ECM SKIPpeada se descarta para todos los clientes incluyendo los locales.
  • Panel de reglas en la pestaña Diagnóstico: tabla de reglas activas con tipo coloreado (ALLOW en verde, SKIP en rojo), CAID, PROVID, SRVID y comentario. Botón de eliminación por regla. Formulario de alta directa (tipo/CAID/PROVID/SRVID/comentario) sin editar el fichero manualmente. Botónes ALLOW/SKIP por fila en la tabla de sugerencias para aplicar directamente las sugerencias del modo preview como reglas prio.
  • Editor de texto en la pestaña Editor: visualización y edición del fichero candela.prio como texto plano, mismo patrón que el resto de editores (SoftCam.Key, Services, SrvID, ProvID). Guardar recarga las reglas en memoria sin reiniciar.
  • API REST completa: GET /api/diag/prio (lista JSON), POST /api/diag/prio/add, POST /api/diag/prio/remove, GET /api/diag/prio/raw y POST /api/diag/prio/raw.
  • Traducciones completas en los 6 idiomas del WebIF (es/en/de/fr/it/pt) para todas las claves del nuevo panel.
  • Fichero de ejemplo candela.prio incluido en la distribución con comentarios explicativos del formato y ejemplos comentados listos para activar.

Correcciones de robustez y seguridad

  • JSON injection en panel de eventos de seguridad: los campos ip, url y usuario del ring buffer de eventos se escapan ahora con wf_json_escape() antes de serializarlos en disco y en la respuesta /api/security/events. Una URL de autenticación fallida con comillas o caracteres especiales podía corromper el JSON del panel de alertas.
  • Protección de mutex en variables de sesión del WebIF: las variables estáticas wf_new_token, wf_has_new_session y wf_emit_csrf se leen y escriben ahora bajo wf_smutex en add_security_headers() y en el bloque de autenticación de ahc(). El código es robusto ante configuraciones MHD con múltiples hilos.
  • Guardia de underflow en buffer JSON de peers (/api/status): el cálculo del espacio restante para insertar entradas NC/MG en el buffer de peers se hace ahora con guardia explícita contra underflow de size_t en buffers casi llenos.
  • JSON injection y escritura fuera de límites en módulo Forense: en /api/forensics/mosc_apply y /api/forensics/mosc_clone, el campo result_msg se escapa ahora con wf_json_escape() antes de incluirse en la respuesta, y cw_len_out se acota a 16 antes del bucle de conversión a hex para prevenir escritura fuera del buffer de 33 bytes.
  • RAND_bytes en modo fuzz del simulador ECM forense: el offset y el byte de mutación en /api/forensics/ecm_sim?fuzz=1 usaban rand() sin semilla. Sustituido por RAND_bytes() para garantizar resultados impredecibles incluso en sesiones de testing repetidas.
  • Parser JSON de configuración acotado por objeto: las funciones parse_accounts() y parse_newcamd_readers() en config.c localizan ahora el cierre } del objeto actual antes de buscar cada campo. Antes, si un objeto carecía de un campo (por ejemplo pass), el strstr avanzaba al objeto siguiente y podía asignar credenciales equivocadas a la cuenta o servidor incorrectos.
  • BCryptGenRandom como fallback PRNG en Windows: si RAND_bytes() falla durante la generación del nonce de autenticación P2P, Candela usa ahora BCryptGenRandom() antes de recurrir a rand(). La biblioteca bcrypt ya estaba enlazada en PLATFORM_LIBS.
  • Validación de IP al restaurar failban desde disco: failban_load() descarta entradas cuyo campo ip no sea una dirección IPv4 o IPv6 válida según inet_pton(). Previene estados inconsistentes si failban.json contiene datos malformados.
  • Comportamiento indefinido en filtro IP/CIDR corregido: en newcamd_server.c y mgcamd_server.c, el prefijo de red leído de config se acota al rango [0, 32] antes del desplazamiento de bits ~0u << (32 - prefix). Un prefijo fuera de rango producía comportamiento indefinido en C.
  • Verificación de certificado SSL en descarga de claves AES IPTV: la conexión HTTPS a la URL de candela.aeskeys activa ahora SSL_CTX_set_verify(SSL_VERIFY_PEER) y SSL_CTX_set_default_verify_paths(). Antes el handshake TLS no verificaba el certificado del servidor, permitiendo sustitución de claves en la red.
  • candela_test con sufijo de arquitectura en el build system: el simulador DVBAPI se genera ahora con el mismo sufijo de arquitectura que el binario principal (ejemplo: candela_test.arm-cortexa15hf-vfp-neon). El nombre se deriva automáticamente de CANDELA_BIN via patsubst en el Makefile; build_common.sh lo copia a Distribution/ junto al binario principal.

Proxy IPTV multicast/unicast - reemplazo de udpxy

  • Nuevo módulo src/iptv/iptv_proxy.c/h: proxy HTTP compatible con la API de udpxy integrado directamente en el daemon. El STB apunta a http://candela_ip:8088/udp/239.x.x.x:8208 (o /rtp/) en lugar de a un proceso udpxy externo. Puerto configurable (iptv_proxy_port, por defecto 8088). Activado con enable_iptv_proxy: 1 en candela.json.
  • Soporte completo de streams sin puerto: URLs tipo /udp/239.x.x.x sin puerto explícito usan el puerto 1234 por defecto (habitual en multicast IPTV). También acepta relay HTTP directo: /http://host/stream o /?url=http://host/stream para streams unicast o HTTP directos que no sean multicast.
  • Header RTP variable según RFC 3550: el proxy parsea correctamente los campos V/P/X/CC del header RTP y salta la longitud exacta (12 + CC×4 + extensión si X=1) en lugar de un offset fijo de 12 bytes. Streams con CSRC y extensiones de cabecera ya no pierden el byte de sincronismo 0x47.
  • Buffer UDP amplio para multicast de alta densidad: SO_RCVBUF = 4 MB en el socket de recepción. Absorbe ráfagas de hasta ~15 Mbps sin pérdida de datagramas antes de que el hilo los procese.
  • Descifrado AES-128 transparente: si existe clave en candela.aeskeys para el SRVID del stream, los paquetes TS se descifran antes de enviarse al cliente. Compatible con los modos AES-128-CBC, ECB, CTR y auto-detección del motor CSA.
  • Estadísticas en tiempo real en el WebIF: nueva card visible en el monitor cuando el proxy está activo. Muestra por stream: grupo multicast, IP del cliente, nombre del canal (si se resuelve), bitrate en KB/s y estado AES. Endpoint GET /api/iptv/streams.
  • Pills de estado en la cabecera del panel: indicadores IPTV y HLS en la barra de módulos activos con el puerto correspondiente, igual que StreamRelay y DVBAPI.

Proxy HLS con descifrado AES-128-CBC transparente

  • Nuevo módulo src/iptv/hls_proxy.c/h: proxy HTTP que intercepta streams HLS y descifra los segmentos AES-128-CBC en vuelo antes de enviarlos al player. El player apunta a http://candela:8089/http%3A%2F%2Foriginal.url/playlist.m3u8 o /?url=http://.... Puerto configurable (hls_proxy_port, por defecto 8089). Activado con enable_hls_proxy: 1.
  • IV correcto por segmento (RFC 8216 §5.2): cuando #EXT-X-KEY no incluye IV=, el IV de cada segmento se calcula como media_sequence + seg_idx en big-endian de 16 bytes. Cada segmento tiene su propio IV embebido en la URL proxy reescrita (?iv=HEX32), garantizando el descifrado correcto sin depender del estado de la sesión.
  • Eliminación de padding PKCS#7: tras el descifrado AES-128-CBC, el padding se valida (todos los bytes iguales, valor 1-16) y se elimina del final del segmento antes de enviarlo al player. Sin esto el último paquete TS del segmento contiene basura.
  • AES-128-CBC vía OpenSSL EVP: aes128cbc_decrypt_raw() usa EVP_aes_128_cbc() con EVP_CIPHER_CTX_set_padding(0). Correcto, portable y con aceleración AES-NI automática en x86/ARM con soporte hardware.
  • HTTPS para URIs de clave: el fetcher interno usa SSL_new/SSL_connect/SSL_read con el OpenSSL ya disponible en el daemon. La mayoría de operadores sirven las claves AES por HTTPS; antes fallaba silenciosamente.
  • Decodificación de Transfer-Encoding: chunked: muchos CDNs devuelven segmentos o manifiestos con Transfer-Encoding: chunked. El fetcher decodifica el formato in-place antes de procesar el contenido. Sin esto el segmento incluye los marcadores de chunk y el TS queda corrupto.
  • Caché de clave por stream: la clave AES (y su IV) se almacena en un caché de 32 entradas indexado por URL base. Los segmentos sucesivos del mismo stream no re-descargan ni re-buscan la clave en disco. Reduce 30+ lookups/minuto a cero para streams continuos.
  • Rotación de claves en m3u8 (múltiples #EXT-X-KEY): el parser procesa todos los bloques #EXT-X-KEY del manifiesto y construye una tabla de rangos key_range_t[] donde cada rango indica desde qué segmento aplica una clave concreta. Canales con rotación rápida de clave ya no fallan a partir del segundo bloque.
  • Detección por contenido: si la URL no contiene .m3u8/.m3u/playlist/manifest pero el cuerpo empieza por #EXTM3U, el proxy lo trata igualmente como manifiesto HLS. Cubre streams CDN con URLs opacas sin extensión.
  • Auto-guardado de claves en candela.aeskeys: cuando se descarga una clave desde la URI del #EXT-X-KEY, se guarda automáticamente en candela.aeskeys con un SRVID derivado de la URL del stream para estar disponible en sesiones futuras sin re-descarga.
  • Reescritura de manifiestos: las URLs de los segmentos en el m3u8 se reescriben para pasar por el proxy con el IV codificado. El player nunca ve ni contacta directamente con el servidor origen; todo pasa por Candela.

Correcciones de bugs DVBAPI y detector de CW falsas

  • Bug: actividad DVBAPI desaparecía con socket TCP o ruta no estándar: el array pfd[] no se reiniciaba entre iteraciones del bucle poll(). El campo revents de la iteración anterior permanecía, causando que POLLHUP de una conexión cerrada se procesara como actividad en la siguiente iteración. Corregido con memset(pfd, 0, sizeof(pfd)) al inicio de cada ciclo y con contador dinámico de listeners (1 o 2) para no pasar fd=-1 a WSAPoll en Windows.
  • Bug: CW BISS rechazadas como FakeCW[MITADES_IGUALES]: el detector de CW falsas comprobaba que los dos halfwords de 8 bytes fuesen distintos. BISS usa por diseño la misma clave de 8 bytes para los periodos even y odd, por lo que ambas mitades son idénticas. Corregido: CAID 0x26xx queda exento de esta comprobación.
  • Bug: contadores ECM OK/FAIL del lector MOSC siempre a cero: el flujo MOSC en reader_hw.c nunca incrementaba hw_readers[i].ecm_ok ni hw_readers[i].ecm_fail. El dashboard mostraba 0/0 aunque el lector estuviera resolviendo correctamente. Corregido con los incrementos en los puntos de retorno de emm_mosc_try_ecm.
  • Bug: diagnóstico ECM se rellenaba inmediatamente tras el reset: el watchdog reintentaba las ECMs pendientes en milisegundos, rellenando ecm_diag_table y ecm_suggest_table antes de que el usuario viera el estado reseteado. Añadido un cooldown de 10 segundos (DIAG_RESET_COOLDOWN_MS) tras cualquier reset: durante ese período no se escriben nuevos registros de diagnóstico.

Logging ECM/CW detallado

  • Logging detallado de ECM y CW: nuevo flag log_cw en configuración. Cuando está activo, cada resolución ECM emite una línea (ecm) USER (DATA=CAID@PROVID/SRVID ECM_L:XX) - CANAL y otra (cw) USER (DATA=CAID@PROVID/SRVID CW=32HEX HOP=HH): OK (NNms) by SOURCE - CANAL. El hex bruto del ECM y la CW se emite siempre a nivel LOG_DEBUG cuando el modo debug está activo.
  • Split CW0/CW1: cuando tanto log_cw como log_ecm están activos simultáneamente, se añade una línea adicional con la CW partida en los dos halfwords de 8 bytes.
R41 Centinela Mayo 2026

Mejoras en el WebIF y correcciones de comportamiento

  • Bug corregido - SoftCam emulador: desactivar ahora detiene realmente el emulador: cuando el emulador SoftCam se desactivaba desde CSA, el fichero SoftCam.key seguía funciónando en memoria, los lectores de emulador aparecían como READY en el dashboard, las claves seguían visibles en la sección SoftCam Keys y los ECMs seguían resolviéndose. Corregido: al desactivar el emulador se liberan las claves de la RAM, los lectores emu/constcw desaparecen del dashboard y el panel SoftCam Keys queda oculto. Activarlo de nuevo recarga el fichero de claves automáticamente.
  • Bug corregido - DVBAPI: el socket DVBAPI se detiene y arranca correctamente al activar/desactivar desde el WebIF: cambiar el estado de DVBAPI en CSA sin reiniciar el daemon ahora detiene y arranca el listener DVBAPI de forma efectiva. Antes el socket seguía en escucha aunque el flag estuviera a 0.
  • Nueva opción - Toggle StreamRelay independiente en CSA: StreamRelay tiene ahora su propio interruptor en la sección CSA del WebIF, independiente del DVBAPI. El campo enable_streamrelay se persiste en candela.json. El toggle se desactiva si DVBAPI está apagado (StreamRelay requiere DVBAPI activo para funciónar).
  • Dashboard se refresca solo tras guardar configuración CSA: al guardar cualquier cambio en la pestaña CSA (activar/desactivar emulador, DVBAPI, StreamRelay), el dashboard se actualiza automáticamente sin necesidad de Ctrl+F5. Los indicadores de módulo reflejan el nuevo estado en tiempo real.
  • Botón "Desbloquear todas" en IPs bloqueadas: el panel de seguridad incluye ahora un botón para desbloquear todas las IPs bloqueadas de una sola acción, sin tener que desbloquearlas una a una. La acción se procesa en el backend vía POST /api/security/unblock_all.
  • Contador de IPs bloqueadas en la pestaña Alertas: el botón de la pestaña "Alertas" del panel de seguridad muestra ahora un badge naranja con el número de IPs actualmente bloqueadas (🚫 N), además del badge rojo de eventos de seguridad no leídos. Ambos badges son independientes y solo aparecen cuando el valor es mayor que cero.
  • Bug corregido - Card Map P2P: los peers reciben el mapa actualizado al deshabilitar el emulador: al desactivar el emulador SoftCam, Candela emitía un CMD_CARD_MAP inmediato a todos los peers conectados para retirar las entradas del emulador. Sin este broadcast, los peers mantenían el card map antiguo con las entradas emu hasta la siguiente reconexión.
  • Bug corregido - Pills de módulos reactivas en el dashboard: los indicadores de DVBAPI, SoftCam y StreamRelay del panel superior ahora reflejan el nuevo estado al instante al guardar la configuración CSA, sin necesidad de F5. La pill de StreamRelay estaba hardcodeada como siempre activa - ahora es reactiva y refleja correctamente el estado real.
  • Bug corregido - Topología de Red P2P oculta lectores emu al deshabilitar el emulador: la vista "Topología de Red P2P" de la pestaña Monitor seguía mostrando el lector emu/constcw como activo tras deshabilitar el emulador. Ahora desaparece inmediatamente al guardar sin necesidad de pausarlo manualmente.
  • Bug corregido - Servidor P2P mantenia el conteo antiguo de tarjetas tras deshabilitar el emulador: en la vista "Topología de Red P2P", la entrada SERVIDOR mostraba el número de tarjetas del momento de la conexión incluso después de deshabilitar el emulador debido a un bucle de reshare (eco) en conexiónes locales (loopback). Añadido filtro de enrutamiento Split Horizon por IP que bloquea el re-anuncio de tarjetas hacia la misma IP de la que provienen. Ahora el conteo se actualiza instantáneamente en el dashboard y topología al activar/desactivar el Softcam sin generar bucles P2P.

Mejoras en servidores NewCamd / MGcamd

  • ECM Coalescing para clientes NewCamd/MGcamd: cuando varios clientes conectados solicitan el mismo ECM simultáneamente, solo se lanza una única resolución al lector. El resto de clientes espera en un condvar y recibe la misma CW sin duplicar peticiónes al hardware. Pool de 128 slots compartido entre ambos protocolos. Reduce carga en lectores físicos y elimina contención bajo conexiónes múltiples.
  • Detección y purga automática de CW mala: si un cliente reenvía el mismo ECM en menos de 5 segundos, Candela interpreta que la CW anterior era inválida, la elimina de la caché de forma selectiva y fuerza una nueva resolución al lector. La detección es por hash MD5 del payload del ECM. Compatible con la configuración global e individual de verificación de CRC: la purga solo actúa cuando el sistema concluye que la CW fue mala, sin anular la lógica de disablecrccws ni disablecrccws_only_for.
  • Push proactivo de CW a clientes: cuando la caché recibe una CW (por cualquier vía: lector local, P2P, reader NC/MG), los clientes NewCamd/MGcamd interesados en ese servicio son notificados al instante a través de un pipe interno por cliente. El thread de cada cliente lo monitoriza en el select() principal. El tiempo de entrega cae a microsegundos desde que la CW está disponible, sin ningún polling. La notificación filtra por hash del ECM para no despertar clientes esperando un período de cifrado diferente (odd vs. even).
  • Métricas de calidad por cliente en el WebIF: el panel de clientes NewCamd/MGcamd conectados muestra en tiempo real el tiempo de resolución del último ECM en milisegundos y el contador de fallos consecutivos sin CW válida. Disponible tanto en la vista de escritorio (tooltip sobre el badge de protocolo) como en la vista móvil.
  • Validación por consenso en Modo Candela: cuando Modo Candela está activo y hay al menos 2 peers P2P conectados, la CW obtenida se contrasta contra la red P2P antes de envíarse al cliente. Si la CW no coincide con el consenso de la red, se descarta y se responde con NAK. Protección efectiva ante upstreams comprometidos que inyectan CWs envenenadas. El consenso no añade latencia perceptible en condiciones normales (timeout máximo 800 ms, solo activo con peers Candela reales).

Compatibilidad Windows (MinGW/MSYS2)

  • Compilación limpia en MinGW64/MSYS2: los cinco ficheros de protocolo (newcamd_server.c, mgcamd_server.c, newcamd_client.c, mgcamd_client.c, newcamd_common.c) usaban funciónes POSIX directas (fcntl, pipe, read, write, close, sleep) que no existen en Winsock. Sustituidos por macros portables en utils/net.h: NET_PIPE_OPEN/READ/WRITE/CLOSE (desactivados en Windows), NET_SET_NONBLOCK, NET_SETSOCKOPT, NET_GETSOCKOPT, net_sleep_sec. En Windows los pipes de push se deshabilitan silenciosamente; el resto del código sigue compilando y funciónando sin cambios de comportamiento.
  • Cast de setsockopt/getsockopt/send/recv en Windows: Winsock exige const char* en lugar de void* en varios syscalls. Corregido con las macros de net.h que aplican el cast solo cuando _WIN32 está definido, sin afectar a Linux/MIPS/ARM.
  • atomic_compat.h: soporte correcto en Clang: Clang reporta __GNUC__=4 __GNUC_MINOR__=2 en modo compatibilidad GCC, lo que hacía que la guardia de version fallara y se usaran las macros de fallback en lugar de <stdatomic.h>. Añadido defined(__clang__) a la condición para que Clang use atomics nativos.
  • Warnings OpenSSL 3.0 en MinGW64 eliminados: MD5() y SHA256_Init/Update/Final de bajo nivel migrados a la API EVP moderna (EVP_Digest, EVP_MD_CTX), que no está deprecada en OpenSSL 3.0. Las funciónes DES (DES_set_odd_parity, DES_set_key_unchecked, DES_ede2_cbc_encrypt) son fijas por el protocolo NewCamd y no tienen equivalente EVP; silenciadas con #pragma GCC diagnostic solo alrededor de esas llamadas.
  • Warnings -Wstringop-truncation en MinGW64 eliminados: los strncpy con límite igual al tamaño del campo menos uno en newcamd_server.c y mgcamd_server.c sustituidos por snprintf, que no genera el warning y hace innecesarios los [N]='\0' manuales.

Rendimiento del WebIF

  • Compresión gzip de assets con caché en memoria: los ficheros estáticos del WebIF (HTML, JavaScript, CSS, traducciones) se comprimen con gzip la primera vez que se sirven y el resultado queda cacheado en RAM. Las peticiónes siguientes se sirven directamente desde la caché sin ningún proceso de compresión. La carga de la interfaz es más rápida y la CPU del dispositivo no sube en cada recarga.
  • Compresión gzip del log: el endpoint /api/log devuelve ahora la respuesta comprimida cuando el navegador lo soporta. El log puede contener cientos de líneas de texto; la compresión reduce el volumen transferido entre el daemon y el navegador en torno al 80-90%.
  • Throttle de polling cuando el WebIF está en segundo plano: cuando el tab del navegador con el WebIF pierde el foco o queda oculto, el intervalo de actualización pasa de 2 segundos a 30 segundos. Al volver al tab, el polling vuelve a 2 segundos de forma inmediata. Reduce la carga generada en el daemon cuando nadie está mirando la interfaz.

Correcciones de seguridad

  • Heap overflow en CMD_ECM_REQ: un peer P2P autenticado podía envíar un ECM de hasta 8167 bytes (límite LZ4) desbordando el buffer interno ecm_data[2048]. Corregido: válidación de longitud antes de pasar a process_ecm_request; el peer es desconectado y baneado si supera MAX_ECM_SIZE.
  • JSON injection en volcado de configuración: los campos string del fichero de configuración (http_user, http_pwd, ghost_ua, user/pass de cuentas y servidores) se escribían sin escapar comillas ni barras. Corregido con json_escape_str() aplicada a todos los campos string antes del volcado.
  • Race condition en contador de clientes activos NC/MG: el bloque de comprobación e incremento de nc_active_clients / mg_active_clients en los hilos listener no estaba bajo mutex. Corregido: toda la secuencia check-increment-decrement protegida con nc_live_mutex / mg_live_mutex.
  • Use-after-free en Single Session Enforcement: al detectar un clon de sesion en CMD_HELLO INCOMING y CMD_HELLO_ACK, se marcaba peer_list[i].active = 0 directamente sin llamar a peer_remove(), dejando ecdh_priv y card_map_tommy sin liberar. Corregido en ambos puntos con patrón collect-then-evict fuera del mutex.
  • Race condition en push notify NC/MG: el hilo de cliente leía last_ecm_hash sin mutex, en carrera con nc_live_remove que hace memset sobre la misma estructura. Corregido copiando el hash bajo mutex antes de usarlo.
  • Race condition en audit_log: el bloque de cifrado leía campos del ring buffer tras liberar el mutex, en carrera con otro hilo que podía haber avanzado audit_head. Corregido capturando los campos en variables locales dentro del mutex.
  • parse_local_readers cross-field: el parser de lectores locales buscaba campos con strstr sin delimitar al objeto JSON actual, pudiendo mezclar claves criptograficas entre lectores distintos si algún campo estaba ausente. Corregido copiando cada objeto a un buffer acotado por } antes de parsear.
  • ecmdb_add crecimiento ilimitado en disco: cada CW nueva hacía append al fichero candela.ecmdb aunque la entrada ya existiera en RAM, pudiendo llenar el disco. Corregido: cuando el fichero supera el máximo, se reescribe completo desde la tabla en RAM.
  • Crash en descarga de backup de config: si el fichero no era legible, ftell devolvía -1 y se pasaba ese valor a malloc y a MHD. Corregido con válidación de tamaño antes del malloc.
  • JSON injection en nombres de canal: el nombre de canal del fichero candela.srvid se incluía sin escapar en el JSON de la API de demuxes. Corregido con json_escape_str().
  • PRNG cpm_xorshift32 thread-safe: el generador xorshift32 de CPM se actualizaba sin sincronizacion desde multiples hilos. Corregido con bucle CAS atomic (atomic_compare_exchange_weak_explicit).
  • Daemon no arranca en entornos sin entropia: fallo de RAND_bytes en entornos chroot sin /dev/urandom mataba el daemon con abort(). Sustituido por fallback xorshift con LOG_WARNING.
  • Otras correcciones menores: malloc sin check en proto_send_packet e init de caché; buffer LZ4 ampliado de 8192 a 8193 bytes con NUL forzado; JSON injection en borraoff_save; strncpy sin terminador NUL en jail_record y mgcamd_server; warning al arrancar si se usan credenciales WebIF por defecto (admin/candela); extract_json_int comprueba ahora el retorno de sscanf antes de asignar.
R37 Alcazar Mayo 2026

Nuevas funciónalidades

  • NETMAP (CMD_NET_MAP): descubrimiento de topología completa por gossip P2P puro. Sin credenciales en transito.
  • NSS (Node Status Signal / CMD_GOING_DOWN): apagado planificado sin pantalla negra en los peers conectados.
  • NRS (Node Reputation Score): scoring 0-100 de upstreams por latencia EWMA, estabilidad y actividad ECM. Exclusión automática de peers degradados.
  • Anti-Eclipse: límite de peers activos por bloque /24 (max_peers_per_subnet) para evitar ataques de eclipse de subred.
  • LAN Discovery: detección automática de instancias Candela en red local via beacon UDP broadcast (puerto 52700).
  • AMPE (Adaptive Multi-Path ECM): consulta paralela de los N mejores peers HLS por ECM (ecm_multipath 1-3). Reduce latencia en canales de alta demanda.

Anti-DPI & Seguridad

  • TCR - TCP Connection Rotation: rotación transparente de la sesión TCP con cada upstream en una ventana aleatoria de [N, 4×N] horas (tcp_rotation_h, opt-in, default 0). Elimina la firma de duración de sesión -días vs segundos HTTPS- sin interrumpir el servicio downstream. Completamente íntegrado con el mecanismo de F3: las rotaciones TCR no incrementan el contador de reconexiónes del dashboard. Con PSN+ETJ+CTF+TCR activos el tráfico Candela es indistinguible estadísticamente de HTTPS ante cualquier nivel de análisis: DPI en tiempo real, análisis de tamaño de paquete, autocorrelación temporal y metadatos de duración de sesión.
  • Anti-DPI Suite - WebIF: controles PSN, ETJ, CTF y TCR íntegrados en el panel de configuración local (Transporte / Anti-DPI Suite). Inputs con tooltips descriptivos; tcp_rotation_h con ventana [N, 4×N] horas. Interfaz completamente traducida a los 6 idiomas soportados (es, en, de, fr, it, pt).
  • Anti-DPI Suite: implementado Packet Size Normalization (PSN) con buckets fijos (256, 512, 1024, 1448 bytes), ECM Timing Jitter (ETJ) aleatorio configurable y Constant Traffic Floor (CTF) para inyección de chaff (tráfico constante).
  • Corrección OOB read en parsing de AUTH_HELLO.
  • NULL check post-malloc en compresor LZ4.
  • strtol en parsers de puerto para evitar desbordamiento de entero.
  • Fix crítico failban: failban_check() usaba now > block_until para expirar bans; con bans permanentes (block_until=0) la condición era siempre verdadera - el ban manual se limpiaba en la primera comprobación permitiendo el acceso. Corregido con !e->manual_block && e->block_until > 0.
  • Expulsión inmediata en ban manual: failban_block_manual() llama ahora a peer_kick_by_ip() para desconectar conexiónes activas de la IP en el momento del baneo.
  • failban_preload(): el estado de bans se carga desde disco antes de arrancar el hilo P2P - elimina la ventana entre apertura del socket y aplicación de bans persistentes.
  • Bans escalonados: 1er ban: 1h · 2º: 12h · 3º: 7 días · 4º+: permanente. Campo ban_count por IP persistido en failban.json.
  • failban_compact(): compactación automática de la tabla failban al 90% de capacidad. FAILBAN_MAX_ENTRIES aumentado de 256 a 1024.
  • AuthWDG ban-check: el watchdog de autenticación comprueba también si la IP está baneada post-conexión, expulsando el peer sin esperar el timeout de 30s.
  • Rate-limit en log de rechazos por IP baneada: 1 aviso/60s por IP con contador acumulado.

Correcciones

  • Contador de reconexiónes - F3 rekey: el rekey ECDH planificado cada 24 horas ([F3]) desconectaba y reconectaba el peer saliente incrementando el contador de reconexiónes del dashboard, induciendo al usuario a pensar que el servidor había caído. Corregido marcando internamente las reconexiónes planificadas para que no incrementen el contador; solo las caídas reales lo hacen.
  • Campana de alertas sin badge al abrir el WebIF: el badge de la campana de seguridad solo se mostraba para eventos de los últimos 5 minutos. Si el usuario abría el WebIF con eventos no leídos más antiguos, el badge no aparecía sin hacer Ctrl+F5. La API /api/security/events/count ahora devuelve también unread (total de eventos no leídos sin límite temporal); el frontend usa ese campo para el badge.
R36 Vigia Abril 2026

Nuevas funciónalidades

  • PIR (Peer Intelligence Ring): comparticion de baneos entre nodos autenticados via CMD_REP_SHARE. Los peers comparten inteligencia sobre IPs maliciosas en tiempo real.
  • CFI (CAS Fingerprint Inversion): retardo mínimo plausible por CAID para difuminar la firma de timing DVB. Evolucion de ERD con latencia hasta 6x menor.
  • CW Cycle Check avanzado por CAID con maxlist, keeptime y sensibilidad configurables.
  • Double Check selectivo por CAID (dcheck_caid).
  • Caché CW/ECM con límites de memoria configurables (cw_cache_memory, ecm_cache_memory).

Seguridad

  • Nonce monotónico anti-birthday: contador uint64 por peer XORado en nonce ChaCha20. Elimina colisiones de nonce.
  • Race condition en tokens WebIF corregida: generación bajo mutex, explicit_bzero de passwords en memoria.
  • Audit log cifrado de eventos de seguridad. Alertas configurables por umbral de fallos y latencia.
R35 Atalaya Abril 2026

Nuevas funciónalidades

  • CPM (Adaptive Pulse Masking): inyecta CMD_PADDING de tamaño aleatorio cada 2–3.5s por peer. Destruye la firma temporal del criptoperíodo DVB (~10s).
  • DPM (Decoy Port Multiplexing): respuesta HTTP/Nginx falsa ante escaners de red. El puerto Candela parece un servidor web normal.
  • ECDH-first Handshake (Protocolo v2): las credenciales viajan siempre bajo clave ECDH efímera X25519. El servidor rechaza cualquier CMD_HELLO sin ECDH previo activo.
  • ECDH Rekey transparente sin corte TCP. Rekey automático en cada N ECMs o tras T segundos.
  • FakeCW blacklist y penalización automática de peers que envían CWs falsas o de baja entropía.
  • DoubleCheck por consenso de peers upstream (CWS). La CW mayoría se entrega; el peer divergente baja en NRS.
  • Reshare enforcement infalsificable a nivel de protocolo. Los campos no_reshare del CMD_CARD_MAP no pueden ser falsificados por el downstream.
  • Failban CGNAT: prevención de baneos accidentales en IPs compartidas (rango /24 configurable).
  • Anti-Scanner: honeypot CAIDs configurables + ventana deslizante de CAID probing. Detección y baneo instantáneo de bots.
R34 Abril 2026
  • WebIF embebido en binario. Assets LZO1X comprimidos. Sin dependencias externas.
  • Panel en tiempo real: estado de peers, ECMs/s, latencia, logs de sesion.
  • Autenticación WebIF por token rotatorio. HTTPS TLS 1.3 nativo.
  • API REST interna (~98 endpoints) para íntegración con herramientas externas.
  • Tema claro/oscuro con persistencia en localStorage.
  • CTC (Candela Transport Camouflage): Fake TLS 1.3 Record Layer con ALPN, cipher suites aleatorios y SNI de CDN. El tráfico Candela es indistinguible de HTTPS para cualquier inspector DPI o firewall.
R33 Abril 2026
  • ETO (ECM Timing Oracle): perfilado estadístico de latencia por reader/peer y CAID. Detecta tarjetas degradadas, emuladores (timing uniforme vs. varianza real) y cambios de clave. Histograma 16 cubos + anomalías 3σ.
  • CWS (Consensus Shield): votación N-peer sobre la CW. La CW ganadora por quórum se entrega; el peer divergente se penaliza. Neutraliza CWs envenenadas de operadoras.
  • ERD (ECM Replay Detector): retardo sintético adaptativo en cache hits para imitar el timing real de la tarjeta (~300ms). Evita detección por respuestas ultrarrápidas (<5ms).
  • EFG (ECM Flow Guard): anti-cascade con ring buffer lock-free por peer. Detecta resharing por diversidad de SIDs. Strict Cache Mode dinámico con auto-recovery. Ignora zapping legítimo.
  • CWRID (CW Replay Detector): ventana deslizante de hashes de CW. Detecta reutilización entre ECMs distintas y entrega lateral de la misma CW a múltiples canales.
  • EEA (ECM Entropy Analyzer): entropía Shannon de cada CW por CAID. Alerta si H < 7.0 bits/byte - CW constante o de patrón fijo indica fake CW o fallo CAS.
  • ECLD (Latency Decomposer): timestamps T0–T4 (recibida, cache lookup, upstream RTT, respuesta, entregada). Desglose completo de la cadena ECM por tramos.
  • OLG (ECM Overlap Guard): entrega la última CW válida como puente mientras el upstream resuelve la ECM nueva. Elimina pantalla negra en cache miss.
  • Adaptive ECM Timeout por CAID usando media ETO×3. Canales rápidos no esperan el timeout global; canales lentos no se cortan prematuramente.
R32 Abril 2026
  • Red P2P - Identidad y Acceso: p2p_allowed (IP allowlist por rangos), p2p_max_conn_per_ip (rate-limit de conexiónes entrantes), panel "Seguridad Avanzada P2P" en mantenimiento.
  • Ghost UA anti-fingerprint: el nodo no revela detalles internos en la negociación hasta autenticación completada.
  • Failban automático íntegrado con alertas por umbral configurable de intentos fallidos.
  • Audit log cifrado de eventos P2P: logins, acciones WebIF y cambios de configuración (ChaCha20-Poly1305, clave derivada del NodeID).
R31 Abril 2026
  • Mensajería P2P cifrada: canal de comunicación directo entre peers autenticados. Comandos CMD_MSG_SEND / CMD_MSG_ACK. Zero-disk: los mensajes existen solo en RAM y desaparecen al cerrar Candela.
  • Cifrado de mensajes con la clave de sesión ChaCha20-Poly1305 existente - sin handshake adicional.
  • Panel de mensajería en WebIF. Activable con enable_p2p_chat. Requiere peers con R31+.
R26 - R30 Enero - Marzo 2026
  • R30 - PFS / ECDH X25519: Perfect Forward Secrecy completo. Clave de sesión efímera negociada por ECDH X25519 en cada conexión - el compromiso de una sesión no compromete las anteriores ni las futuras. Rekey automático sin corte TCP.
  • R29 - Anti line-sharing: Session Token con nonce rotativo firmado por HMAC-SHA256. Cada par (servidor, cliente) usa un token único que rota con cada intercambio de ECM - bloquea el sharing de credenciales entre múltiples instancias.
  • R28 - Soporte SOCKS5 / Tor / I2P: proxy configurable para conexiónes salientes. Operación completamente anónima a través de la red Tor o I2P sin modificar el comportamiento del protocolo.
  • R27 - Optimizaciones de rendimiento: tommyDS hashlin O(1) para lookup de CWs en caché (sustituye scan líneal O(n)). Adaptive ECM Timeout dinámico por CAID usando media histórica. Load balancing ECM mejorado por latencia EWMA y tasa de éxito por upstream.
  • R26 - Card Map, CW-Push & CW Predictor: peers anuncian sus CAIDs sin revelar qué tarjetas tienen (Blind Discovery). CW-Push: los upstreams envían CWs proactivamente sin esperar solicitud. CW Predictor: primer softcam con prefetch predictivo - aprende el ciclo EWMA de cada canal y prelanza la petición antes de que expire la CW actual, eliminando pantallas negras en el zapping.
R21 - R25 Septiembre - Diciembre 2025
  • R25 - Soporte Android NDK (arm64-v8a): compilación nativa para Android. Candela funcióna como proceso nativo en Android sin emulación, con todas las funciónalidades del protocolo P2P.
  • R24 - CAID Tunneling: mapeo transparente de CAIDs (p.ej. Betacrypt→Nagra). Los upstreams que solo conocen un CAID pueden resolver ECMs de otro sin configuración adicional.
  • R23 - Virtual MOSC: clon completo de tarjeta física en RAM para análisis forense. Permite inspeccionar el comportamiento del CAS, editar parámetros del clon y procesar ECMs en entorno aislado.
  • R22 - ECM Idle Watchdog & BorraOff: detección y recuperación automática de canales ECM inactivos. BorraOff limpia la caché selectivamente al detectar canales fuera de servicio, evitando entregas de CWs obsoletas.
  • R21 - ACF herramientas forenses avanzadas: Nagra Key Calculator, Inspector de Payload ECM, Timeline forense, EMM Vault, APDU Fuzzer & Profiler, ECM Simulator y CW Brute-Force Analyzer añadidos al Arsenal Forense.
R16 - R20 Abril - Agosto 2025
  • R20 - Arsenal Forense Candela (ACF): suite forense íntegrada en el WebIF. Incluye Inspector de Payload ECM, Timeline forense, EMM Vault, Nagra Key Calculator, APDU Fuzzer & Profiler, ECM Simulator y CW Brute-Force Analyzer.
  • R19 - WebIF completo: interfaz web con panel en tiempo real (ECMs/s, peers, caché), monitor de CWs en vivo, pestaña CSA, editor de archivos de configuración, visor de log y módulo de mantenimiento.
  • R18 - Servicios y FakeCW: control de acceso por grupo de canales (candela.services), blacklist estática de CWs falsas conocidas y detección dinámica por entropía, patrón de bytes y latencia sospechosa.
  • R17 - Soporte TLS en WebIF: HTTPS con TLS 1.3 (auto-signed o certificado externo), failban íntegrado y rate limiting por IP para el panel de administración.
  • R16 - Soporte multi-CAS completo: Nagravision 2/3/CAK7, Viaccess 3/5, SECA 2, Irdeto 2, Conax, CryptoWorks, NDS, DRE, TongFang y Streamguard. Lectores físicos: PC/SC, Phoenix/Smartreader, AZBox, STAPI y GX.
R11 - R15 Noviembre 2024 - Marzo 2025
  • R15 - Soporte MIPSEL y ARM64: compilación para routers MIPSEL (OpenWrt) y sistemas ARM64. Candela funcióna en decodificadores, routers y servidores NAS sin dependencias externas.
  • R14 - Double Check CW: verificación cruzada de CW entre dos upstreams independientes antes de entregarla al demux. Detecta CWs envenenadas inyectadas por operadoras sin penalizar la latencia en condiciones normales.
  • R13 - DoubleCheck por CAID & CW Cycle Check: verificación selectiva por CAID y detección automática de cambio de criptoperíodo - cierre correcto del ciclo de descifrado sin artefactos visuales.
  • R12 - SoftCam emulator: resolución local de ECMs con SoftCam.Key sin necesidad de tarjeta física ni upstream. Soporte completo del formato SoftCam.Key estándar con reload en caliente.
  • R11 - Affinity & load balancing: afinización de canal por peer (mismo upstream para mismo SRVID) y balanceo inteligente basado en latencia, tasa de éxito y NRS score.
R6 - R10 Julio - Octubre 2024
  • R10 - Sistema de cuentas granular: permisos por usuario (reshare, EMM, cw_push, max_hops, reshare_hops), filtros de acceso por CAID/PROVID/SRVID y gestión dinámica sin reinicio.
  • R9 - Caché ECM & ECM DB offline: base de datos de ECMs con hash MD5, TTL configurable y persistencia en disco. Permite resolver ECMs sin upstream activo para canales ya vistos.
  • R8 - DVBAPI completo: íntegración DVBAPI estándar (socket Unix y TCP) con soporte multi-demux, procesamiento PMT, StreamRelay HTTP y entrega de CW a hardware.
  • R7 - API REST & hot-reload: interfaz REST completa para gestión remota - configuración, cuentas, peers, logs y métricas. Cambios de configuración en caliente sin cortar conexiónes activas.
  • R6 - Cifrado simétrico de sesión: ChaCha20-Poly1305 con clave de sesión única por peer, negociada en el handshake. Autenticación HMAC por paquete, protección contra replay y manipulación.
R1 - R5 2024 - Fundamentos
  • R5 - Protocolo P2P estable: protocolo binario propietario con 22 tipos de mensaje (CMD_HELLO, CMD_ECM_REQ, CMD_CW_RESP, CMD_KEEPALIVE, CMD_PADDING…), framing con longitud variable, estado de conexión por máquina de estados y gestión de timeout.
  • R4 - Multi-puerto y pool de upstreams: hasta 9 puertos TCP P2P simultáneos, watchdog de reconexión automática, pending ECM queue (hasta 1024 ECMs en vuelo) y routing por CAID/PROVID/SRVID.
  • R3 - Caché CW en RAM: almacenamiento de Control Words por (CAID, PROVID, SRVID, hash ECM) con estadísticas de hit/miss, límite de memoria configurable y limpieza periódica automática.
  • R2 - Configuración JSON: parseo completo de candela.json con válidación, carga en arranque y persistencia. Estructura jerárquica: parámetros globales, cuentas, servidores, filtros y lectores locales.
  • R1 - Núcleo P2P: primera versión funciónal del protocolo Candela sobre TCP con cifrado por sesión. Motor ECM handler, gestión de peers (hasta 256 simultáneos), compilación para Linux x86_64, ARMv7 y soporte Enigma2 DVBAPI.