Кратко

  • RFC 3391 разбивал MIME-сообщения на нумерованные фрагменты с заданной длиной и чередовал их, чтобы изображение могло прийти непосредственно до или после ссылки в корневом сообщении.
  • Близость задавал производитель без обратной связи: корректный фрагмент не доказывал достаточность памяти, удачную компоновку и будущее завершение всех открытых сообщений.

Сканер узнаёт содержание следующей страницы в процессе работы. Изображение становится известно тогда, когда генератор доходит до ссылки на него. На другом конце принтер хотел бы начать вывод до получения всего задания. Обычная последовательность частей заставляет выбирать: отправить изображения заранее и занять память либо поставить их после длинного документа и ждать.

multipart/related хорошо выражал принадлежность частей одному составному объекту, но располагал body parts последовательно. Между ссылкой в длинной корневой части и её целью могли лежать многие октеты. Правильная упаковка не обязательно давала подходящий график доставки.

RFC 3391 вышел в декабре 2002 года как Informational RFC и определил application/vnd.pwg-multiplexed. Его сущность состояла из фрагментов. Каждый содержал целое MIME-сообщение или его часть, а фрагменты разных сообщений разрешалось перемежать. Корень можно было прервать, передать изображение и продолжить.

Документ отделял объект от представления. Составной объект, корень и компоненты были абстракциями; сущность и сообщения — их октетным воплощением. После сборки сообщение должно было совпадать октет в октет с body part, представляющей тот же компонент в multipart/related. Менялся порядок доступности, а не смысл изображения.

Заголовок фрагмента содержал CHK, номер сообщения, длину полезной нагрузки и MORE либо LAST. Длина указывала границу без поиска multipart-разделителя. MORE обещал продолжение, LAST закрывал последнее звено сообщения. Другие сообщения могли вклиниваться, но части одного сообщения сохраняли внутренний порядок.

Первый фрагмент содержал корневое сообщение целиком или частично. Допускалась даже пустая нагрузка, поэтому настоящие первые октеты корня могли появиться позже. Всю сущность завершал отдельный сторож CHK 0 0 LAST; номер ноль резервировался для него.

Сторож не исправлял предыдущие пропуски. Если он появлялся до последних фрагментов всех сообщений, поведение получателя становилось неопределённым. Номера обычно были уникальными, однако повторное использование допускалось, хотя и не рекомендовалось. Прежнее сообщение с таким номером следовало закрыть до начала нового.

Обязательный параметр type объявлял медиатип корневого сообщения. Получатель мог понять класс составного объекта, не открывая вложенный корень. При расхождении объявления с фактическим Content-Type поведение снова оставалось неопределённым. Для связей подходили Content-ID и Content-Location по образцам MHTML; сам RFC 3391 не определял язык отношений.

В первом примере производитель создавал длинную последовательность описаний страниц и обнаруживал изображения по ходу дела. Изображение помещалось незадолго до первой ссылки. Когда принтер читал ссылку, ресурс уже находился у него, хотя весь корень и будущие изображения ещё не пришли.

В сценарии сканирования изображение могло следовать сразу после ссылки. Сначала получатель узнавал место, затем принимал материал. Выигрыш состоял в сокращении октетного расстояния между именем и объектом, а не в магическом исчезновении буферов.

Третий пример передавал решение о вёрстке получателю и показывал предел. Изображения могли стоять рядом, текст — обтекать картинку. Производитель видел позицию ссылки, но не ширину страницы, шрифт, запас памяти и стратегию вывода другой машины.

Чередование полос соседних изображений выглядело привлекательным, пока хватало памяти. При её исчерпании у получателя оставались попеременные незаконченные части нескольких картинок. RFC советовал не чередовать изображения в этой ситуации. Возможность формата не являлась рекомендацией применять её везде.

Для обтекания требовалось угадать место разреза текста. Слишком ранний разрез вынуждал сохранить всё изображение или преждевременно закончить обтекание. Слишком поздний — накопить лишний текст или отодвинуть картинку. Поскольку текст обычно меньше графики, документ предлагал ошибаться в сторону большего объёма текста. Это была практическая эвристика, а не наблюдение за получателем.

Поэтому IESG Note определяла условие эксплуатации. Медиатип подходил лишь там, где производитель полностью знал возможности и ограничения потребителя. Разным потребителям требовались разные компоненты в разное время, а однонаправленное представление не позволяло спросить. Для неизвестного получателя рекомендовалось рассмотреть двусторонний механизм, например BEEP.

Сравнение разделяло предсказание и запрос. В multiplexed-сущности производитель заранее проталкивал компонент. В двустороннем протоколе потребитель мог запросить изображение, встретив ссылку, или потребовать полосы под собственную компоновку. Запрос добавлял ожидание; предзагрузка рисковала ошибиться. Скорость и наблюдаемость были разными свойствами.

Окончательное представление также принадлежало потребителю. Если он понимал контейнер и тип корня, компоненты отображались в контексте составного объекта, а Content-Disposition мог быть лишним или вводящим в заблуждение и игнорировался для показа. Если был понятен контейнер, но не корень, сущность можно было скрыть или показать как смешанные вложения. Неизвестный контейнер оставался непрозрачным.

Угрозы хранения были обратной стороной свободы расписания. Ошибочный или злонамеренный производитель мог разнести части сообщения на огромное число октетов или никогда не прислать конец. Он мог открыть множество сообщений, сослаться на отсутствующие компоненты или передать столько ресурсов заранее, что получатель не понимал, какие уже можно удалить.

При этом отдельный фрагмент мог быть безупречен. Номер, длина и состояние продолжения проходили локальную проверку, а совокупность незакрытых обещаний раздувала память без полезной границы. Валидная рамка не доказывала ограниченность всей обработки.

Принцип Lu Heng о минимальной первоначальной спецификации объясняет узость общего слоя. Номера, длины, продолжение, корень и завершение требовали согласия. Вёрстка и политика памяти оставались локальными и могли развиваться без центрального разрешения.

Примат работающего кода ограничивает доказательство. Регистрация медиатипа не подтверждает, что реальный принтер не остановился. Получение LAST не подтверждает, что изображение показано. Исходный поток, граф ссылок, телеметрия памяти и результат визуализации — разные квитанции.

RFC 3391 сделал близость программируемой, но не сделал читателя прозрачным. Изображение приходило рядом со ссылкой. Узнать, подходил ли этот момент конкретному получателю, по тому же одностороннему потоку было невозможно.

Источники