Resumen

  • RFC 3261 trataba de forma distinta la referencia IPv6 de sent-by y la dirección IPv6 de received; RFC 5118 documentó implementaciones que no coincidían sobre los corchetes.
  • La respuesta fue asimétrica: aceptar received con o sin corchetes para interoperar, pero enviar la forma sin corchetes. La tolerancia de entrada no entregaba autoridad para reescribir cualquier campo.
  • Un resultado de parser solo prueba una interpretación local. Los bytes originales, el árbol, la intención host-puerto, la salida reenviada, el siguiente salto y el resultado SIP siguen siendo recibos distintos.

La cadena era incómoda, no incomprensible. Un valor received=[2001:db8::9:255] podía violar una lectura estricta de la producción de RFC 3261 y, sin embargo, representar sin ambigüedad la dirección que otro equipo había observado.

RFC 5118 recogió una realidad de interoperabilidad: durante pruebas, unas implementaciones añadían corchetes y otras no. Obligar a todos los receptores a rechazar una de las dos formas habría convertido una diferencia conocida en una ruptura. Aceptar ambas resolvía la entrada; emitir solo la forma prevista por la gramática evitaba propagar la divergencia.

Una excepción con nombre, campo y dirección

La regla no decía «sé liberal con todo». Nombraba el parámetro received, la ambigüedad y el comportamiento de recepción. También distinguía emisión de recepción. Ese límite es lo que vuelve gobernable la robustez.

Cuando una biblioteca implementa la excepción como una limpieza global de corchetes, puede dañar una URI SIP, donde los corchetes sí separan el literal IPv6 del puerto. Cuando un producto elimina toda tolerancia, puede rechazar tráfico que el perfil de interoperabilidad esperaba procesar. La política correcta no cabe en un booleano strict.

El registro útil debe indicar los bytes, el campo, la producción, la excepción activada, la dirección estructurada resultante y la forma serializada. Solo así un cambio de versión puede revisarse sin confundir más aceptación con más corrección.

La URI válida que no quería decir eso

Otro mensaje de RFC 5118 muestra el límite inverso. La forma sip:[2001:db8::10:5070] puede analizarse correctamente. Pero si el emisor quería 2001:db8::10 y el puerto 5070, cerró los corchetes demasiado tarde. El grupo 5070 quedó dentro de la dirección.

El erratum verificado corrige el lenguaje original: se convierte en la última pareja de octetos IPv6, no en el último octeto. El detalle no cambia la tesis, pero sí cambia la descripción técnica y debe acompañar cualquier reproducción seria.

La forma con puerto separado es sip:[2001:db8::10]:5070. Ambas pueden ser sintácticamente válidas. Solo una coincide con la intención. Un parser no puede deducir esa intención desde los caracteres que recibió; una prueba necesita una expectativa externa y una observación del socket elegido.

RFC 5118 incluye además una URI sin los corchetes obligatorios que debe rechazarse con 400. La colección diferencia así tres cosas: inválido y rechazable; válido pero semánticamente inesperado; inválido en sentido estricto pero tolerado en un campo concreto. Reducirlas a «pasa/no pasa» destruye el valor de la colección.

La cabecera y el cuerpo no comparten puntuación

En una URI SIP, el literal IPv6 lleva corchetes. En una línea de conexión SDP no. Un mensaje válido puede mezclar direcciones IPv4 e IPv6 en varias cabeceras Via, o asignar una familia distinta al audio y al vídeo. Una dirección IPv4 mapeada en IPv6 puede aparecer en señalización, SDP o ambos.

La misma secuencia visual tiene reglas distintas según su contenedor. Por eso una capa de normalización debe conocer el árbol y preservar el campo original. La uniformidad visual no es un objetivo del protocolo; la interpretación inequívoca sí.

El RFC examina incluso una ruta ABNF que podía producir un colon adicional antes de una parte IPv4 incrustada. Un receptor podía aceptarlo por robustez y, si reenviaba, quitar el colon extra. De nuevo, el acto de comprender la entrada no equivale al acto de copiarla.

El RFC impidió que la página fingiera ser el cable

Las líneas SIP largas no cabían limpiamente en el formato editorial. allOneLine, heredado de RFC 4475, indica cómo concatenar líneas sin inventar espacios. RFC 5118 incluye además un archivo codificado con las representaciones exactas.

Copiar desde HTML o PDF puede cambiar el experimento. Un espacio, salto o longitud de cuerpo recalculada crea otra entrada. La custodia debe comenzar con hash, método de extracción y bytes. La interfaz de prueba debe decir si normalizó antes de invocar el parser.

Incluso con bytes exactos, el documento no certifica un producto. Es Informational, no normativo y no exhaustivo. Algunos casos prueban el parser; otros alcanzan la aplicación. El resultado pertenece a una compilación y configuración concretas.

Después del parser empieza el sistema

Un árbol correcto no selecciona por sí solo el siguiente salto. No recibe una respuesta SIP, no crea un diálogo, no comprueba que el SDP sea alcanzable y no transporta media. Cada fase puede fallar después de un parseo aceptado.

También puede ocurrir lo contrario: una llamada termina gracias a un contacto alternativo aunque dos intermediarios hayan interpretado una forma de manera distinta. El éxito oculta la diferencia hasta que cambia la topología.

La cadena de prueba debe mantener: fixture exacta; regla aplicada; árbol; intención; salida; ruta; transacción; diálogo; media; resultado. La primera marca verde no tiene mandato sobre las demás.

Robustez sin impunidad

RFC 5118 ofrece una política más madura que «aceptar lo que llegue». La entrada tolerante se justifica con evidencia de interoperabilidad y se acompaña de una salida limitada. La excepción queda visible. La base normativa no se reescribe por accidente.

Ese patrón permite convivir con implementaciones reales sin convertir cada desviación en precedente. La capa común puede ser pequeña: bytes reproducibles, reglas explícitas y unas pocas excepciones probadas. Las decisiones sobre riesgo, registro y retirada pertenecen al operador que asume el efecto.

Fuentes