Het artikel behandelt de Android-only Aware-sessie-levenscyclus, het
publish / subscribe-ontdekkingsmodel, de twee-fase-rolverdeel-handshake
die requestNetwork aan beide kanten synchroniseert binnen het ~500 ms-
venster van het framework, de per-peer-link-pool met idle-sweeping, de
IPv6 + aangepaste-DNS-truc die een enkele OkHttp-client zowel LAN als
Aware laat bedienen, en de prewarmer die peer-Aware-startup via BLE
triggert.
Voor de bredere fallback-chain, zie Chatarchitectuur. Voor het BLE-transport dat overneemt wanneer Aware onbeschikbaar is, zie BLE-transport. Voor hoe de gedeelde ChaCha20-sleutel die wordt hergebruikt als de Aware-PMK wordt opgebouwd, zie het Koppelingsproces.
Inhoudsopgave
- Waarom Wi-Fi Aware?
- Waar Aware zit in de fallback-chain
- Sessie-levenscyclus: Attach → Publish + Subscribe
- Ontdekking en roltoewijzing
- De twee-fase-handshake (hello + ready)
- NDP requestNetwork — Het 500 ms-venster
- Per-peer-link-pool en idle-sweeping
- IPv6-adressering en de
plain-aware-peer-DNS-truc - Cryptografie: PMK-afleiding en ChaCha20-hergebruik
- Verzendpad voor berichten (end-to-end)
- Downloadpad voor bestanden (end-to-end)
- Prewarming: BLE-getriggerde Aware-startup
- Foutmodi en de fast-skip-vlag
- Referentie van sleutelconstanten
- Samenvatting van ontwerpafwegingen
Waarom Wi-Fi Aware? {#why-wi-fi-aware}
Wi-Fi Aware (IEEE 802.11bc, voorheen NAN — Neighbor Awareness Networking) is een Wi-Fi Alliance-certificering die twee apparaten in staat stelt elkaar te ontdekken en data uit te wisselen zonder enige Wi-Fi-infrastructuur — geen AP, geen router, geen DHCP. PlainApp gebruikt het voor twee scenario's die LAN niet kan dekken:
- Verschillende SSID's / VLAN's. Een telefoon op het gastnetwerk en een laptop op het IoT-VLAN zijn beide "online" via Wi-Fi maar kunnen elkaars IP niet bereiken. Aware creëert een direct apparaat-tot-apparaat-data-pad dat de infrastructuur volledig omzeilt.
- Helemaal geen infrastructuur. Twee apparaten in de wildernis met Wi-Fi aan maar zonder AP kunnen nog steeds chatten. (BLE dekt dit ook, maar Aware is veel sneller — ~10 ms round trips versus seconden, en MB/s versus tientallen KB/s.)
Platformbeperkingen
Wi-Fi Aware is alleen Android in PlainApp:
- Android 13 (API 33) is het minimum — de
WifiAwareNetworkSpecifier.Builder-overloads metsetPort()ensetPmk()waarvan PlainApp afhankelijk is, vereisenisTPlus(). - iOS ontsluit Wi-Fi Aware niet aan third-party apps. iOS-PlainApp valt
direct van LAN naar BLE; het
WifiAwareTransport-object wordt niet eens gecompileerd in de iOS-target (@RequiresApi(Build.VERSION_CODES.S)- androidMain-source-set).
Daarom roept PeerTransportRouter.buildListcreateWifiAwareTransport() aan — een factory die null retourneert op
iOS.
Waar Aware zit in de fallback-chain {#where-aware-sits-in-the-fallback-chain}
PlainApp's PeerTransportRouter is een geordende lijst. Voor elke send-
of downloadFile-aanroep loopt het de lijst af en probeert elk transport
totdat één slaagt; storingen cascaderen naar beneden.
Waarom is Aware "het midden" en niet "de eerste"?
Omdat LAN bijna altijd sneller is wanneer beschikbaar. Een same-subnet Wi-Fi-hop via een AP is een enkele 802.11-frame-uitwisseling; een Aware-data-pad voegt een NDP-setup toe (~5 s bij eerste gebruik) plus een tweede Wi-Fi-radi-context voor de apparaat-tot-apparaat-verbinding. Als beide bereikbaar zijn, wint LAN op latentie en doorvoer.
Omgekeerd is BLE altijd trager — maar het werkt wanneer beide apparaten maar gekoppeld zijn. Aware zit in het midden: sneller dan BLE, trager dan LAN, en alleen beschikbaar op Android 13+-apparaten met Wi-Fi aan.
Sessie-levenscyclus: Attach → Publish + Subscribe {#session-lifecycle-attach--publish--subscribe}
Een Wi-Fi Aware-sessie is procesbreed. Er is precies één
WifiAwareSession per apparaat; daarin draait PlainApp één
publish-sessie (zodat peers ons kunnen ontdekken) en één
subscribe-sessie (zodat we peers kunnen ontdekken). Beide worden
gestart zodra AwareSession.start() de attach-callback voltooit.
Waarom publish EN subscribe op hetzelfde apparaat?
Het Wi-Fi Aware-ontdekkingsmodel is asymmetrisch: een publisher
adverteert een service, een subscriber scant ernaar. Om ontdekking
symmetrisch te maken (beide apparaten ontdekken elkaar), doet PlainApp
beide tegelijk. Zonder dit zou apparaat A vooraf moeten weten of het
de publisher of de subscriber is voor een bepaalde peer — maar
peer-rollen worden later bepaald door clientId-vergelijking (zie
Ontdekking en roltoewijzing).
Tegelijkertijd publiceren en abonneren betekent dat elk apparaat elkaars
onServiceDiscovered ziet (als subscriber) EN elkaars hello-berichten
ontvangt (als publisher) — beide richtingen van de handshake zijn altijd
beschikbaar.
Auto-restart bij beëindiging
Sommige Android-varianten (met name MIUI) beëindigen langlopende
Aware-sessies om batterij te besparen. PlainApp handelt dit af in de
onSessionTerminated-callbacks: het zet de beëindigde sessie op null en
roept onmiddellijk opnieuw publishOwnService / subscribeOwnService
aan op de nog-verbonden WifiAwareSession. De attach-sessie zelf gaat
niet verloren — alleen de publish/subscribe-ontdekkingssessie.
Peer-handles van vóór de beëindiging worden stale, daarom controleert
awaitPeerHandle de discoveredAt-timestamp en verwijdert handles
ouder dan 30 s.
Ontdekking en roltoewijzing {#discovery--role-assignment}
Het Wi-Fi Aware-data-path-protocol vereist dat de ene kant optreedt als publisher (server) en de andere als subscriber (client). Beide kanten kunnen niet gelijktijdig de initiator zijn — het framework wijst verzoeken zonder een passende counterpart af.
PlainApp wijst rollen deterministisch per peer toe met een eenvoudige lexicografische vergelijking van clientIds:
Waarom deterministisch en niet onderhandeld?
Een onderhandelde aanpak (bijv. "lagere MAC is de server") zou een extra
bericht-uitwisseling vereisen. De lexicografische vergelijking is
idempotent, symmetrisch en stateless: beide apparaten berekenen
dezelfde rol voor hetzelfde paar zonder enige communicatie. De clientId is
een 13-tekens short UUID, dus gelijkspel (clientId == peer.id) treedt
alleen op bij vergelijking van een peer met zichzelf — wat nooit het
transport bereikt.
De rol bepaalt downstream twee dingen:
- Wie de hertry-loop aandrijft. Alleen de client probeert
requestNetworkopnieuw; de server doet precies één poging per ontvangen hello. Dit is kritiek voor het 500 ms-venster (volgende sectie). - Wie de poort instelt. De publisher roept
setPort(httpsPort)aan omdat het degene is die inkomende verbindingen accepteert op zijn HTTPS-serverpoort. De subscriber stelt geen poort in — hij leert de poort van de peer uit deWifiAwareNetworkInfonadat het data-pad is opgezet.
De twee-fase-handshake (hello + ready) {#the-two-phase-handshake-hello--ready}
Het moeilijkste deel van Wi-Fi Aware-data-path-setup is timing. Het
framework vereist dat beide kanten connectivityManager.requestNetwork
binnen ongeveer 500 ms van elkaar aanroepen — als de ene kant het
aanroept voordat de andere zijn passend verzoek heeft geregistreerd,
wijst het framework het onmiddellijk af met onUnavailable
("releaseRequestAsUnfulfillableByAnyFactory").
PlainApp lost dit op met een twee-bericht applicatie-laag-handshake
die draait bovenop het Aware L2-berichtkanaal (dezelfde sendMessage-
API die door onServiceDiscovered wordt gebruikt):
Waarom twee berichten (hello + ready) in plaats van slechts één?
De hello alleen is niet genoeg vanwege richtingsasymmetrie. De
subscriber kan hello verzenden zodra hij de publisher ontdekt (in
onServiceDiscovered), maar de publisher kan niet
requestNetwork starten totdat hij de PeerHandle van de subscriber
heeft, die hij pas leert door de hello te ontvangen. Dus de hello dient
twee doelen:
- De PeerHandle van de subscriber aan de publisher leveren. De
publisher heeft deze nodig om de
WifiAwareNetworkSpecifierte bouwen. - Intentie om te verbinden signaleren. Het ontvangen van de hello vertelt de publisher "de subscriber staat op het punt requestNetwork te doen, dus ik ook."
De ready-bevestiging bestaat voor de tegenovergestelde richting —
om de subscriber te vertellen "de publisher heeft zijn requestNetwork
geregistreerd." Zonder dit zou de requestNetwork van de subscriber
voor die van de publisher kunnen uitrennen en door het framework worden
afgewezen. De ready-bevestiging is een non-blocking signaal: de
subscriber wacht er niet op voordat hij requestNetwork aanroept (dat
zou een round-trip toevoegen), maar als het aankomt terwijl de
subscriber in IDLE-state is (tussen hertry-pogingen), kan de
subscriber onmiddellijk opnieuw proberen zonder op de
RETRY_DELAY_MS-gap te wachten.
De asymmetrie van de hertry-loop
Dit is het meest subtiele deel van het ontwerp. Alleen de subscriber
doet hertries. De publisher doet precies één requestNetwork-poging
per ontvangen hello. Dit komt omdat:
- Als beide kanten onafhankelijk hertries zouden doen, zouden hun
hertry-cycli uit fase drijven (verschillende
delay()-duren, verschillende GC-pauzes), en de tweerequestNetwork-aanroepen zouden zelden binnen het 500 ms-venster overlappen. - De hertry-loop van de subscriber stuurt bij elke poging een verse
hello, wat de
buildLinkvan de publisher opnieuw triggert viapublishHelloListeners. Dit garandeert dat derequestNetworkvan de publisher altijd op ~50 ms na de hello volgt, ruim binnen het 500 ms-venster.
Dit is in detail gedocumenteerd in
AwarePeerLink.build.
NDP requestNetwork — Het 500 ms-venster {#ndp-requestnetwork--the-500-ms-window}
De requestNetwork-aanroep is de meest timing-gevoelige operatie in het
Aware-transport. Hier is wat er aan elke kant gebeurt:
Wat de onUnavailable-callback betekent
onUnavailable vuurt wanneer het framework het requestNetwork afwijst
voordat een passend peer-verzoek wordt gevonden. De PeerHandle zelf is
nog steeds geldig — alleen de NDP (Neighbor Discovery Protocol)-
paring faalde omdat de andere kant nog niet had geregistreerd. PlainApp
roept in dit geval bewust nietsession.invalidatePeerHandle aan, omdat het
invalidaten van de handle het enige signaal zou weggooien dat
onServiceDiscovered ooit is aangeroepen (het vuurt één keer per peer
per levensduur van de subscribe-sessie). Met de handle behouden kan de
hertry deze hergebruiken in plaats van wachten op een verse ontdekking.
Hetzelfde geldt voor de publisher-zijde-handle van onMessageReceived —
de publisher behoudt de publishPeerHandles[fromCid]-entry over
mislukte pogingen, zodat de volgende hello van de subscriber de
gecachede handle hergebruikt in plaats van te worden gedropt.
Per-peer-link-pool en idle-sweeping {#per-peer-link-pool--idle-sweeping}
Elke gekoppelde peer krijgt zijn eigen AwarePeerLink-object, eigendom
van de procesbrede AwareLinkPool. De pool behandelt
ontdekkingsevenementen, link-hergebruik en idle-verwijdering.
Waarom niet auto-builden bij ontdekking?
De pool bouwt expliciet geen link wanneer onServiceDiscovered vuurt.
Dit is een kritieke beslissing: een drukke koffietent kan 100
PlainApp-apparaten hebben die allemaal de "plain-peer"-service
publiceren. Als elke ontdekking een requestNetwork zou triggeren,
zou het framework worden overspoeld met NDP-setup-pogingen en zou de
Wi-Fi-radio worden verzadigd.
In plaats daarvan noteert de pool alleen de PeerHandle en wacht op één van:
- De lokale gebruiker verzendt een bericht →
WifiAwareTransport.send→pool.buildLink(peer)(verzender-zijde-trigger). - De remote peer stuurt een hello →
onPublishHelloReceived→buildLink(peer)(ontvanger-zijde-trigger). - De remote peer stuurt een ready →
onSubscribeReadyReceived→buildLink(peer)(ontvanger-zijde-trigger).
Zo worden links alleen gebouwd voor peers waarmee de gebruiker daadwerkelijk berichten uitwisselt — niet elk PlainApp-apparaat in radiobereik.
Idle-sweep
Elke 10 seconden loopt de pool alle links langs en sluit elke link
waarvan lastActiveAt ouder is dan 60 seconden. Elke send en
downloadFile roept link.touch() aan om de timestamp te verversen.
Dit maakt de Wi-Fi-radi-context en OkHttp-connectie-pool vrij voor peers
waarmee de gebruiker is gestopt chatten — belangrijk omdat Android het
aantal gelijktijdige Aware-data-paden beperkt tot ongeveer 4–10
(apparaatafhankelijk).
IPv6-adressering en de plain-aware-peer-DNS-truc {#ipv6-addressing--the-plain-aware-peer-dns-trick}
Wi-Fi Aware-data-paden gebruiken alleen link-local IPv6. Er is geen
IPv4, geen DNS-server, geen DHCP. Het IPv6-adres van de peer wordt
geleverd via het WifiAwareNetworkInfo.peerIpv6Addr-veld in
onCapabilitiesChanged — een fe80::...-adres dat alleen betekenis
heeft op de Aware-netwerkinterface.
PlainApp moet HTTPS-verzoeken naar dit adres sturen, maar de
https://-URL-parsing van OkHttp weigert raw IPv6-literals in een
hostnaam (https://[fe80::abcd]:8443/ werkt, maar het via een aangepaste
Dns-resolver leiden is schoner). De truc:
Waarom een sentinel-hostnaam?
Het alternatief — de IPv6-literal direct in de URL doorgeven — zou
vereisen dat elke call-site op de hoogte is van het link-local-adres. Door
een sentinel-hostnaam te gebruiken is de URL-constructie identiek voor
LAN en Aware: beide produceren een geldige
https://<host>:<port>/peer_graphql-URL die OkHttp kan parsen. Het
enige verschil is de aan de client gebonden Dns-implementatie — LAN
gebruikt de systeem-DNS, Aware gebruikt awareDns(peerIpv6) die het
gecacheerde link-local-adres voor de sentinel-hostnaam retourneert en
voor al het andere naar Dns.SYSTEM doorvalt.
Waarom network.socketFactory?
Het Network-object van Android vertegenwoordigt een specifieke
netwerkinterface (in dit geval het Aware-data-pad). Door
network.socketFactory aan te roepen en het door te geven aan de
socketFactory-config van OkHttp, forceren we dat alle TCP-sockets op
de Aware-interface worden gecreëerd — niet de standaard Wi-Fi- of
cellulaire interface. Zonder dit zou het OS het verzoek via het
standaardnetwerk routeren, waar de link-local IPv6 onbereikbaar is, en
zou het verzoek falen met ENETUNREACH.
Cryptografie: PMK-afleiding en ChaCha20-hergebruik {#cryptography-pmk-derivation--chacha20-reuse}
Wi-Fi Aware ondersteunt een optionele PMK (Pairwise Master Key) voor het data-pad. Wanneer ingesteld, is de L2-link zelf versleuteld met die PMK — de Wi-Fi-radio handelt versleuteling af, geen applicatie-laag-crypto nodig.
PlainApp leidt de PMK af van dezelfde gedeelde ChaCha20-sleutel die
LanTransport en BleTransport gebruiken voor
applicatie-laag-versleuteling:
Waarom afkappen tot 32 bytes?
De Wi-Fi Aware-PMK moet exact 32 bytes (256 bits) zijn. De gedeelde
ChaCha20-sleutel uit koppeling is in het normale geval ook 32 bytes, dus
de raw.size == 32-tak is het algemene pad. De
afkap/opvul-fallback handelt het (theoretische) geval af waarin de
sleutel korter was opgeslagen — opvullen met nullen tot 32 bytes is een
defensieve maatregel, geen iets dat in de praktijk voorkomt bij correct
gekoppelde peers.
De ondertekende envelope is identiek aan LAN
Omdat createCryptoHttpClient dezelfde factory is die door LanTransport
wordt gebruikt, is de L7-crypto op Aware byte-voor-byte identiek aan
LAN. De PeerGraphQLService aan server-zijde weet niet (of kan het niet
schelen) welk transport het verzoek heeft afgeleverd — hij ziet slechts
een ondertekende, versleutelde GraphQL-payload en ontcijfert het met de
gedeelde sleutel van de peer. Dit is het "één codebase, vele transports"-
principe gedocumenteerd in Chatarchitectuur.
Verzendpad voor berichten (end-to-end) {#message-send-path-end-to-end}
Alles samenvoegend — wat gebeurt er wanneer een chatbericht via Wi-Fi Aware wordt verzonden:
Opmerkelijke ontwerpkeuzes
- Hergebruik van verbindingen. In tegenstelling tot
BleTransport, dat de GATT-verbinding na elk verzoek afbreekt, hergebruiktWifiAwareTransporthet Aware-data-pad voor zoveel verzoeken als de gebruiker doet binnen het 60 s-idle-venster. Het eerste verzoek betaalt de ~400 ms-handshake; volgende verzoeken zijn ~10 ms round-trips. - Dezelfde crypto als LAN. De ChaCha20-interceptor en ondertekende
envelope zijn byte-identiek aan LAN. De
PeerGraphQLServicevan de peer weet niet welk transport het verzoek heeft afgeleverd. - Geen preemption bij link-fout. Als
buildLinkfaalt, gooit het transportTransportUnavailableen valt de router door naar BLE. Er is geen hertry binnensend—AwarePeerLink.builddoet al zijn eigen interne hertry-loop (metMAX_BUILD_ATTEMPTS = 1aan de client-kant, meer als de prewarmer beide kanten heeft geprimed).
Downloadpad voor bestanden (end-to-end) {#file-download-path-end-to-end}
Bestandsdownloads via Aware hergebruiken hetzelfde data-pad als chatberichten, maar gebruiken een aparte OkHttp-client die is geconfigureerd voor het streamen van grote bestanden:
Waarom een aparte client voor downloads?
De chat-client (AwareHttpClientFactory.build) heeft een
30 s-requestTimeoutMillis — passend voor GraphQL-mutations maar
catastrofaal voor een 100 MB-bestandsdownload. De download-client
(buildFileDownload) stelt in:
connectTimeoutMillis = 10_000(langer dan de 5 s van chat, meer tolerant voor traag first-packet op een vers data-pad)readTimeout = 120 sper read (versus de impliciete standaard van 10 s)requestTimeoutMillis = 120_000(2 minuten — genoeg voor de meeste bestanden)retryOnConnectionFailure(true)— een verloren read midden in de download wordt opnieuw geprobeerd in plaats van de hele overdracht te laten falen
Het laat ook de ChaCha20-interceptor achterwege. Het /fs-endpoint
serveert ruwe bestands-bytes (geen ondertekende GraphQL-envelope), en de
L2-PMK (indien aanwezig) versleutelt al de radiolink. Dubbel versleutelen
van een 50 MB-video met ChaCha20 in software zou CPU verspillen en de
overdracht vertragen.
Streamen, niet bufferen
Zoals het BLE-pad, streamen Aware-downloads het bestand door een
ByteReadChannel — het bestand wordt naar een temp-bestand geschreven
zoals bytes aankomen, niet in memory gebufferd. PeerFileDownloader
leest 8 KB-chunks en emit elk seconde voortgangsevenementen. Dezelfde
DownloadedResponse / PeerFileDownloader / DownloadQueue-pijplijn
wordt hergebruikt over alle transports — alleen de channel-bron is
transport-specifiek.
Prewarming: BLE-getriggerde Aware-startup {#prewarming-ble-triggered-aware-startup}
De grootste voor de gebruiker zichtbare latentie in het Aware-pad is de eerste handshake — als beide kanten Aware nog niet hebben gestart, moet het eerste bericht van de gebruiker wachten op:
- Lokale Aware-sessie-attach (~1 s)
- Lokale publish + subscribe-start (~1 s)
- Aware-startup van de remote peer (~2 s via BLE)
- Wederzijdse ontdekking (~1 s)
- NDP-handshake (~400 ms)
Dat is ~5 seconden voordat de eerste byte wordt verzonden. Om deze
latentie te verbergen, draait PeerTransportPrewarmer bij binnenkomst op
ChatPage en triggert de Aware-startup van de remote peer via BLE:
De dubbele rol van BLE
BLE dient hier twee doelen:
- De huidige Aware-state van de peer lezen (goedkoop, geen
GATT-connect — de
serviceDatabyte0 van de scanrespons vervoert de Aware-vlaggen). - De peer triggeren om Aware te starten als het het ondersteunt
maar momenteel niet draait. Dit gaat via het reguliere
BleTransport.send-pad — eenstartAware-GraphQL-mutation versleuteld met de gedeelde ChaCha20-sleutel, afgeleverd via GATT-RPC naar het/peer_graphql-endpoint van de peer.
Dit is een van de weinige plaatsen waar de transports samenwerken in plaats van alleen maar terug te vallen: BLE wordt gebruikt om de sessie preemptief te upgraden naar het snellere Aware-transport, voordat de gebruiker het überhaupt merkt.
Waarom optimistisch setAwareRunning(true)?
De startAware-mutation retourneert succes zodra de resolver van de
remote peer WifiAwareTransport.start() aanroept — maar de Aware-sessie
is nog niet echt verbonden (onAttached vuurt asynchroon). PlainApp
markeert de peer optimistisch als awareRunning = true, omdat:
- Als het daadwerkelijk startte, zal de volgende
sendAware gebruiken (snel). - Als het niet zo is (bijv. Wi-Fi van de peer staat uit), zal de
buildLinkvan de volgendesendfalen metTransportUnavailableen van nature naar BLE terugvallen. - De kosten van een false positive zijn één ~5 s-timeout, geen
permanente blokkade —
PeerCircuitBreakernoteert de fout maar opent de BLE-leg niet (BLE opent alleen bij zijn eigen fouten).
Waarom throttelen tot 30 s?
PeerTransportPrewarmer.prewarm(peerId) noteert een timestamp per peer
en weigert binnen 30 s opnieuw te draaien. Dit komt omdat de gebruiker
veelvuldig heen en weer navigeert tussen chat-lijst en chat-pagina —
zonder throttling zou elke navigatie een BLE-scan + startAware-mutation
triggern, wat batterij zou verbruiken en de BLE-radio zou spammen. Het
30 s-venster is kort genoeg om een peer die net online is gekomen te
vangen (bijv. gebruiker opende de app op het remote apparaat) maar lang
genoeg om spurieuze her-runs te vermijden.
Foutmodi en de fast-skip-vlag {#failure-modes--the-fast-skip-flag}
Aware heeft meer foutmodi dan enig ander transport. De
isAwareRunning-fast-skip-vlag is de belangrijkste optimalisatie in de
hele module — zonder deze zou elke send 10 s verspillen aan
buildLink-timeouts voordat naar BLE wordt teruggevallen.
De isAwareRunning-vlag is de spil
Zonder deze enkele boolean zou elke Aware-send ofwel:
- Altijd
buildLinkproberen → 10 s-timeout bij elke send naar een peer wiens Aware niet draait. - Altijd Aware overslaan → het nooit gebruiken, zelfs niet wanneer beide kanten het draaien.
De vlag wordt ververst vanuit twee bronnen, in volgorde van autoriteit:
- BLE-scanrespons (goedkoop, geen GATT-connect) — ingesteld door
PeerTransportPrewarmer.refreshAwareFlagFromScan. De peer adverteert zijn Aware-state in de 9-byteserviceData-payload (byte0-bitfield). - GATT DISCOVER-antwoord (autoritatief) — ingesteld door
PairingTransport.scanAndDiscoverwanneer een volledige ontdekking plaatsvindt. Dit overschrijft de scan-hint.
Wanneer onwaar, gooien WifiAwareTransport.send en downloadFile
onmiddellijk TransportUnavailable — geen scan, geen handshake, geen
timeout. De router valt in microseconden door naar BLE.
Referentie van sleutelconstanten {#key-constants-reference}
| Constante | Waarde | Waar | Doel |
|---|---|---|---|
AwareSession.SERVICE_NAME | "plain-peer" | Ontdekking | Servicenaam gepubliceerd & geabonneerd door elk PlainApp-apparaat |
AwareSession.PEER_HANDLE_MAX_AGE_MS | 30 000 | PeerHandle-cache | Verwijder stale handles (publish-sessie van peer kan zijn herstart) |
AwareSession.READY_TIMEOUT_MS | 15 000 | Handshake | Subscriber-wachttijd op ready-bevestiging van publisher |
AwareSession.MSG_HELLO | 0 | Handshake | Subscriber → Publisher-bericht-ID |
AwareSession.MSG_READY | 1 | Handshake | Publisher → Subscriber-bericht-ID |
AwarePeerLink.MAX_BUILD_ATTEMPTS | 1 | Handshake (alleen client) | Eén poging — was 3, nu 1 omdat prewarmer beide kanten primed |
AwarePeerLink.ATTEMPT_TIMEOUT_MS | 5 000 | Handshake | Per-poging-timeout — was 10 s, gehalveerd om fallback te versnellen |
AwarePeerLink.RETRY_DELAY_MS | 500 | Handshake | Vertraging tussen hertry-pogingen (alleen client) |
AwarePeerLink.REQUEST_TIMEOUT_MS | 30 000 | NDP | connectivityManager.requestNetwork-timeout |
AwareLinkPool.IDLE_TIMEOUT_MS | 60 000 | Pool-sweep | Sluit idle links na 60 s inactiviteit |
AwareLinkPool.IDLE_SWEEP_INTERVAL_MS | 10 000 | Pool-sweep | Sweep-interval |
AwareHttpClientFactory.AWARE_HOST | "plain-aware-peer" | DNS | Sentinel-hostnaam opgelost naar peer-IPv6 door aangepaste Dns |
build chat-client | connectTimeout 5 s, requestTimeout 30 s, ChaCha20-interceptor | ||
buildFileDownload | connectTimeout 10 s, readTimeout 120 s, requestTimeout 120 s, geen crypto | ||
PeerTransportPrewarmer.PREWARM_TTL_MS | 30 000 | Prewarm | Throttle per peer |
PeerTransportPrewarmer.BLE_SCAN_TIMEOUT_MS | 15 000 | Prewarm | BLE-scan-timeout voor refreshAwareFlagFromScan |
PeerCircuitBreaker.WINDOW_MS | 30 000 | Circuit-breaker | Open-duur na drempel |
PeerCircuitBreaker.MAX_FAILURES | 2 | Circuit-breaker | Fouten binnen venster om te openen |
TempData.httpsPort | 8443 (standaard) | Server | Poort van publisher geadverteerd via WifiAwareNetworkSpecifier.setPort |
BleServiceData.AWARE_SUPPORTED | 0x01 | BLE-scanrespons | Bit die aangeeft dat peer Wi-Fi Aware ondersteunt |
BleServiceData.AWARE_RUNNING | 0x02 | BLE-scanrespons | Bit die aangeeft dat de Aware-service van peer momenteel draait |
Samenvatting van ontwerpafwegingen {#design-trade-offs-recap}
Verder lezen
- Chatarchitectuur — hoe
WifiAwareTransportpast in deLAN → Aware → BLE-fallback-chain en de bredere chat-verzend/ontvang-pijplijn. - BLE-transport — het last-resort-transport dat overneemt wanneer Aware onbeschikbaar is; ook het kanaal dat door de prewarmer wordt gebruikt om Aware-startup op de remote peer te triggeren.
- Koppelingsproces — hoe de gedeelde
ChaCha20-sleutel die als de Aware-PMK wordt hergebruikt, wordt
opgebouwd, en hoe de BLE-scanrespons-vlaggen
(
AWARE_SUPPORTED/AWARE_RUNNING) worden gevuld.