3.6 KiB
Native mobile voice calls are working with the Hub — one small Hub tweak away from complete
We've built a native Android Qortal client with Reticulum voice calling that interoperates with the desktop Hub, and we're genuinely at the finish line. This is the breakthrough: a phone and the Hub now hold a real RNS voice call. We just need one small adjustment on the Hub side to make it work in both call directions.
The breakthrough
Hub → mobile calls work fully today — clean two‑way audio, low latency. No Hub changes were needed for this. The phone:
- captures mic audio, encodes Opus, and
QGAU‑wraps frames byte‑for‑byte like the desktop peer; - performs the
QGCCTL1+ signedGC_JOINlink‑auth handshake over the RNS audio link, and the Hub verifies it and deliversGC_KEYover the link — exactly as designed; - carries audio both ways over the verified Reticulum link.
In other words, the entire wire protocol — audio framing, Ed25519 link‑auth signatures, key delivery, RNS link transport — is already correct and the Hub already accepts it. That's the hard part, and it's done.
The one remaining gap
Mobile‑initiated calls (phone → Hub) get stuck on the Hub showing "connecting…" and drop after a few seconds, even though the phone is already "in call", sending audio, and sending the same signed link‑auth the Hub happily accepts in the other direction.
We traced it through electron/src/group-call.ts, and it is not a protocol or
signature problem — the join verifies. It's a small ordering precondition:
- The audio‑link owner is chosen by address ordering
(
isLocalAddressReticulumAudioLinkOwner), not by who placed the call, so the Hub opens the link in both directions. - Inbound link audio is dropped unless the link is marked verified
(
audio-unverified-address). - A link is only marked verified in
applyVerifiedReticulumLinkAuthJoinif the sender is already present inroom.participantsat that instant.
When the phone initiates, its verified link‑auth GC_JOIN arrives before the Hub
has registered the caller in room.participants, so the Hub closes the link with
link-auth-no-participant / drops audio as audio-unverified-address, and never leaves
"connecting". In the Hub‑initiated direction the participant state is already in place,
so the identical handshake verifies and the call connects. That single ordering
difference is the whole gap.
The small Hub change we're asking for
In applyVerifiedReticulumLinkAuthJoin, when the signed GC_JOIN verifies and the
sender is a valid Qortal member of the call, admit the participant from the verified
join instead of bailing with link-auth-no-participant.
The verified join is itself authenticated proof of membership (Ed25519 over
buildGcJoinSignedFields, already checked), so this removes the race without
weakening security at all — it just lets a correctly‑signed mobile caller be admitted
regardless of which side's participant bookkeeping landed first.
That's it. One precondition relaxed for the already‑verified path. With that in place, mobile→Hub (and mobile↔mobile) calls verify deterministically, exactly like the Hub→mobile calls that already work today.
What we are NOT asking for
- No change to the wire format, audio framing, signing, key delivery, or the link‑owner rule.
- Nothing changes for Hub‑initiated calls — they keep working as‑is.
Happy to jump on a call or share a build to demo the working direction live. We think this is a great step toward Qortal voice on phones, and we're one small Hub tweak from calls working every direction.