Skip to content

Commit 5161af4

Browse files
TheTechmagedbluhm
authored andcommitted
chore: Add commands & clean websock code
Signed-off-by: Colton Wolkins (Indicio work address) <[email protected]>
1 parent c9df710 commit 5161af4

File tree

1 file changed

+40
-10
lines changed

1 file changed

+40
-10
lines changed

didcomm_messaging/quickstart.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,16 +357,17 @@ async def fetch_relayed_messages(
357357
# soon as they arrive instead of waiting to be picked up with the pickup
358358
# protocol.
359359

360-
# TODO add comments to the below code segments and tidy it up
361-
360+
# Because the quickstart can be used without using websockets or connecting to
361+
# an inbound relay/mediator. If we don't have the necessary libraries, we can
362+
# just raise a warning about the lack of support.
362363
try:
363364
import websockets
364365
import asyncio
365366
except ImportError:
366367
import warnings
367368

368369
warnings.warn(
369-
"Missing websockets or asyncio import, live-delivery will be unavailable",
370+
"Missing websockets or asyncio import, live-delivery support will be unavailable",
370371
ImportWarning,
371372
)
372373

@@ -379,25 +380,44 @@ async def handle_websocket(
379380
callback: Callable[[Dict[str, Any]], Awaitable[None]] = _message_callback,
380381
):
381382
"""Loop over messages received and process them."""
383+
384+
# Using async with on the websocket allows us to wait for then loop over
385+
# new messages that come in over the websocket.
382386
async with mediator_websocket as websocket:
387+
# Send our live-delivery request to the inbound relay.
383388
await websocket.send(live_delivery_message)
384-
LOG.debug("Connected to WebSocket and requested Live Delivery!")
389+
LOG.debug("Connected to WebSocket and requested Live Delivery.")
390+
391+
# Loop over all incoming messages
385392
while True:
386393
message = await websocket.recv()
387394
LOG.debug("Received message over websocket")
388395

389396
try:
397+
# Unpack/Decrypt the message, decode it, and load the JSON into
398+
# a native python object.
390399
unpacked_message, metadata = await dmp.packaging.unpack(message)
391400
msg = unpacked_message.decode()
392401
msg = json.loads(msg)
393402
LOG.debug("Received websocket message %s", msg["type"])
403+
404+
# If the message is not from the relay, process it via the callback
394405
if msg["from"] != relay_did:
395406
await callback(msg)
396407

408+
# NOTE: While out of scope for this example, when implementing
409+
# your own handler, it's advisable to handle messages that come
410+
# from the relay. For example: the relay will respond to the
411+
# live-delivery call with a pickup protocol status message. The
412+
# status message may contain a message count that is greater
413+
# than zero. If there are messages that are waiting, it is
414+
# advisable to request the messages and process them.
415+
397416
except Exception as err:
398417
LOG.error("Error encountered while decrypting websocket message")
399418
LOG.exception(err)
400419

420+
# Clean up the websocket
401421
await websocket.close()
402422

403423

@@ -410,6 +430,7 @@ async def activate_websocket(
410430
) -> Union[Awaitable[None], "asyncio.Task"]:
411431
"""Connect to a websocket and request message forwarding."""
412432

433+
# Construct a message to request live-delivery and pack it
413434
message = {
414435
"type": "https://didcomm.org/messagepickup/3.0/live-delivery-change",
415436
"id": str(uuid.uuid4()),
@@ -424,10 +445,14 @@ async def activate_websocket(
424445
to=relay_did,
425446
frm=my_did,
426447
)
448+
449+
# Get the websocket endpoint from the packed message. This will pull out
450+
# the endpoint that is closest to us, the sender.
427451
endpoint = packed.get_endpoint("ws")
428-
LOG.info("Relay Websocket Address: %s", endpoint)
452+
LOG.debug("Relay Websocket Address: %s", endpoint)
453+
429454
if endpoint:
430-
LOG.info("Found Relay websocket, connecting")
455+
# Connect to the websocket and prepare our handler function
431456
mediator_websocket = websockets.connect(uri=endpoint)
432457
websocket_handler = handle_websocket(
433458
dmp,
@@ -436,6 +461,9 @@ async def activate_websocket(
436461
packed.message,
437462
callback,
438463
)
464+
465+
# Create an asyncio task upon request to run in another async "thread",
466+
# otherwise we'll just return the function that runs in the thread.
439467
if create_task:
440468
return asyncio.create_task(websocket_handler)
441469
else:
@@ -450,17 +478,19 @@ async def websocket_loop(
450478
) -> None:
451479
"""Run the websocket handler in a task and reconnect on failure."""
452480

481+
# Helper method to create the async task
453482
async def create_task():
454483
return await activate_websocket(dmp, my_did, relay_did, callback, True)
455484

485+
# Create the initial task
456486
mediator_websocket_proc = await create_task()
457487

488+
# Check to make sure the thread is still running every 5 seconds (to give
489+
# the OS some breathing room). Should the thread "crash" or exit for any
490+
# reason, log any exceptions and attempt to restart it.
458491
while True:
459492
await asyncio.sleep(5)
460493
if mediator_websocket_proc.done():
461494
LOG.exception(mediator_websocket_proc.exception())
462-
try:
463-
LOG.error("Websocket died, re-establishing connection!")
464-
except Exception:
465-
pass
495+
LOG.error("Websocket died, re-establishing connection!")
466496
mediator_websocket_proc = await create_task()

0 commit comments

Comments
 (0)