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_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[] 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.GET /api/diag/cw_state./api/diag/cw_state. Permite identificar qué sistema de acceso condicional está activo para cada canal y detectar cambios de PID en canales multiplex.GET /api/diag/emm_stats.GET /api/diag/reader_latency.GET /api/diag/stats. Coste: 5 contadores atómicos, sin impacto medible.GET /api/diag/events. Coste: ~20 KB fijos en RAM.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.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'.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).#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.$(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.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.POST /api/security/events/read_all.POST /api/security/events/block_all.GET /api/diag/channels.GET /api/diag/readers.GET /api/diag/suggestions, reset vía POST /api/diag/suggestions/reset.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.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.avg_latency_ms recibe siempre la ECM primero entre los compatibles con el CAID.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.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).card_map[k].avg_latency_ms). Con esta actualización todas las fuentes locales y remotas se rigen por el mismo criterio.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.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.ecm_multipath: 1 conservan su valor.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.ecm_multipath. Rango 0-10. Hint contextual explicando el efecto de cada valor.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.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.is_request_allowed() antes que los filtros por usuario. Una ECM SKIPpeada se descarta para todos los clientes incluyendo los locales.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.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.candela.prio incluido en la distribución con comentarios explicativos del formato y ejemplos comentados listos para activar.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.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./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./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./api/forensics/ecm_sim?fuzz=1 usaban rand() sin semilla. Sustituido por RAND_bytes() para garantizar resultados impredecibles incluso en sesiones de testing repetidas.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.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.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.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.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.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.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./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.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.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.GET /api/iptv/streams.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.#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.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.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.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.#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..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.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.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.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.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.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.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.enable_streamrelay se persiste en candela.json. El toggle se desactiva si DVBAPI está apagado (StreamRelay requiere DVBAPI activo para funciónar).POST /api/security/unblock_all.disablecrccws ni disablecrccws_only_for.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).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.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.__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.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.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./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%.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.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.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.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.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.audit_head. Corregido capturando los campos en variables locales dentro del mutex.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.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.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.candela.srvid se incluía sin escapar en el JSON de la API de demuxes. Corregido con json_escape_str().atomic_compare_exchange_weak_explicit).RAND_bytes en entornos chroot sin /dev/urandom mataba el daemon con abort(). Sustituido por fallback xorshift con LOG_WARNING.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.hop=0, is_hw=1, igual que una tarjeta física local. Autenticacion: 3DES-EDE2-CBC con deskey de 14 bytes + MD5 password, compatible con NCam y OSCam.hop=0, is_hw=1. Útil para instalar Candela como fuente adicional de CWs sin reconfigurar la infraestructura NCam/OSCam existente.NEWCAMD / MGCAMD (purpura) distingue las entradas de protocolo no-Candela.<dir_config>/candela.pid (ruta configurable con "pidfile" en config.json, o desactivable con "none"). Si al arrancar detecta que el proceso anterior sigue vivo, aborta con mensaje claro indicando cómo usar -c para una segunda instancia. Al apagar, el fichero se borra. Comportamiento identico al de NCam.candela -c /ruta/instancia2/candela.json) con puertos distintos (candela_port, web_port y puertos NewCamd/MGcamd). No hay ningún otro requisito: las instancias son completamente independientes.legacy_proto en gossip: los nodos con servidor NewCamd o MGcamd activo anuncian el bit 0x02 en el byte de flags de CMD_NET_MAP y el bit 0x04 en CMD_NODE_INFO. El flag se propaga a toda la red via gossip y activa reenvío cuando cambia de estado.legacy_proto=1 muestran el candado abierto en el panel compacto de nodos y en la tabla del mapa de red, tanto junto al nombre como junto al NRS Score. Tooltip explicativo visible al pasar el ratón.legacy_proto en JSON: el campo aparece en /api/peers/netmap y /api/peers/nrs para uso de herramientas externas.CMD_MSG_SEND) requiere peer->ecdh_active=1 y peer->authenticated=1. Los clientes NewCamd/MGcamd no participan en peer_list[] ni tienen sesión ECDH Candela, por lo que no pueden envíar ni recibir mensajes P2P bajo ningúna circunstancia.__newcamd__ / __mgcamd__ para todas las peticiónes ECM. El rate-limiter, los filtros de servicios y los logs trataban a todos los clientes como el mismo usuario. Corregido: se usa el nombre de usuario autenticado en el handshake. Si existe una cuenta Candela con ese nombre, se le aplican sus restricciones individuales.NC_MSG_ECM_ODD y el case adicional en el bucle principal de ambos servidores.cache_add() tras cada resolución satisfactoria, con fuente "NewCamd" / "MGcamd".bind() fallase silenciosamente. Corregido con detección de duplicados en los _init() (log WARNING + skip) y válidación en el WebIF antes de guardar (alert bloqueante)._init() y válidación en WebIF.parse_accounts() insertaba ambas entradas en el índice tommy_hashlin sin comprobar duplicados por nombre de usuario, dejando la segunda como entrada zombie que ocupaba un slot del límite. Corregido con comprobación previa a la inserción.parse_servers() no comprobaba ip:port duplicados; dos conexiónes TCP a la misma IP y puerto establecidas simultáneamente. Corregido con la misma estrategia.recv() en servidores y clientes NewCamd/MGcamd podían bloquearse indefinidamente si el extremo remoto dejaba de responder sin cerrar la conexión. Añadido SO_RCVTIMEO de 10 segundos en todos los sockets (servidor al aceptar la conexión, cliente justo después de conectar).port <= 65535.NC_MAX_MSG_LEN) podía causar un desbordamiento en el buffer de envío al hacer el cast a size_t. Añadida comprobación previa que descarta el ECM y devuelve NAK inmediato."pidfile" leído del fichero de configuración se copiaba directamente sin pasar por la función de sanitización de rutas, permitiendo rutas relativas con ... Ahora pasa por config_build_path(), que bloquea path traversal y resuelve rutas relativas desde el directorio de configuración.candela_mode por entrada (servidor y reader): campo selecciónable en cada entrada de servidor NewCamd/MGcamd y en cada reader NewCamd/MGcamd. Valor 0 = modo legado compatible con NCam/OSCam; valor 1 = Modo Candela, activa la capa adicional. Al ser por entrada, un nodo puede tener simultáneamente peers en Modo Candela y peers en modo legado sin conflicto.candela_mode=1 añade 12 bytes al payload de login NewCamd: 4 bytes magic ASCII CNDL seguidos de 8 bytes de NodeID binario. Servidores NCam/OSCam ignoran estos bytes extra (compatibilidad garantizada). Si el servidor Candela detecta CNDL y tiene candela_mode=1, responde en el ACK con CNDL más sus propios 8 bytes de NodeID. Si alguno de los dos lados no admite CNDL, el protocolo cae en modo legado automáticamente sin interrupción de la conexión.cm_send_ctr / cm_recv_ctr). El contador solo se incrementa cuando el payload tiene longitud mayor que cero, garantizando que el counter del emisor siempre sea igual al counter del receptor para cada dirección. Los mensajes sin payload (keepalive, status) no consumen contador.nc_chacha20_apply() construye el IV de 16 bytes como [counter(4 bytes LE) | ceros(12 bytes)] y aplica ChaCha20 in-place sobre el buffer de datos. Al ser un cifrado de flujo, cifrar y descifrar son la misma operación.ca_ip en el log de conexión tras liberar la estructura nc_client_arg_t (vía free(ca)) pero antes de declararla. Corregido declarando y copiando struct in_addr ca_ip = ca->cli_ip antes del free(ca).global_config.nodeid[17] que almacena 16 caracteres hex = 8 bytes binarios. Corregido a 8 bytes binarios (12 bytes totales) en todos los puntos: login del cliente, ACK del servidor, detección en servidor y cliente, y buffers intermedios.allowed): cada entrada de servidor NewCamd y MGcamd tiene un campo allowed que acepta lista de rangos separados por coma. Formatos soportados: IP exacta (192.168.1.10), CIDR (192.168.0.0/24) y comodín de octeto (192.168.*). Vacío = cualquier IP. Las conexiónes rechazadas por filtro se cierran inmediatamente con log de aviso indicando la IP rechazada. Implementado en nc_ip_allowed() / mg_ip_allowed().max_clients): el límite de conexiónes simultáneas por servidor NewCamd/MGcamd, que en la iteración anterior era el valor compilado fijo de 64, es ahora configurable por servidor vía el campo max_clients. Valor 0 = usar el límite compilado (64). El campo se lee desde config.json y se serializa correctamente en las funciónes de guardado.keepalive_enabled): con keepalive_enabled=0 el bucle principal del hilo servidor NewCamd/MGcamd no envía el mensaje de keepalive periódico y cierra la conexión en el primer timeout de select sin datos, en lugar de mantenerla viva indefinidamente. Útil para servidores de acceso restringido donde se prefiere desconexión por inactividad.translations.json para los campos allowed (nc_allowed_lbl/tip), max_clients (nc_max_clients_lbl/tip), keepalive (nc_keepalive_lbl/tip) y candela_mode (nc_candela_mode_lbl/tip) en español, inglés, alemán, francés, italiano y portugués. Los paneles NewCamd/MGcamd del WebIF usan t() en lugar de texto hardcodeado en español.socks4 (RFC 1928 legacy, con userid), socks5 (sin autenticación), socks5 con usuario+contraseña (RFC 1929), tor (alias SOCKS5 en localhost:9050, resolución DNS remota vía ATYP=0x03) e i2p (alias SOCKS5 en localhost:4444). El proxy per-servidor preexistente se mantiene como fallback para retrocompatibilidad. Control en WebIF - Transporte / Proxy Universal. Default: desactivado.CMD_NET_MAP contiene como máximo netmap_gossip_max NodeIDs selecciónados aleatoriamente (Fisher-Yates parcial, PRNG xorshift32 no bloqueante). Con netmap_gossip_max=30 (default), un actor con múltiples peers autenticados necesita ≥ log₂(N/30) peticiónes para enumerar la red completa, en lugar de recibirla de golpe. Control en WebIF - Anti-DPI Suite. Default: 30 entradas.TuIP → CardServerIP ante un observador externo (ISP, tap de red). Flujo: CMD_ECM_RELAY (origin→relay) → CMD_ECM_REQ (relay→dest) → CMD_CW_RESP (dest→relay) → CMD_ECM_RELAY_RESP (relay→origin). Compatible con AMPE: cada path paralelo usa un relay distinto; si no hay relay disponible para un path concreto, ese path va directo sin bloquear los demás. Nuevos comandos 0x17/0x18 en el protocolo Candela. Default: desactivado (opt-in).enable_mcrr=1 y ≥2 lectores físicos activos, las ECMs se distribuyen determinísticamente por SRVID % num_lectores. Cada lector atiende un subconjunto fijo de canales - desde el punto de vista del sistema CA de la operadora, cada tarjeta tiene el perfil de uso de un suscriptor con pocos canales activos, independientemente del número total de canales servidos por el nodo.max_parallel o en estado de error, la petición pasa transparentemente al siguiente lector compatible de la lista. El orden de failover es circular, comenzando siempre desde el lector asignado por SRVID.relaxed (suficiente para PRNG no criptográfico).ftell), se pasaba directamente a malloc. Corregido con válidación explícita antes de cualquier asignación.relaxed.coal_update() leía el campo ts_ms de la primera entrada de la tabla de coalescing antes de adquirir el mutex que protege esa tabla. En ARM32, una lectura de 64 bits sin sincronización puede producir un valor partido (torn read). Corregido moviendo la lectura inicial al interior del bloque protegido por el mutex.strtol en parsing hex de reglas de tunel y lista de proveedores (ARM 32 bits): los campos de PROVID en las reglas de tunel de CAID y en la lista de nombres de proveedores se parseaban con strtol. Misma clase de bug que el fix del parser SoftCam.key: en ARM 32 bits, valores superiores a 0x7FFFFFFF se saturaban incorrectamente. Corregido con strtoul.strtol → strtoul en parser de SoftCam.key (ARM 32 bits): en arquitecturas Enigma2 (ARM 32 bits), el parser de SoftCam.key usaba strtol para los identificadores de canal (id1/id2). Los valores superiores a 0x7FFFFFFF (frecuentes en entradas BISS) se saturaban al valor máximo del tipo con signo, haciendo que cientos de canales distintos colapsaran en el mismo identificador. Resultado: en lugar de los ~826 pares CAID:PROVID reales, el emulador anunciaba solo 285. Corregido con strtoul.is_hw en la entrada card_map_entry_t y propagándolo en el byte HOP del wire format CMD_CARD_MAP (bit 6). El conteo agrupa las entradas de tarjeta física por CAID único (1 tarjeta por CAID), mientras que las entradas de emulador siguen contando cada par CAID:PROVID individualmente.scc_max_channels, los canales nuevos se redirigen transparentemente a P2P en lugar de ir a la tarjeta local. Para el sistema CA de la operadora, el perfil de uso de la tarjeta no supera el de un suscriptor multi-room estándar (típico: 1-4 canales). Los SRVIDs se marcan como inactivos tras scc_window_s segundos sin ECM. Control: WebIF - Mantenimiento - Transporte y Anti-DPI - Operator Stealth. Default: 0 (desactivado, opt-in).ets_max_spread_ms] ms antes de llegar a la tarjeta. Para el sistema CA, los inicios de canal llegan distribuidos en el tiempo, como si fuera un suscriptor cambiando de canal secuencialmente. El spreading solo aplica al primer ECM de un SRVID nuevo; las ECMs de refresco de canales ya activos pasan sin retardo. La detección de ráfaga es no-bloqueante: si un solo canal inicia sin otros concurrentes, no hay delay. Default: activado, 2000 ms.CAID+PROVID+SRVID independiente del hash de ECM. Cuando la CA varía el payload de la ECM entre peticiónes del mismo criptoperíodo (nonce interno, timestamp propio), el coalescing detecta que ya se resolvió ese canal recientemente y reutiliza la CW sin acceder al hardware. La ventana ecm_coalesce_window_ms se clampea a 9000 ms (inferior al criptoperíodo DVB de 10 s), garantizando que nunca se sirve una CW caducada. Evicción LRU. Default: 0 (desactivado, opt-in).memory_order_relaxed - coste cero en x86/ARM.CMD_NET_MAP es de 53 bytes y contiene exclusivamente metadatos públicos: nodeid[16] + proto_ver[2] + name[32] + country[2] + flags[1]. Las IPs son conocidas solo por los peers con conexión TCP directa y nunca salen a la red. Un actor malicioso con múltiples peers autenticados no puede enumerar las IPs de la red Candela mediante gossip.flags [52] (bit0=pir_auto_connect, bit1=anon_peer_ips). Los nodos PEER_INCOMING ya son visibles en el NETMAP global. Retrocompatible: R37 (50B) aceptado sin error.pir_auto_connect=1, los nodos entrantes se añaden a pir_discovered[] y el watchdog los propaga al resto de peers cada 60 s via CMD_PEER_DISC. Bloqueado automáticamente si anon_peer_ips=1 para no filtrar IPs reales.pir_auto_connect=1 con anon_peer_ips=0 son marcados como contribuidores y reciben +10 puntos de bonus en su NRS Score (tope 100). En el WebIF aparecen con el icono 🔥 en el mapa de red. El flag contributor se propaga en CMD_NODE_INFO byte [52] bit0 y en CMD_NET_MAP byte [52] de cada entrada.max_peers_per_subnet) para evitar ataques de eclipse de subred.ecm_multipath 1-3). Reduce latencia en canales de alta demanda.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.tcp_rotation_h con ventana [N, 4×N] horas. Interfaz completamente traducida a los 6 idiomas soportados (es, en, de, fr, it, pt).strtol en parsers de puerto para evitar desbordamiento de entero.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.failban_block_manual() llama ahora a peer_kick_by_ip() para desconectar conexiónes activas de la IP en el momento del baneo.ban_count por IP persistido en failban.json.FAILBAN_MAX_ENTRIES aumentado de 256 a 1024.[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./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.maxlist, keeptime y sensibilidad configurables.dcheck_caid).cw_cache_memory, ecm_cache_memory).explicit_bzero de passwords en memoria.p2p_allowed (IP allowlist por rangos), p2p_max_conn_per_ip (rate-limit de conexiónes entrantes), panel "Seguridad Avanzada P2P" en mantenimiento.CMD_MSG_SEND / CMD_MSG_ACK. Zero-disk: los mensajes existen solo en RAM y desaparecen al cerrar Candela.enable_p2p_chat. Requiere peers con R31+.