1010 Tuple ,
1111)
1212import aiohttp
13- import attr
14- import attrs
1513import json
1614import logging
1715import uuid
3735LOG = logging .getLogger (__name__ )
3836
3937
40- @attr .s (auto_attribs = True )
41- class Message :
42- """Provide a nicer interface for messages than just Dictionaries."""
43-
44- type : str
45- body : JSON_OBJ
46- id : Optional [str ] = None
47- typ : Optional [str ] = "application/didcomm-plain+json"
48- frm : Optional [DID ] = None
49- to : Optional [List [DID ]] = None
50- lang : Optional [str ] = None
51- created_time : Optional [int ] = None
52- expires_time : Optional [int ] = None
53- thid : Optional [str ] = None
54- pthid : Optional [str ] = None
55- please_ack : Optional [List [str ]] = None
56- ack : Optional [List [str ]] = None
57-
58- # TODO: better implement/support these fields
59- attachments : Optional [List [Attachment ]] = None
60- # from_prior: Optional[JWT] = None
61-
62- # TODO: Add message validation for spec-defined fields
63-
64- def __attrs_post_init__ (self ):
65- """Ensure that id is set."""
66- # super().__init__(*args, **kwargs)
67- if self .id is None :
68- self .id = str (uuid .uuid4 ())
69-
70- def as_dict (self ):
71- """Return message as a dictionary for serialization."""
72- return attrs .asdict (self , filter = (lambda _ , x : x is not None ))
73-
74- @classmethod
75- def from_json (cls , data : str ):
76- """Create a Message object from a JSON string."""
77- data = json .loads (data )
78- if "from" in data :
79- data ["frm" ] = data ["from" ]
80- del data ["from" ]
81- return cls (** data )
82-
83-
8438class CompatibilityPrefixResolver (PrefixResolver ):
8539 """Provide backwards compatibility with older DID methods.
8640
@@ -225,13 +179,13 @@ async def setup_default(
225179
226180
227181async def send_http_message (
228- dmp : DIDCommMessaging , my_did : DID , message : Message , target : DID
229- ) -> Optional [Message ]:
182+ dmp : DIDCommMessaging , my_did : DID , message : Dict [ str , Any ] , target : DID
183+ ) -> Optional [Dict [ str , Any ] ]:
230184 """Send a message via HTTP."""
231185
232- # Get the message as a dictionary
233- message_wrapper = message
234- message = message_wrapper . as_dict ( )
186+ # Ensure an ID is on the message
187+ if "id" not in message or not message [ "id" ]:
188+ message [ "id" ] = str ( uuid . uuid4 () )
235189
236190 # Encrypt/pack the message to our target
237191 packy = await dmp .pack (
@@ -245,19 +199,28 @@ async def send_http_message(
245199 endpoint = packy .get_endpoint ("http" )
246200
247201 async with aiohttp .ClientSession () as session :
248- LOG .info ("posting message type %s to %s" , message_wrapper . type , endpoint )
202+ LOG .info ("posting message type %s to %s" , message [ " type" ] , endpoint )
249203
250204 async with session .post (endpoint , data = packed ) as resp :
251- LOG .debug ("posted message: %s" , message )
252- LOG .debug ("message ID: %s" , message_wrapper .id )
205+ # Get the message from the response and prepare for decryption
253206 packed = await resp .text ()
254207
208+ # Dump useful information about the message
209+ LOG .debug ("posted message: %s" , message )
210+ LOG .debug ("message ID: %s" , message ["id" ])
211+ LOG .debug ("response code: %s" , resp .status )
212+ LOG .debug ("response message: %s" , packed )
213+
214+ # Raise an exception if the destination did not return success
215+ if resp .status != 200 :
216+ raise Exception ("Destination responded with error: %s" % packed )
217+
255218 # If the HTTP enpoint responded with a message, decode it
256219 if len (packed ) > 0 :
257220 unpacked = await dmp .packaging .unpack (packed )
258221 msg = unpacked [0 ].decode ()
259222 LOG .debug ("Raw message from remote %s" , msg )
260- return Message . from_json (msg )
223+ return json . loads (msg )
261224 return
262225
263226
@@ -270,24 +233,24 @@ async def setup_relay(
270233 """
271234
272235 # Request mediation from the inbound relay
273- message = Message (
274- type = "https://didcomm.org/coordinate-mediation/3.0/mediate-request" ,
275- id = str (uuid .uuid4 ()),
276- body = {},
277- frm = my_did ,
278- to = [relay_did ],
279- )
236+ message = {
237+ " type" : "https://didcomm.org/coordinate-mediation/3.0/mediate-request" ,
238+ "id" : str (uuid .uuid4 ()),
239+ " body" : {},
240+ " frm" : my_did ,
241+ "to" : [relay_did ],
242+ }
280243 message = await send_http_message (dmp , my_did , message , target = relay_did )
281244
282245 # Verify that mediation-access has been granted
283- if message . type == "https://didcomm.org/coordinate-mediation/3.0/mediate-deny" :
246+ if message [ " type" ] == "https://didcomm.org/coordinate-mediation/3.0/mediate-deny" :
284247 return
285- if message . type != "https://didcomm.org/coordinate-mediation/3.0/mediate-grant" :
248+ if message [ " type" ] != "https://didcomm.org/coordinate-mediation/3.0/mediate-grant" :
286249 # We shouldn't run into this case, but it's possible
287- raise Exception ("Unknown response type received: %s" % message . type )
250+ raise Exception ("Unknown response type received: %s" % message [ " type" ] )
288251
289252 # Create a new DID with an updated service endpoint, pointing to our relay
290- relay_did = message . body ["routing_did" ][0 ]
253+ relay_did = message [ " body" ] ["routing_did" ][0 ]
291254 new_did = generate (
292255 [
293256 KeySpec .verification (
@@ -333,27 +296,27 @@ async def setup_relay(
333296
334297 # Send a message to the relay informing it of our new endpoint that people
335298 # should contact us by
336- message = Message (
337- type = "https://didcomm.org/coordinate-mediation/3.0/recipient-update" ,
338- id = str (uuid .uuid4 ()),
339- body = {
299+ message = {
300+ " type" : "https://didcomm.org/coordinate-mediation/3.0/recipient-update" ,
301+ "id" : str (uuid .uuid4 ()),
302+ " body" : {
340303 "updates" : [
341304 {
342305 "recipient_did" : new_did ,
343306 "action" : "add" ,
344307 },
345308 ],
346309 },
347- frm = my_did ,
348- to = [relay_did ],
349- )
310+ " frm" : my_did ,
311+ "to" : [relay_did ],
312+ }
350313 message = await send_http_message (dmp , my_did , message , target = relay_did )
351314
352315 return new_did
353316
354317
355- async def _message_callback (msg : Message ) -> None :
356- if msg . type == "https://didcomm.org/basicmessage/2.0/message" :
318+ async def _message_callback (msg : Dict [ str , Any ] ) -> None :
319+ if msg [ " type" ] == "https://didcomm.org/basicmessage/2.0/message" :
357320 logmsg = msg .body ["content" ].replace ("\n " , " " ).replace ("\r " , "" )
358321 LOG .info ("Got message: %s" , logmsg )
359322
@@ -362,57 +325,56 @@ async def fetch_relayed_messages(
362325 dmp : DIDCommMessaging ,
363326 my_did : DID ,
364327 relay_did : DID ,
365- callback : Callable [[Message ], Awaitable [None ]] = _message_callback ,
366- ) -> List [ Message ] :
328+ callback : Callable [[Dict [ str , Any ] ], Awaitable [None ]] = _message_callback ,
329+ ) -> None :
367330 """Fetch stored messages from the relay."""
368331
369332 # Fetch a count of all stored messages
370- message = Message (
371- type = "https://didcomm.org/messagepickup/3.0/status-request" ,
372- id = str (uuid .uuid4 ()),
373- body = {},
374- frm = my_did ,
375- to = [relay_did ],
376- )
333+ message = {
334+ " type" : "https://didcomm.org/messagepickup/3.0/status-request" ,
335+ "id" : str (uuid .uuid4 ()),
336+ " body" : {},
337+ " frm" : my_did ,
338+ "to" : [relay_did ],
339+ }
377340 message = await send_http_message (dmp , my_did , message , target = relay_did )
378341
379342 # If there's no messages, we can return early
380- if message . body ["message_count" ] == 0 :
343+ if message [ " body" ] ["message_count" ] == 0 :
381344 return []
382345
383346 # Request messages that are stored at the relay, according to the
384347 # message_count returned in the previous call
385- message = Message (
386- type = "https://didcomm.org/messagepickup/3.0/delivery-request" ,
387- id = str (uuid .uuid4 ()),
388- body = {
389- "limit" : message . body ["message_count" ],
348+ message = {
349+ " type" : "https://didcomm.org/messagepickup/3.0/delivery-request" ,
350+ "id" : str (uuid .uuid4 ()),
351+ " body" : {
352+ "limit" : message [ " body" ] ["message_count" ],
390353 },
391- frm = my_did ,
392- to = [relay_did ],
393- )
354+ " frm" : my_did ,
355+ "to" : [relay_did ],
356+ }
394357 message = await send_http_message (dmp , my_did , message , target = relay_did )
395358
396359 # Handle each stored message is order we receive it
397- for attach in message . attachments :
360+ for attach in message [ " attachments" ] :
398361 LOG .info ("Received message %s" , attach ["id" ][:- 58 ])
399362
400363 # Decrypt/Unpack the encrypted message attachment
401364 unpacked = await dmp .unpack (json .dumps (attach ["data" ]["json" ]))
402365 msg = unpacked .message
403- msg = Message .from_json (msg )
404366
405367 # Call callback if it exists, passing the message in
406368 if callback :
407369 await callback (msg )
408370
409- message = Message (
410- type = "https://didcomm.org/messagepickup/3.0/messages-received" ,
411- id = str (uuid .uuid4 ()),
412- body = {
413- "message_id_list" : [msg . id for msg in message . attachments ],
371+ message = {
372+ " type" : "https://didcomm.org/messagepickup/3.0/messages-received" ,
373+ "id" : str (uuid .uuid4 ()),
374+ " body" : {
375+ "message_id_list" : [msg [ "id" ] for msg in message [ " attachments" ] ],
414376 },
415- frm = my_did ,
416- to = [relay_did ],
417- )
377+ " frm" : my_did ,
378+ "to" : [relay_did ],
379+ }
418380 await send_http_message (dmp , my_did , message , target = relay_did )
0 commit comments