Skip to content

Latest commit

 

History

History
73 lines (47 loc) · 13.1 KB

File metadata and controls

73 lines (47 loc) · 13.1 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Язык документации и комментариев — русский; коды, имена сообщений/полей, команды — в оригинале.

⛔ ГРАНИЦА РЕПОЗИТОРИЯ (жёсткое правило)

dcvp-serverотдельный git-репозиторий (github.com/uzmasterdev/dcvp-server), физически вложенный в монорепо voyah-courage. Работать строго в пределах этого репозитория — корень /Users/saidakbar.sadikov/code/voyah-courage/soft/dcvp-server.

  • НЕ читать, НЕ править, НЕ создавать, НЕ искать файлы вне этой папки: ни в ../ (soft/), ни в ../../ (voyah-courage/), ни в соседних ../firmware/, ../../docs/, ../../experience/ и т.д. Все пути, начинающиеся с ../, — за границей и трогать их нельзя.
  • grep/find/ls/Read/Edit/Write запускать только по путям внутри dcvp-server. Не подниматься выше корня репозитория.
  • Ссылки в коде и docs на ../firmware/tbox-power-and-redirect.md (§C.*) — это внешний первоисточник реверса, только для сведения. Не открывать его и не зависеть от него: всё нужное для работы уже перенесено в этот репозиторий (README.md, docstring server/dcvp_server.py, docs/).
  • Родительские CLAUDE.md (soft/ и корень voyah-courage) и так подаются автоматически — читать их файлы вручную не нужно; при конфликте это правило о границе имеет приоритет.

Исключение — только по явной просьбе пользователя выйти за границу в конкретный файл; по своей инициативе — никогда.

Что это

Приёмный сервер телематического протокола DCVP (Dongfeng Cloud Vehicle Platform) для блока T-BOX нашей машины (T_BOX_H37A3630849BA). Цель — принимать штатную выгрузку T-BOX на свой сервер в бортовой сети, без китайского облака. Протокол восстановлен статическим реверсом прошивки tsp_manager — правок на живой машине нет. Полный контекст — в README.md, первоисточник реверса — ../firmware/tbox-power-and-redirect.md (§C), на которую ссылаются комментарии в коде (§C.3, §C.4, §C.5).

⚠️ Исследовательский стенд для собственного авто. Реальные device-секреты (rsa_aes_tbox.key, боевой client.crt, tbox.pfx, ca.pem) и идентификаторы машины (VIN/ICCID/IMEI/MAC/GPS) сюда класть нельзя; значения в client/fake_tbox.py — синтетические заглушки.

Команды

make certs     # свой лабораторный CA + server/client cert (локально, gitignored)
make build     # docker-образ; protobuf-байндинги генерятся ВНУТРИ из .proto
make up        # сервер на :6504/:6507 (сессия) + :6553 (HTTPS-логи), лог в консоль (== certs)
make client    # синтетический клиент: полный цикл login→binding→loc→N×(heartbeat+veh)→logout
make logs      # docker compose logs -f dcvp-server
make stats     # сводка по базе принятого (logs/dcvp.sqlite3)
make export    # JSONL-выгрузка → logs/export.jsonl (SINCE=… TABLE=… VIN=…)
make raw       # hexdump сырого захвата соединений logs/raw/ (FILE=… LIMIT=…)
make down      # остановить;  make clean — down -v + снести сгенерённые cert'ы
make gen       # сгенерить *_pb2.py локально (нужен protoc: python -m grpc_tools.protoc) — для правки вне докера

Тестового фреймворка нет — проверка сквозная: поднять сервер (make up) и прогнать против него клиент (make client), глядя на лог кадров/ACK и на базу (make stats / make export). Без docker: сгенерить байндинги в отдельный каталог (python -m grpc_tools.protoc -Iproto --python_out=<gen> proto/vcp_custom_message.proto) и запустить PYTHONPATH=<gen>:server DCVP_LOGDIR=<data> python server/dcvp_server.py --plaintext --ports 16504 --log-port 16553, клиент — PYTHONPATH=<gen> python client/fake_tbox.py --plaintext --port 16504. Отладка без TLS: добавить серверу флаг --plaintext или --no-client-certdocker-compose.yml, поле command), клиенту — --plaintext.

Байндинги vcp_custom_message_pb2.py не коммитятся — генерятся из .proto при docker build/app/gen) или через make gen. Код без них деградирует до hexdump (HAVE_PB=False).

Архитектура

Три части, обёртка кадра — китайский нацстандарт GB/T 32960, внутри едет protobuf. Чтобы понять систему, читать в связке proto/vcp_custom_message.protoserver/dcvp_server.pyclient/fake_tbox.py (клиент и сервер должны строить/разбирать кадр одинаково).

  • proto/vcp_custom_message.proto — схема данных (пакет tboxev.vcp, proto2, 68 сообщений / 534 поля), извлечённая из встроенного FileDescriptorProto в .rodata бинаря tsp_manager (не protoc'ом, декодером wire-формата). Только имена — секретов нет. Ключевые сообщения: in_binding_info (хендшейк), in_veh_data (97 полей состояния), in_location_data, in_general_config (адрес платформы).

  • server/dcvp_server.py (~450 строк, stdlib + protobuf, потоки на соединение) — приёмник:

    • serve() слушает несколько портов; порты сессии (6504/6507) идут в handle_session, порт логов (6553) — в handle_log_upload (отдельный HTTPS POST /log/logReceiveGateway, канал libcurl, не GB/T).
    • gb_deframe() нарезает TCP-поток на кадры: ищет старт ## (0x23 0x23), длина data-unit — big-endian по смещению 22, контроль — XOR-BCC (gb_bcc, не CRC). Пропускает мусор, придерживает недочитанный кадр — это ядро устойчивости, не упрощать.
    • Диспетч по cmd (байт[2]); cmd=0xCB (заводской диапазон 0x80..0xFE) — custom-кадр, data-unit распаковывается как protobuf (try_decode перебирает типы, берёт полностью поглотившие payload и ранжирует: required на месте → меньше unknown-полей → больше распознанных → тип из TOP_CANDIDATES; альтернативы уходят в базу). enc=0x02 (AES) помечается, не парсится (ключа нет).
    • make_ack() строит GB-ACK (resp=0x01) — без него T-BOX ловит response_TimeOut и переоткрывает сессию. Отвечаем только на запросы (resp=0xFE) с верным BCC, не на чужие ACK и не на битые кадры. ACK минимальный (эхо time+serial для login/logout, header-only для heartbeat) — точная структура data-unit ACK статически не выведена.
    • Порядок в handle_session: analyze_framestore.add_frame → ACK → mark_acked. Персист до ACK (FR-5) — не переставлять. Ошибка базы логируется как STORE-ERR и сессию не роняет.
    • Консоль — не место для координат/ICCID/серийников (SEC-9): mask_text()/MASK_FIELDS режут их в дампе protobuf, login data-unit печатается только как time+serial. Полные значения — только в базе.
  • server/store.py — хранилище (FR-15…17): SQLite (stdlib, WAL, одно соединение под Lock) в DCVP_LOGDIR + uploads/ для тел журналов. Таблицы sessions / frames (каждый кадр сырьём raw + разбор pb_json + status) / log_uploads / meta. Схема версионируется: SCHEMA_VERSION + MIGRATIONS[n]старые миграции не править, только добавлять следующую; база новее кода → отказ на старте. Retention DCVP_RETENTION_DAYS (0 = хранить всё) — purge() на старте и раз в час. Экспорт/статистика/ручная чистка — server/dcvp_export.py. Сырьё хранится всегда: без него нечего будет сверять с живым перехватом.

  • server/rawcap.py — сырой захват каждого соединения до кадрирования (DCVP_RAW_CAPTURE=1 по умолчанию) в logs/raw/<ts>_<port>_<peer>.raw: записи 'DR'|ts|dir|len|payload, без буферизации. Это страховка на первый живой трафик: если раскладка кадра окажется не такой, как выведена статически, байты всё равно на диске. handle_session вызывает cap.rx() на каждый recv и cap.tx() на каждый ACK, на закрытии печатает недокадрованный хвост (TAIL). Читать — dcvp_export.py raw. Не убирать, пока формат не подтверждён живым блоком.

  • postman/ — коллекция для пробы канала логов 6553 из Postman (сырой TCP-сессии Postman не умеет). Секретов нет: VIN/tbox_id синтетические.

  • client/fake_tbox.py — синтетический T-BOX: гоняет login(0x01) → in_binding_info → in_location_data → N×(heartbeat(0x07) + in_veh_data) → logout(0x04), печатает ACK. Позволяет отлаживать приёмник без живой машины и без qemu-стенда.

Формат кадра GB/T 32960 задокументирован в docstring server/dcvp_server.py и в README.md (таблица смещений). Правишь раскладку кадра/BCC — правь синхронно в сервере и клиенте.

  • harness/README.md — план (пока только план, без скриптов) qemu-стенда: запуск настоящего tsp_manager под qemu-user (aarch64) с LD_PRELOAD-стабами железа, чтобы снять ground-truth формата сессии/ACK, оставшийся невыясненным при статическом реверсе.

  • certs/gen-ca.sh — генератор нашего лабораторного CA + server/client cert. SAN серверного cert включает боевые хосты платформы (vdcvpapinx.dfmc.com.cn и т.п.) — под подмену ca.pem в trust store T-BOX (§C.3). Вся папка certs/ gitignored.

ТЗ

docs/REQUIREMENTS.md — индекс, подТЗ в docs/requirements/*.md, разбиты по областям. Сквозные идентификаторы (FR-*, NFR-*, SEC-*, NOT-*) уникальны по всему ТЗ; канон каждого — в его «домашнем» файле (см. карту в §3 индекса), из других файлов на него ссылаются, не дублируют. Реализованы пока только телематический приёмник и хранение принятого (telematics.md: FR-1…FR-8, FR-14…FR-17) — FR-9 (нормализованная модель телеметрии), backend-API, биллинг, PKI-провижининг, SMS-канал и т.д. в коде отсутствуют, есть только требования.