Skip to content

Команды протокола

Эта страница фиксирует текущий JSON command set из Engine/Proto/CommandType.h. Реальный формат сообщений VideoGrace — объект с одним ключом-командой:

{
  "connect_request": {
    "channel_type": 0,
    "login": "user@example.com",
    "password": "secret"
  }
}

Не использовать устаревший envelope вида {"command":"...","data":{...}}.

Группы команд

Группа Команды
Auth/session connect_request, connect_response, disconnect, change_server, ping, sso_negotiate_request, sso_negotiate_response
User/account user_update_request, user_update_response, update_grants, set_max_bitrate
Contacts/groups contact_list, search_contact, contacts_update, group_list, group_update_request, group_update_response, change_contact_state
Conferences conferences_list, conference_update_request, conference_update_response, create_temp_conference, send_connect_to_conference, connect_to_conference_request, connect_to_conference_response, disconnect_from_conference, change_member_state, member_action, want_speak, turn_speaker, schedule_connect
Devices/media control device_params, device_connect, device_disconnect, renderer_connect, renderer_disconnect, resolution_change, microphone_active, request_media_addresses, media_addresses_list, webrtc_routes_request, webrtc_routes, webrtc_offer, webrtc_answer, webrtc_ice_candidate
Messages/blobs delivery_messages, load_messages, delivery_blobs, load_blobs
Offline push push_subscription_update

Auth/session

connect_request

Первое сообщение после открытия WebSocket. Для CommandLoop передает credentials, для WSMedia и BlobChannel передает access_token.

{
  "connect_request": {
    "client_type": 0,
    "channel_type": 0,
    "client_version": 100,
    "system": "Web",
    "login": "user@example.com",
    "password": "secret",
    "avatar_hashes": {
      "223900002": "c9a04c225a72b54101e427e637c08f602c7f786fd5529f890b9f621fe7b58626"
    }
  }
}

Поля:

Поле Тип Назначение
client_type number 0=Ordinal, 1=MediaProcessor, 2=Connector, 3=Recorder.
channel_type number 0=CommandLoop, 1=WSMedia, 2=BlobChannel.
client_version number Версия клиента.
system string Платформа/окружение клиента.
login string Логин для CommandLoop.
password string Пароль для CommandLoop.
access_token string Token для дополнительных каналов.
avatar_hashes object Необязательный cache manifest аватаров: client_id -> SHA-256 в lower-case hex. Используется только для CommandLoop.

connect_response

Ответ сервера на connect_request.

{
  "connect_response": {
    "result": 1,
    "server_version": 100,
    "id": 223900001,
    "connection_id": 1,
    "access_token": "opaque-token",
    "name": "User",
    "redirect_url": "",
    "secure_key": "",
    "server_name": "VideoGrace",
    "options": 0,
    "grants": 0,
    "max_output_bitrate": 4096
  }
}

result: 0=Undefined, 1=OK, 2=InvalidCredentials, 3=UpdateRequired, 4=Redirect, 5=ServerFull, 6=InternalServerError, 7=Banned.

disconnect

Команда закрытия session. На сервере также может приходить как server-side kick/disconnect event.

{ "disconnect": {} }

change_server

Сервер просит клиента перейти на другой URL.

ping

Легковесная проверка живости control channel. Не заменяет reconnect policy.

Contacts/groups

search_contact / contact_list

search_contact запрашивает список контактов. Пустой query означает полный список. Клиент может передать хеши уже сохраненных аватаров:

{
  "search_contact": {
    "query": "",
    "avatar_hashes": {
      "223900002": "6f4a9b73a40780ba4f511ca9d54054f84d8f5608c5b5aa3f3f64a3d474ee35a2"
    }
  }
}

Сервер отвечает contact_list. Для каждого участника действуют delta-правила:

Поля участника Значение
avatar и avatar_hash присутствуют Аватар новый или изменился. Клиент заменяет кэш и сохраняет новый SHA-256.
avatar отсутствует Хеш совпал. Клиент сохраняет ранее закэшированный аватар, а не очищает его.
avatar равен пустой строке Аватар удален. Клиент очищает аватар и сохраненный хеш.

avatar_hashes можно передавать и в CommandLoop connect_request: сервер применит тот же cache manifest к начальному contact_list, отправляемому сразу после входа. Хеш считается от точной строки поля avatar, обычно это data URL. Сервер принимает не более 10 000 записей с 64-символьным хешем.

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

Conferences

connect_to_conference_request

Вход в конференцию.

{
  "connect_to_conference_request": {
    "tag": "default",
    "connect_members": 1,
    "has_camera": 1,
    "has_microphone": 1,
    "has_demonstration": 0
  }
}

connect_to_conference_response

Результат входа в конференцию. OK переводит клиента в conferencing state; NotAllowed, NotExists, LicenseFull возвращают в ready state.

create_temp_conference

Создание временной конференции для p2p call flow. После ответа клиент приглашает второго участника через send_connect_to_conference.

send_connect_to_conference

Invite-команда: один клиент просит сервер подключить другого участника к конференции.

disconnect_from_conference

Выход из конференции. Перед ним клиент должен удалить локальные capturer devices.

change_member_state

Серверная рассылка изменения состава/состояния участников.

member_action, want_speak, turn_speaker

Команды управления участниками и speaker flow. Доступность зависит от conference/member grants.

Devices/media control

device_params

Запрос на создание локального capturer device.

{
  "device_params": {
    "id": 0,
    "ssrc": 0,
    "device_type": 1,
    "ord": 0,
    "name": "Camera",
    "metadata": "",
    "resolution": 31457920,
    "color_space": 0
  }
}

device_connect

Серверное событие о подключении device. Для автора my=1, для удаленных клиентов my=0.

Ключевые поля:

Поле Назначение
connect_type 1=CreatedDevice, 2=ConnectRenderer.
device_type 1=Camera, 2=Demonstration, 4=Microphone, 5=VideoRenderer, 6=AudioRenderer.
device_id Control lifecycle id устройства.
receiver_ssrc SSRC для приема remote stream.
author_ssrc SSRC автора/local publish.
port Порт media translator.
secure_key Ключ payload encryption.

device_disconnect

Удаление capturer device. Shared media transport не закрывается.

renderer_connect / renderer_disconnect

Native renderer lifecycle для UDP receive path. В browser WSMedia mux роль renderer выполняет локальная регистрация receiver_ssrc в demux.

request_media_addresses / media_addresses_list

Запрос списка media endpoints: RTP ports и WSS fallback endpoint.

webrtc_routes_request / webrtc_routes

Запрос списка RTC routes для WebRTC primary media path.

{ "webrtc_routes_request": {} }

Ответ:

{
  "webrtc_routes": {
    "routes": [
      {
        "rtc_node_id": "rtc-eu-1",
        "role": "rtc-translator",
        "version": "3.0.0",
        "capabilities": ["rtc", "webrtc", "rtp_bridge"]
      }
    ]
  }
}

rtc_node_id передается в webrtc_offer и webrtc_ice_candidate. Если route не подключился при первичном создании endpoint'а в режиме auto, клиент пробует следующую route, затем может перейти на WSMedia fallback. Для уже успешно поднятого WebRTC endpoint'а stale/stall recovery выполняется через WebRTC restart/backoff без WSM fallback.

webrtc_offer / webrtc_answer / webrtc_ice_candidate

WebRTC signaling поверх CommandLoop.

{
  "webrtc_offer": {
    "peer_id": "remote-video-1006-228800002",
    "conference_tag": "radio",
    "scope": "video-subscribe",
    "rtc_node_id": "rtc-eu-1",
    "endpoint_id": "video-subscribe-uuid",
    "sdp": "v=0...",
    "device_id": 1006,
    "author_ssrc": 1042,
    "receiver_ssrc": 1044,
    "port": 5060
  }
}

endpoint_id коррелирует answer и ICE с конкретным RTCPeerConnection. Подробный flow описан в WebRTC media transport.

Messages/blobs

delivery_messages / load_messages

Доставка и загрузка сообщений. Сообщение описывается структурой Message.

Полный контракт отправки, начального snapshot, cursor pagination, offline-догона, локального кеша и прав удаления описан в разделе Чаты и история сообщений.

Актуальный wire format delivery_messages содержит массив:

{
  "delivery_messages": [
    {
      "guid": "msg-uuid",
      "dt": 1788000000,
      "type": 1,
      "author_id": 228800010,
      "sender_id": 228800010,
      "subscriber_id": 228800112,
      "status": 1,
      "text": "{\"type\":\"simple\",\"message\":\"Добрый день\"}"
    }
  ]
}

Начальный клиент запрашивает latest_per_chat, выбранный чат загружается страницами по contact_id или conference_tag, а incremental-догон после reconnect использует from_dt.

Семантика IM-сообщений

guid является стабильным идентификатором сообщения. Клиент должен применять входящие delivery_messages идемпотентно по guid.

Статусы Modified и Deleted являются update-событиями существующего сообщения:

Статус Код Поведение клиента
Created 1 Создать новое сообщение.
Sended 2 Обновить статус исходящего сообщения.
Delivered 3 Обновить статус доставки.
Readed 4 Обновить статус прочтения.
Modified 5 Найти сообщение по guid, заменить пользовательский payload, сохранить исходное время сообщения в UI.
Deleted 6 Найти сообщение по guid и убрать его из UI без tombstone-заглушки. Payload удаленного сообщения не использовать.

При offline-догоне клиент отправляет load_messages с последним известным dt. Сервер возвращает сообщения, у которых dt > from или modify_dt > from, поэтому Modified и Deleted догоняются после offline так же, как новые сообщения.

Для Deleted сервер не должен отдавать пользовательский текст, preview или url. Клиенты также должны игнорировать payload, если он ошибочно присутствует.

Если удаляемое сообщение содержит ссылки на storage attachments вида /api/storage/blobs/<blob_id>, сервер удаляет связанные объекты из storage. Blob не удаляется, если на него еще ссылается другое не удаленное сообщение.

Реакции на сообщения

Реакции передаются как отдельные service-сообщения, а не как изменение текста исходного сообщения. Это защищает от гонок, когда несколько пользователей одновременно реагируют на один guid.

Формат:

{
  "guid": "reaction-uuid",
  "dt": 1777440100,
  "type": 14,
  "author_id": 223900001,
  "sender_id": 223900001,
  "subscriber_id": 223900002,
  "conference_tag": "",
  "status": 1,
  "text": "{\"type\":\"vg.reaction.v1\",\"target_guid\":\"msg-uuid\",\"reaction\":\"👍\",\"action\":\"set\"}"
}

Payload text:

Поле Тип Назначение
type string Всегда vg.reaction.v1.
target_guid string guid сообщения, к которому относится реакция.
reaction string Значение реакции, например 👍, ❤️, 😂.
action string set или remove.

Клиент не показывает reaction service-сообщения в ленте и не использует их как last message. UI агрегирует последнее reaction-событие каждого author_id по паре target_guid + author_id. Если пришло remove, реакция этого пользователя с целевого сообщения снимается.

Реакции не создают push-уведомления и не должны увеличивать счетчик непрочитанных сообщений. Это служебная синхронизация состояния сообщения, а не новое пользовательское сообщение.

Реакции в комнате конференции

Быстрая реакция из панели VideoRoom передается отдельным ServiceMessage с conference_tag текущей конференции. У такого события нет target_guid: оно относится ко всей комнате, а не к сообщению чата.

Формат:

{
  "guid": "conf-reaction-uuid",
  "dt": 1777440600,
  "type": 14,
  "author_id": 223900001,
  "sender_id": 223900001,
  "subscriber_id": 0,
  "conference_tag": "daily",
  "status": 1,
  "text": "{\"type\":\"vg.conference.reaction.v1\",\"reaction\":\"👏\"}"
}

Payload text:

Поле Тип Назначение
type string Всегда vg.conference.reaction.v1.
reaction string Значение реакции, например 👍, 👏, ❤️, 😂, 🔥.

Клиент не показывает эти service-сообщения в чате и не использует их как last message. UI конференции показывает входящее событие как короткую floating-анимацию поверх VideoRoom; старые события из offline DB при входе не должны проигрываться заново.

Реакции комнаты не создают push-уведомления и не должны увеличивать счетчик непрочитанных сообщений.

delivery_blobs / load_blobs

Legacy-доставка и загрузка blob metadata/data. Новые вложения чатов используют HTTPS storage API: upload session, chunked PUT, complete, затем ссылка /api/storage/blobs/<blob_id> в тексте сообщения.

Offline push

push_subscription_update

Клиент регистрирует или удаляет endpoint/token для offline-уведомлений. Подробный контракт для browser Web Push и native FCM описан в разделе Offline Push.

chat_mute_list / chat_mute_update

Персональные настройки отключения уведомлений для контактов и конференций. chat_mute_list приходит как полный snapshot после login, chat_mute_update меняет настройку и возвращает подтверждение всем активным сессиям пользователя. Контракт, семантика и примеры описаны в разделе Чаты и история сообщений.

Правило добавления новой команды

  1. Добавить Cmd*.h/.cpp в Engine/Proto.
  2. Добавить enum value в Engine/Proto/CommandType.h.
  3. Добавить detection в Engine/Proto/CommandType.cpp.
  4. Добавить обработку в Server/Http/HttpServer.h.
  5. Добавить метод в IProcessor/Processor, если команда серверная.
  6. Добавить client-side handling в Engine/Controller и/или web-client.
  7. Обновить эту страницу и сценарии.