Define BLE v5 visibility, admission and bounded publication contracts

This commit is contained in:
evgeny committed 2026-10-31 00:37:11 +01:00
1 parent 5deb6de7ee
commit d00a642c49
3 files changed
+19 -11

No files matched your search

+1
View File
@@ -329,6 +329,7 @@ int ble_advertise(struct ble_transport* t, const void* data, size_t len) {
return ble_backend_advertise(t->backend, data, len);
}
ble_link_id ble_connect(struct ble_transport* t, const struct ble_endpoint* ep, uint64_t peer) {
if (!peer) { DEBUG_ERROR(CAT, "BLE connect requires expected peer service identity"); return 0; }
if (!t || !t->ready) { DEBUG_WARN(CAT, "BLE connect before ready"); return 0; }
struct ble_connection* c = new_link(t, ep, 1, peer);
if (!c) return 0;
+8 -7
View File
@@ -39,7 +39,7 @@ struct ble_advertising_power {
/* Копия возможностей активного радио, без I/O; NULL/не готово возвращает неизвестные значения. Только uasync. */
struct ble_advertising_power ble_get_advertising_power(const struct ble_transport* transport);
struct ble_callbacks {
/* Объявление нужного company_id; буфер заимствован до возврата. RSSI=127 означает неизвестный. */
/* Node UUID из объявления сервиса: общий ble_identity bytes; буфер заимствован. RSSI=127 — неизвестный. */
void (*broadcast)(void* arg, const struct ble_endpoint* endpoint, const uint8_t* data, size_t len, int rssi);
void (*status)(void* arg, enum ble_state state, const char* reason); /* Состояние радио, reason заимствован. */
void (*advertising)(void* arg, enum ble_state state, const char* reason); /* Публикация bytes: READY не подтверждает приём. */
@@ -52,14 +52,14 @@ struct ble_callbacks {
};
struct ble_config {
uint64_t node_id; /* Ненулевой ID для HELLO; не криптографическое доказательство. */
uint16_t company_id; /* Manufacturer ID, одинаковый у участников. 0xffff только для разработки. */
uint16_t company_id; /* Необязательные метаданные имени Android; адресация определяется UUID, а не manufacturer. */
const char* adapter; /* Linux: hci0 либо NULL (первый адаптер); Windows: NULL. Копируется. */
struct ble_callbacks callbacks;
void* arg; /* Заимствованный контекст callbacks, живёт до destroy. */
unsigned tx_limit; /* Целых TX-пакетов, включая фрагментируемый: 0=64, 1..64. */
unsigned tx_window; /* DATA в очереди/отправке/ожидании удалённого ACK: 0=BLE_TX_WINDOW_FRAMES, 1..64. */
uint8_t initial_advertisement[BLE_BROADCAST_MAX]; /* Начальное объявление; копируется вместе с config. */
size_t initial_advertisement_size; /* 0: выключено; 1..24: Windows запускает publisher до GATT. */
size_t initial_advertisement_size; /* 0: скрыть идентичность в advertising; 1..24: объявлять node UUID сервиса. */
};
/* Создать остановленный transport. ua/config заимствованы только ua; возвращает handle или NULL с логом. */
struct ble_transport* ble_create(struct UASYNC* ua, const struct ble_config* config);
@@ -67,13 +67,14 @@ struct ble_transport* ble_create(struct UASYNC* ua, const struct ble_config* con
int ble_start(struct ble_transport* transport);
/* Остановить свои объявления/scan/сессии, завершить pending и освободить очереди. Идемпотентно, вне callbacks. */
void ble_stop(struct ble_transport* transport);
/* Разрешить/запретить новые входящие; запрет закрывает текущие входящие. По умолчанию разрешены. */
/* Разрешить/запретить наши новые входящие сессии; запрет закрывает текущие входящие. Общий ACL ОС этим не управляется. */
void ble_set_incoming(struct ble_transport* transport, int allowed);
void ble_destroy(struct ble_transport* transport); /* stop + free; NULL допустим. */
/* Заменить повторяемое manufacturer-объявление (0..24 байта); копирует данные. NULL,0 выключает его.
* Регистрация не гарантирует выход в эфир/получение. Собственное connectable-объявление сервиса независимо. */
/* Задать метаданные ble_identity и публиковать node UUID сервиса. NULL,0 скрывает UUID/метаданные в advertising.
* Сервис остаётся зарегистрированным для известных адресов; допуск определяет ble_set_incoming, не видимость.
* Регистрация не гарантирует выход в эфир/получение. Собственное имя Windows выбирается ОС. */
int ble_advertise(struct ble_transport* transport, const void* data, size_t len);
/* Самостоятельно выполнить connect/discovery/subscribe/HELLO. expected_node=0 не проверяет ID ответа.
/* Самостоятельно выполнить connect/discovery/subscribe/HELLO. expected_node ненулевой, задаёт UUID сервиса и ID ответа.
* Handle либо 0 при отказе. Готовность/ошибка — connection; физическое ACL может обслуживать другие сервисы. */
ble_link_id ble_connect(struct ble_transport* transport, const struct ble_endpoint* endpoint, uint64_t expected_node);
/* Копировать направление существующего GATT в outgoing (0/1). 0 — успех, -1 — неверный handle/аргументы с логом. */
+10 -4
View File
@@ -285,7 +285,8 @@ struct WinState : std::enable_shared_from_this<WinState> {
parameters.IsConnectable(true); parameters.IsDiscoverable(broadcast_enabled);
DEBUG_INFO(CAT, "BLE WinRT start single GATT advertisement UUID=%s connectable=1 discoverable=%d",
service_uuid.c_str(), broadcast_enabled);
service_requested = true; publication_deadline = get_time_us() + 20000000;
service_requested = true;
if (!publication_deadline) publication_deadline = get_time_us() + 20000000;
step("GattServiceProvider.StartAdvertising"); provider.StartAdvertising(parameters);
}
/* Один GATT provider обслуживает и обнаружение, и подключения; отдельного publisher нет. */
@@ -304,11 +305,14 @@ struct WinState : std::enable_shared_from_this<WinState> {
}
return;
}
if (status == GattServiceProviderAdvertisementStatus::Started) {
if (status == GattServiceProviderAdvertisementStatus::Started ||
status == GattServiceProviderAdvertisementStatus::StartedWithoutAllAdvertisementData) {
if (status != GattServiceProviderAdvertisementStatus::Started)
DEBUG_WARN(CAT, "BLE WinRT advertising omitted some fields UUID=%s; confirm service UUID on scanner", service_uuid.c_str());
publication_deadline = 0; service_ready = true;
ble_backend_advertising(owner, broadcast_enabled ? BLE_READY : BLE_CLOSED, "GATT discovery publication applied"); ready();
} else if (status == GattServiceProviderAdvertisementStatus::Aborted) radio_error("GATT advertising aborted", error);
else if (service_requested) fail("GATT advertisement stopped unexpectedly");
else if (service_requested && service_ready) fail("GATT advertisement stopped unexpectedly");
}
/* Только доступные Win11 API: фактические параметры отделены от запрошенного профиля. */
void log_connection(ble_link_id id) {
@@ -792,6 +796,7 @@ extern "C" struct ble_backend* ble_backend_create(struct ble_transport* owner, s
auto state = std::make_shared<WinState>(); state->owner = owner; state->ua = ua; state->company = cfg->company_id;
state->broadcast_size = cfg->initial_advertisement_size;
state->broadcast_enabled = state->broadcast_size != 0;
state->publication_deadline = get_time_us() + 20000000;
char uuid[37]; if (ble_service_uuid_encode(uuid, cfg->node_id)) return nullptr; state->service_uuid = uuid;
if (state->broadcast_size > state->broadcast.size()) { DEBUG_ERROR(CAT, "BLE WinRT initial advertisement too large"); return nullptr; }
if (state->broadcast_size) std::memcpy(state->broadcast.data(), cfg->initial_advertisement, state->broadcast_size);
@@ -827,9 +832,10 @@ extern "C" struct ble_backend* ble_backend_create(struct ble_transport* owner, s
if (!adapter.IsLowEnergySupported() || !adapter.IsCentralRoleSupported() || !adapter.IsPeripheralRoleSupported()) {
s.fail("adapter lacks BLE central/peripheral support"); return;
}
s.adapter_ready = true; WinState::diagnostics_tick(&s);
s.adapter_ready = true;
s.ensure_service();
});
WinState::diagnostics_tick(state.get());
void* memory = u_malloc(sizeof(ble_backend));
if (!memory) { DEBUG_ERROR(CAT, "BLE WinRT allocation failed"); state->shutdown(); return nullptr; }
return new(memory) ble_backend{state};