Кратко

  • Успешный SETUP создавал на сервере контекст управления и возвращал идентификатор Session; ни описание SDP, ни открытое TCP-соединение такого состояния не создавали.
  • Контекст мог пережить замену управляющего соединения, но идентификатор не отменял правильный URI, допустимость метода, аутентификацию и фактическую достижимость медиатракта.
  • Сервер хранил состояние, пока получал приемлемые признаки активности. После TEARDOWN, тайм-аута или другого завершения прежнее значение могло вызвать лишь 454 Session Not Found.

Пульт не был привязан к одному проводу

У потокового управления две шкалы времени. Команды PLAY и PAUSE коротки, TCP-канал может оборваться, а выбранные дорожки, транспорт и общая позиция воспроизведения должны жить дольше отдельного запроса. Если бы память сервера совпадала по сроку с одним сокетом, краткий сетевой сбой отменял бы всё ранее согласованное.

RFC 2326 в 1998 году выразил решение предельно прямо: понятия RTSP-соединения нет. Сервер поддерживал сеанс, отмеченный идентификатором, и этот сеанс не зависел от транспортного соединения вроде TCP. Клиент мог открывать и закрывать несколько надёжных каналов, продолжая один контекст управления.

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

Описание ещё ничего не резервировало

До управления клиент обычно получал описание презентации. SDP из RFC 4566 задаёт формат для типов медиа, кодеков, адресов и других метаданных. Это представление сведений, а не протокол, создающий транспорт или выполняющий команды.

Слово «сеанс» используется в обоих слоях, отчего возникает опасная подмена. SDP может перечислить аудио и видео и дать ссылки управления. Это не означает, что сервер уже выделил порты, принял вариант транспорта, создал буферы или сохранил состояние для конкретного зрителя.

Границу пересекал SETUP. Клиент называл медиаресурс и предлагал параметры Transport. При успехе сервер выбирал допустимый вариант, сохранял его и возвращал результат. RFC 7826, определивший RTSP 2.0 в 2016 году, прямо называет это созданием контекста сеанса RTSP. Описание отвечало, что может быть предложено; успешный SETUP — что сервер действительно принял и удерживает.

Второй адрес указывал на память, а не на произведение

Медиа-URI обозначал объект управления. Session различал принятые контексты доставки, в том числе два сеанса для одного URI. RTSP 1.0 требовал непрозрачную случайную строку не короче восьми октетов. RTSP 2.0 установил длину от 8 до 128 символов, криптографически случайное формирование и рекомендацию примерно в 128 бит энтропии.

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

Для личности и допуска существовал отдельный механизм. Digest по RFC 7616, например, применяет вызов, учётные данные, nonce и защиту от повторов. Session отвечает на вопрос «какой сохранённый контекст?», а аутентификация — «какой заявитель принят в этой области защиты?». Оба элемента нужны в одном запросе именно потому, что решают разные задачи.

Знание Session не отменяло правильный URI

Получив идентификатор, клиент добавлял его к PLAY, PAUSE, TEARDOWN и другим командам для существующего контекста. Поэтому новый TCP-канал мог добраться до прежнего состояния. Однако URI запроса оставался обязательным.

Это хорошо видно в агрегированном сеансе. Аудио и видео могут идти по общей временной шкале, чтобы один PLAY запустил оба потока. Но операция над целым должна поступить на подходящий aggregate control URI, а не на URI отдельной дорожки. URI помогает прокси маршрутизировать, указывает ресурс и сохраняет осмысленную область журнала.

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

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

Много сеансов в соединении, много соединений у сеанса

RTSP 2.0 требовал поддержки как постоянных, так и кратковременных TCP-соединений. Клиент мог отправить SETUP и PLAY, закрыть канал и позже открыть другой для PAUSE. Так пара могла пережить потерю TCP, например из-за истечения записи NAT, не перестраивая презентацию с нуля.

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

Медиатракт оставался отдельным слоем. RTP мог идти по согласованным UDP-портам или чередоваться с управлением. Действительный контекст не доказывал, что кандидаты проходят NAT и межсетевой экран. Поэтому RFC 7825 приспособил ICE к дейтаграммным медиа под управлением RTSP. Session указывал, какое состояние менять; ICE проверял, существует ли путь для пакетов.

Память требовала признаков жизни

Сервер не мог бесконечно хранить брошенные контексты. Ответ Session мог сообщить, сколько он ждёт следующего запроса или иного допустимого сигнала; по умолчанию это было 60 секунд. В RTSP 2.0 параметр timeout разрешался только в ответе, а его продолжительность нельзя было менять посреди установленного сеанса.

Любой RTSP-запрос со ссылкой на контекст мог обновить активность. Для чистого keep-alive RTSP 2.0 предпочитал пустой SET_PARAMETER. В системах с RTP помогал и RTCP. RFC 3550 определил отчёты отправителя и получателя о медиаисточнике и приёме; отчёт от подходящего источника и сетевого кортежа мог показать серверу, что сторона клиента ещё присутствует.

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

Строка могла остаться после исчезновения состояния

Обычное завершение выполнял TEARDOWN. На агрегированном уровне он мог остановить общую доставку и уничтожить контекст. Разрешённый TEARDOWN для отдельного медиа удалял компонент; после последнего сеанс заканчивался. Сервер мог также удалить состояние по тайм-ауту, при завершающем перенаправлении или неустранимой ошибке.

После этой границы повтор старого идентификатора ничего не воскрешал. Ответ 454 Session Not Found охватывал отсутствующий, неверный или просроченный Session. Клиент мог безошибочно помнить те же символы, хотя живой серверной записи уже не было.

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