diff --git a/public/call.html b/public/call.html index b72dd5a..0c9f778 100644 --- a/public/call.html +++ b/public/call.html @@ -21,7 +21,7 @@
-
+
@@ -38,7 +38,25 @@
Call Hash
-
{{ callHash }}
+
{{ audioCall?.hash || "Unknown" }}
+
+ +
+
Remote Identity Hash
+
{{ audioCall?.remote_identity_hash || "Unknown" }}
+
+ +
+
Remote Destination Hash
+
{{ audioCall?.remote_destination_hash || "Unknown" }}
+
+ +
+
Path
+
+ {{ audioCall.path.hops }} {{ audioCall.path.hops === 1 ? 'hop' : 'hops' }} away via {{ audioCall.path.next_hop_interface }} + Unknown +
@@ -118,11 +136,12 @@
Active Calls
-
+
Call Hash: {{ audioCall.hash }}
-
Initiator Identity: {{ audioCall.initiator_identity_hash || "Unknown" }}
+
Identity: {{ audioCall.remote_identity_hash || "Unknown" }}
+
Destination: {{ audioCall.remote_destination_hash || "Unknown" }}
Direction: Outbound Direction: Inbound @@ -159,11 +178,12 @@
Call History
-
+
Call Hash: {{ audioCall.hash }}
-
Initiator Identity: {{ audioCall.initiator_identity_hash || "Unknown" }}
+
Identity: {{ audioCall.remote_identity_hash || "Unknown" }}
+
Destination: {{ audioCall.remote_destination_hash || "Unknown" }}
Direction: Outbound Direction: Inbound @@ -201,6 +221,7 @@ data() { return { + audioCall: null, audioCalls: [], myAudioCallAddressHash: null, @@ -313,6 +334,8 @@ // we are now connected this.isWebsocketConnected = true; + await this.updateCall(callHash); + // send mic audio over call await this.startRecordingMicrophone((encoded) => { @@ -543,6 +566,24 @@ // do nothing on error } }, + async updateCall(callHash) { + + // clear previous call + this.audioCall = null; + + try { + + // get path to destination + const response = await window.axios.get(`/api/v1/calls/${callHash}`); + + // update ui + this.audioCall = response.data.audio_call; + + } catch(e) { + console.log(e); + } + + }, }, computed: { activeAudioCalls: function() { diff --git a/src/audio_call_manager.py b/src/audio_call_manager.py index f7e5f88..a733c56 100644 --- a/src/audio_call_manager.py +++ b/src/audio_call_manager.py @@ -56,8 +56,8 @@ class AudioCall: # send codec2 audio received from call receiver to call initiator over reticulum link RNS.Packet(self.link, data).send() - # gets the identity of the caller, or returns None if they did not identify - def initiator_identity(self): + # gets the identity of the other person, or returns None if they did not identify + def get_remote_identity(self): return self.link.get_remote_identity() # determine if this call is still active diff --git a/web.py b/web.py index 7f3a2eb..228f28e 100644 --- a/web.py +++ b/web.py @@ -254,24 +254,33 @@ class ReticulumWebChat: # get audio calls audio_calls = [] for audio_call in self.audio_call_manager.audio_calls: - - # get initiator identity hash - initiator_identity_hash = None - initiator_identity = audio_call.initiator_identity() - if initiator_identity is not None: - initiator_identity_hash = initiator_identity.hash.hex() - - audio_calls.append({ - "hash": audio_call.link.hash.hex(), - "initiator_identity_hash": initiator_identity_hash, - "is_active": audio_call.is_active(), - "is_outbound": audio_call.is_outbound, - }) + audio_calls.append(self.convert_audio_call_to_dict(audio_call)) return web.json_response({ "audio_calls": audio_calls, }) + # get calls + @routes.get("/api/v1/calls/{audio_call_link_hash}") + async def index(request): + + # get path params + audio_call_link_hash = request.match_info.get("audio_call_link_hash", "") + + # convert hash to bytes + audio_call_link_hash = bytes.fromhex(audio_call_link_hash) + + # find audio call + audio_call = self.audio_call_manager.find_audio_call_by_link_hash(audio_call_link_hash) + if audio_call is None: + return web.json_response({ + "message": "audio call not found", + }, status=404) + + return web.json_response({ + "audio_call": self.convert_audio_call_to_dict(audio_call), + }) + # initiate a call to the provided destination @routes.get("/api/v1/calls/initiate/{destination_hash}") async def index(request): @@ -782,6 +791,48 @@ class ReticulumWebChat: "audio_call_address_hash": self.audio_call_manager.audio_call_receiver.destination.hexhash, } + # convert audio call to dict + def convert_audio_call_to_dict(self, audio_call: AudioCall): + + # get remote identity hash + remote_identity_hash = None + remote_identity = audio_call.get_remote_identity() + if remote_identity is not None: + remote_identity_hash = remote_identity.hash.hex() + + # get remote destination hash + # we need to know the remote identity to determine their destination hash + remote_destination_hash = None + if remote_identity is not None: + remote_destination_hash = RNS.Destination.hash(remote_identity, "call", "audio") + + # determine path to remote destination + path = None + if remote_destination_hash is not None: + + # determine next hop and hop count + hops = RNS.Transport.hops_to(remote_destination_hash) + next_hop_bytes = self.reticulum.get_next_hop(remote_destination_hash) + + # ensure next hop provided + if next_hop_bytes is not None: + next_hop = next_hop_bytes.hex() + next_hop_interface = self.reticulum.get_next_hop_if_name(remote_destination_hash) + path = { + "hops": hops, + "next_hop": next_hop, + "next_hop_interface": next_hop_interface, + } + + return { + "hash": audio_call.link.hash.hex(), + "remote_destination_hash": remote_destination_hash.hex(), + "remote_identity_hash": remote_identity_hash, + "is_active": audio_call.is_active(), + "is_outbound": audio_call.is_outbound, + "path": path, + } + # convert app data to string, or return none unable to do so def convert_app_data_to_string(self, app_data):