Resumen

  • RFC 3391 permitía partir mensajes MIME en bloques numerados y entrelazarlos, de modo que una imagen pudiera viajar cerca del pasaje del mensaje raíz que la referenciaba.
  • El productor elegía esa cercanía sin recibir información del consumidor; un flujo bien formado no demostraba que hubiera memoria suficiente, que la disposición fuese adecuada o que todos los mensajes fueran a terminar.

Una impresora rápida no necesita todo un documento al mismo tiempo. Necesita la página que va a imprimir y las imágenes que esa página invoca. Sin embargo, un contenedor convencional podía obligarla a recibir todas las imágenes antes del documento o a esperar hasta que el documento entero terminara para recibirlas después.

Ese orden no era un defecto de los componentes. Era una propiedad de su representación. En multipart/related, las partes del cuerpo se sucedían entre límites. La referencia podía aparecer al comienzo de una parte larga y el objeto referenciado a muchos octetos de distancia.

RFC 3391, publicado como documento informativo en diciembre de 2002, atacó precisamente esa distancia. Su tipo application/vnd.pwg-multiplexed transportaba una secuencia de bloques. Cada bloque contenía un mensaje MIME completo o un tramo de uno. Los bloques de mensajes diferentes podían alternarse, permitiendo detener el texto raíz, insertar una imagen y continuar el texto.

La especificación insistía en no confundir objeto y transporte. El documento compuesto, su raíz y sus componentes eran abstracciones. La entidad y los mensajes eran representaciones en octetos. De hecho, un mensaje reconstruido debía ser idéntico, octeto por octeto, a la parte que habría representado el mismo componente en multipart/related. La innovación estaba en el calendario de los bytes, no en una nueva semántica de imagen o enlace.

El calendario tenía una gramática pequeña. Una cabecera llevaba CHK, un número de mensaje, la longitud de la carga y un estado MORE o LAST. La longitud eliminaba la necesidad de buscar una cadena delimitadora. MORE mantenía abierto el mensaje; LAST cerraba su último tramo. Aunque otros mensajes se interpusieran, los tramos de uno mismo debían conservar su secuencia.

El primer bloque pertenecía a la raíz, completa o parcialmente. Podía incluso estar vacío, una licencia práctica para productores que necesitaban emitir otros datos antes de los primeros octetos reales de la raíz. El cierre general era CHK 0 0 LAST. El cero quedaba reservado a ese centinela.

El centinela no garantizaba una historia coherente por sí solo. Si aparecía antes del cierre de todos los mensajes, el comportamiento quedaba sin definir. Tampoco era obligatorio que cada número identificara una sola pieza para siempre. Reutilizar números estaba permitido, aunque no recomendado, siempre que un mensaje llegara a LAST antes de comenzar el siguiente con el mismo número.

El parámetro obligatorio type declaraba el tipo de contenido de la raíz. Así, el consumidor podía conocer la clase del objeto sin abrir todavía el mensaje interno. Si la declaración discrepaba de la cabecera real, la especificación dejaba de prometer un resultado. Para enlazar componentes, el formato podía aprovechar Content-ID, Content-Location y las pautas de MHTML; no redefinía esas relaciones.

La primera escena del RFC era una larga descripción de páginas. El productor no sabía qué imágenes incluir hasta generar cada página. Con la nueva representación podía enviar una imagen poco antes de su primera referencia. Cuando la impresora encontraba el enlace, la imagen ya estaba disponible, sin obligarla a retener todas las imágenes futuras.

La segunda escena era un escáner parecido a un fax. Cada página generaba una imagen y una referencia. Colocar la imagen inmediatamente antes o después de esa referencia permitía producir y consumir el trabajo progresivamente. La proximidad evitaba que uno de los extremos tuviese que acumular el lote completo.

La tercera escena mostraba el límite. El consumidor decidía la maquetación. Si varias imágenes debían aparecer lado a lado, entrelazar sus bandas podía ahorrar espera mientras todo iba bien. Pero, al agotarse la memoria, el consumidor conservaría porciones de muchas imágenes sin poder completar ninguna. El RFC recomendaba no hacer ese entrelazado.

El texto alrededor de una imagen era aún menos predecible. El productor ignoraba dónde terminaría el contorno en la maquetación del receptor. Si cortaba el texto demasiado pronto, el consumidor podía verse obligado a guardar toda la imagen o a interrumpir el contorno. Si lo cortaba demasiado tarde, podía guardar demasiado texto o desplazar la imagen. La recomendación de enviar algo más de texto se apoyaba en que el texto suele pesar menos que una imagen. No convertía la conjetura en información.

Por eso la nota del IESG encabeza el documento. El uso solo era apropiado cuando el productor conocía plenamente las capacidades y limitaciones del consumidor. Distintos consumidores podían necesitar cosas distintas en momentos distintos, y el medio no ofrecía ningún canal para averiguarlo. Si esas capacidades eran desconocidas, convenía considerar una alternativa bidireccional como BEEP.

La comparación separaba dos clases de control. En el contenedor multiplexado, el productor colocaba por anticipado. En BEEP, el consumidor podía pedir una imagen al llegar a su referencia o solicitar bandas adaptadas a su disposición. Pedir podía introducir espera; empujar podía equivocarse sobre el momento. El formato no abolía esa elección.

La presentación final también pertenecía al consumidor. Cuando reconocía tanto el contenedor como el tipo raíz, trataba las piezas como una sola obra compuesta. En ese contexto, Content-Disposition podía ser redundante o engañoso y debía ignorarse para mostrar el contenido. Si entendía el contenedor pero no la raíz, podía suprimir el conjunto o mostrar los mensajes como partes mezcladas. Si no entendía el tipo, solo veía un objeto opaco.

Los riesgos de almacenamiento eran la cara adversa de la misma libertad. Un productor defectuoso o malicioso podía separar durante muchos octetos los tramos de un mensaje y no enviar nunca el cierre. Podía mantener abiertos numerosos mensajes, referenciar componentes ausentes o entregar una gran colección antes de que el consumidor supiera cuáles podía descartar.

Ninguno de esos ataques necesitaba falsificar cada cabecera. Un bloque podía tener número, longitud y estado correctos. El problema aparecía al acumular promesas locales en una obligación global imposible. Validar el bloque no era validar el coste de toda la entidad.

La idea de Especificación Inicial Mínima de Lu Heng ilumina la decisión. RFC 3391 fijó lo necesario para reconstruir mensajes independientes: numeración, longitudes, continuidad, raíz y final. No intentó imponer una única política de memoria o maquetación. Esas decisiones podían evolucionar en el software del borde.

La Primacía del Código en Ejecución impide extraer más evidencia de la que existe. Registrar un tipo MIME no demuestra que una impresora real mantuviera su velocidad. Recibir LAST no demuestra que la imagen correcta apareciera. Solo la ejecución observada, con trazas de memoria y resultado renderizado, puede cerrar esas afirmaciones.

El legado de RFC 3391 está en haber hecho programable la cercanía sin fingir que era conocimiento. El productor pudo poner la imagen junto a su referencia. Siguió sin ver el lector. Entre ambos quedó una frontera decisiva: ordenar lo que se envía no es observar cómo será usado.

Fuentes