Глава 5. Механизм переговоров

5.1 Принципы переговоров

Реализация DTP MUST обеспечивать соблюдение следующих принципов переговоров:

  1. Переговоры в первую очередь: до любой передачи данных Fragment MUST уже существовать Agreement в состоянии active.
  2. Никакой передачи без Agreement: реализация MUST NOT допускать передачу данных, не опирающуюся на Agreement.
  3. Двусторонние переговоры: Master MAY инициировать переговоры по сбору данных; Slave MAY инициировать переговоры по инжекции данных.
  4. Динамическая корректировка: обе стороны MAY корректировать параметры Agreement, пока он находится в состоянии active.
  5. Явное прекращение: обе стороны MAY явно прекратить Agreement. После прекращения передача данных в рамках этого Agreement MUST немедленно остановиться.

5.2 Типы переговорных фреймов

Переговоры MUST осуществляться через два типа фреймов: Request_Frame и Response_Frame.

5.2.1 Request_Frame

Request_Frame MUST содержать следующие поля:

interface RequestFrame {
  frameType: "request";
  requestId: string;
  requestorRole: "master" | "slave";
  requestType: "collection" | "injection" | "adjustment" | "termination";
  targetAgreementId?: AgreementID;
  proposedParams: AgreementParams;
}
ПолеНормативное требование
frameTypeMUST быть литералом "request"
requestIdMUST быть уникальным идентификатором запроса. SHOULD использовать UUID v4
requestorRoleMUST быть "master" или "slave", идентифицирующим инициатора запроса
requestTypeMUST быть одним из четырёх типов в таблице ниже
targetAgreementIdMUST быть указан, когда requestType"adjustment" или "termination"
proposedParamsMUST содержать полные AgreementParams (см. раздел 5.4)

5.2.2 RequestType

ЗначениеСемантикаОграничение
"collection"Запрос на сбор данныхMUST инициироваться requestorRole = "master"
"injection"Запрос на инжекцию данныхMUST инициироваться requestorRole = "slave"
"adjustment"Корректировка существующего AgreementMUST содержать targetAgreementId; целевой Agreement MUST находиться в состоянии active
"termination"Прекращение существующего AgreementMUST содержать targetAgreementId

Реализация MUST отклонять любой запрос, не удовлетворяющий приведённым выше ограничениям, и возвращать соответствующую ошибку (см. главу 9).

5.2.3 Response_Frame

Response_Frame MUST содержать следующие поля:

interface ResponseFrame {
  frameType: "response";
  requestId: string;
  result: NegotiationResult;
  agreedParams?: AgreementParams;
  agreementId?: AgreementID;
  rejectionReason?: string;
}
ПолеНормативное требование
frameTypeMUST быть литералом "response"
requestIdMUST быть requestId соответствующего Request_Frame
resultMUST быть одним из значений NegotiationResult
agreedParamsMUST быть указан, когда resultaccepted или counter_proposal
agreementIdMUST быть указан, когда resultaccepted; MUST быть вновь сгенерированным UUID v4
rejectionReasonMUST быть указана, когда resultrejected

5.2.4 NegotiationResult

NegotiationResult MUST быть одним из следующих трёх значений:

ЗначениеСемантика
"accepted"Принять запрос
"rejected"Отклонить запрос
"counter_proposal"Предложить альтернативу

Реализация MUST NOT возвращать значения результата, не указанные в списке.

5.3 Процесс переговоров

5.3.1 Переговоры по сбору данных (инициируются Master)

Переговоры по сбору данных MUST следовать данному процессу:

  1. Master отправляет Request_Frame с requestType = "collection" и requestorRole = "master".
  2. Slave MUST ответить Response_Frame с одним из следующих трёх результатов:
    • "accepted": согласие передавать в соответствии с proposedParams. MUST включать вновь сгенерированный agreementId в Response_Frame.
    • "rejected": отказ от передачи. MUST указать ограничение, связанное с соответствием требованиям (например, политика DLP), в rejectionReason. MUST NOT отказывать по причинам, не связанным с соответствием.
    • "counter_proposal": предложение альтернативных параметров. MUST предоставить изменённые параметры в agreedParams.
  3. Если Slave отвечает counter_proposal, Master MAY отправить новый Request_Frame, чтобы принять, отклонить или продолжить переговоры.
  4. Master MUST сохранять результат ответа Slave для каждого запроса на сбор данных.

5.3.2 Переговоры по инжекции данных (инициируются Slave)

Переговоры по инжекции данных MUST следовать данному процессу:

  1. Slave отправляет Request_Frame с requestType = "injection" и requestorRole = "slave".
  2. Master MUST ответить Response_Frame с одним из следующих трёх результатов:
    • "accepted": согласие предоставить данные. MUST описать отфильтрованную область данных (минимизированный набор данных) в agreedParams. MUST включать вновь сгенерированный agreementId в Response_Frame.
    • "rejected": отказ от предоставления данных. SHOULD указать причину в rejectionReason.
    • "counter_proposal": предоставление данных другой области или формата. MUST описать альтернативу в agreedParams.
  3. Master MUST обладать полным правом принятия решения по инжекции данных и MUST NOT принуждаться к принятию запроса.

5.3.3 Тайм-аут переговоров

Реализация MUST устанавливать пороговое значение тайм-аута для Request_Frame. Если Response_Frame от пира не получен в пределах порогового значения:

  1. Инициатор SHOULD повторно отправить Request_Frame; число повторов MUST NOT превышать настроенный реализацией верхний предел.
  2. После достижения верхнего предела повторов инициатор MUST прекратить переговоры и уведомить приложение верхнего уровня об ошибке AGREEMENT_NEGOTIATION_FAILED (3003).

5.4 AgreementParams

AgreementParams MUST содержать следующие поля:

interface AgreementParams {
  dataType: string;
  dataRange: string;
  transferMode: TransferMode;
  frequency: number | null;
  validityPeriod: number;
  priority: Priority;
}
ПолеТипНормативное требование
dataTypestringMUST быть непустой. Идентифицирует тип данных
dataRangestringMUST быть непустой. Описывает область данных
transferModeTransferModeMUST быть одним из трёх значений в таблице ниже
frequencynumber | nullВ Гц. MUST быть null при transferMode = "one_time"; MUST быть положительным числом для других режимов
validityPeriodnumberВ миллисекундах. MUST быть положительным целым числом
priorityPriorityMUST быть одним из четырёх значений в таблице ниже

5.4.1 TransferMode

ЗначениеСемантика
"one_time"Однократная передача. Agreement SHOULD автоматически прекращаться после завершения передачи
"periodic"Периодическая передача. MUST задавать frequency
"streaming"Потоковая передача. MUST задавать frequency

5.4.2 Priority

ЗначениеСемантика
"low"Низкий приоритет
"normal"Нормальный приоритет (по умолчанию)
"high"Высокий приоритет
"critical"Критический приоритет

Реализация SHOULD планировать конкуренцию ресурсов между несколькими Agreement в соответствии с priority.

5.5 Жизненный цикл Agreement

5.5.1 Определения состояний

AgreementStatus MUST быть одним из следующих четырёх значений:

СостояниеСемантика
"negotiating"Идут переговоры
"active"Agreement действует; идёт передача данных
"suspended"Соединение разорвано; Agreement приостановлен
"terminated"Agreement прекращён

5.5.2 Переходы состояний

Состояние Agreement MUST соответствовать следующим правилам переходов:

Текущее состояниеТриггерное событиеЦелевое состояние
(нет)Отправлен Request_Framenegotiating
negotiatingResponse_Frame возвращает acceptedactive
negotiatingResponse_Frame возвращает rejected(прекращён)
activeНижележащее соединение разорваноsuspended
activeПолучен Request_Frame типа terminationterminated
activeИстёк validityPeriodterminated
suspendedСоединение восстановлено и повторная верификация CAP пройденаactive
suspendedТайм-аут храненияterminated
terminated(терминальное состояние)(нет)

5.5.3 Автоматическое прекращение однократных Agreement

Когда transferMode = "one_time" и передача данных завершена:

  1. Отправитель MUST прекратить Agreement после последнего Fragment, отправив Request_Frame с requestType = "termination".
  2. Получатель MUST установить состояние Agreement в terminated после получения и подтверждения всех Fragment.

5.6 Одновременность нескольких Agreement

Реализация DTP MUST поддерживать одновременное существование нескольких Agreement в состоянии active в рамках одной Session.

Реализация MUST обеспечивать:

  1. Каждый Fragment связан с конкретным Agreement через свой Agreement_ID.
  2. Fragment, принадлежащие разным Agreement, MAY чередоваться в потоке передачи.
  3. Конкретный способ передачи нескольких Agreement (последовательный или параллельный) DEPENDS от возможностей нижележащего Transport_Adapter.
  4. Реализация MUST NOT ограничивать максимальное число активных Agreement в одной Session значением менее 16. SHOULD поддерживать произвольное число.

5.7 Ограничения переговоров для Observer

Роль Observer MUST удовлетворять следующим требованиям:

  1. MUST NOT отправлять Request_Frame. Если Observer пытается отправить такой фрейм, DTP_Engine MUST отклонить операцию и вернуть ошибку OBSERVER_WRITE_DENIED (8002).
  2. MUST NOT получать какие-либо права принятия решения по Response_Frame.
  3. MAY получать копии data-фреймов только для чтения.
  4. MUST быть явно авторизован Controller при подключении в качестве Observer.