11import type { Logger } from '../logger'
22import type { ConnectionRecord } from '../modules/connections'
33import type { InboundTransport } from '../transport'
4- import type { UnpackedMessageContext , UnpackedMessage , WireMessage } from '../types'
4+ import type { DecryptedMessageContext , PlaintextMessage , EncryptedMessage } from '../types'
55import type { AgentMessage } from './AgentMessage'
66import type { TransportSession } from './TransportService'
77
@@ -59,21 +59,29 @@ export class MessageReceiver {
5959 }
6060
6161 /**
62- * Receive and handle an inbound DIDComm message. It will unpack the message, transform it
62+ * Receive and handle an inbound DIDComm message. It will decrypt the message, transform it
6363 * to it's corresponding message class and finally dispatch it to the dispatcher.
6464 *
65- * @param inboundPackedMessage the message to receive and handle
65+ * @param inboundMessage the message to receive and handle
6666 */
67- public async receiveMessage ( inboundPackedMessage : unknown , session ?: TransportSession ) {
68- if ( typeof inboundPackedMessage !== 'object' || inboundPackedMessage == null ) {
69- throw new AriesFrameworkError ( 'Invalid message received. Message should be object' )
67+ public async receiveMessage ( inboundMessage : unknown , session ?: TransportSession ) {
68+ this . logger . debug ( `Agent ${ this . config . label } received message` )
69+
70+ if ( this . isPlaintextMessage ( inboundMessage ) ) {
71+ await this . receivePlaintextMessage ( inboundMessage )
72+ } else {
73+ await this . receiveEncryptedMessage ( inboundMessage as EncryptedMessage , session )
7074 }
75+ }
7176
72- this . logger . debug ( `Agent ${ this . config . label } received message` )
77+ private async receivePlaintextMessage ( plaintextMessage : PlaintextMessage ) {
78+ const message = await this . transformAndValidate ( plaintextMessage )
79+ const messageContext = new InboundMessageContext ( message , { } )
80+ await this . dispatcher . dispatch ( messageContext )
81+ }
7382
74- const unpackedMessage = await this . unpackMessage ( inboundPackedMessage as WireMessage )
75- const senderKey = unpackedMessage . senderVerkey
76- const recipientKey = unpackedMessage . recipientVerkey
83+ private async receiveEncryptedMessage ( encryptedMessage : EncryptedMessage , session ?: TransportSession ) {
84+ const { plaintextMessage, senderKey, recipientKey } = await this . decryptMessage ( encryptedMessage )
7785
7886 let connection : ConnectionRecord | null = null
7987
@@ -90,27 +98,11 @@ export class MessageReceiver {
9098 }
9199
92100 this . logger . info (
93- `Received message with type '${ unpackedMessage . message [ '@type' ] } ' from connection ${ connection ?. id } (${ connection ?. theirLabel } )` ,
94- unpackedMessage . message
101+ `Received message with type '${ plaintextMessage [ '@type' ] } ' from connection ${ connection ?. id } (${ connection ?. theirLabel } )` ,
102+ plaintextMessage
95103 )
96104
97- let message : AgentMessage | null = null
98- try {
99- message = await this . transformMessage ( unpackedMessage )
100- await this . validateMessage ( message )
101- } catch ( error ) {
102- if ( connection ) await this . sendProblemReportMessage ( error . message , connection , unpackedMessage )
103- throw error
104- }
105-
106- const messageContext = new InboundMessageContext ( message , {
107- // Only make the connection available in message context if the connection is ready
108- // To prevent unwanted usage of unready connections. Connections can still be retrieved from
109- // Storage if the specific protocol allows an unready connection to be used.
110- connection : connection ?. isReady ? connection : undefined ,
111- senderVerkey : senderKey ,
112- recipientVerkey : recipientKey ,
113- } )
105+ const message = await this . transformAndValidate ( plaintextMessage , connection )
114106
115107 // We want to save a session if there is a chance of returning outbound message via inbound transport.
116108 // That can happen when inbound message has `return_route` set to `all` or `thread`.
@@ -131,53 +123,68 @@ export class MessageReceiver {
131123 this . transportService . saveSession ( session )
132124 }
133125
126+ const messageContext = new InboundMessageContext ( message , {
127+ // Only make the connection available in message context if the connection is ready
128+ // To prevent unwanted usage of unready connections. Connections can still be retrieved from
129+ // Storage if the specific protocol allows an unready connection to be used.
130+ connection : connection ?. isReady ? connection : undefined ,
131+ senderVerkey : senderKey ,
132+ recipientVerkey : recipientKey ,
133+ } )
134134 await this . dispatcher . dispatch ( messageContext )
135135 }
136136
137137 /**
138- * Unpack a message using the envelope service.
139- * If message is not packed, it will be returned as is, but in the unpacked message structure
138+ * Decrypt a message using the envelope service.
140139 *
141- * @param packedMessage the received, probably packed, message to unpack
140+ * @param message the received inbound message to decrypt
142141 */
143- private async unpackMessage ( packedMessage : WireMessage ) : Promise < UnpackedMessageContext > {
144- // If the inbound message has no @type field we assume
145- // the message is packed and must be unpacked first
146- if ( ! this . isUnpackedMessage ( packedMessage ) ) {
147- try {
148- return await this . envelopeService . unpackMessage ( packedMessage )
149- } catch ( error ) {
150- this . logger . error ( 'error while unpacking message' , {
151- error,
152- packedMessage,
153- errorMessage : error instanceof Error ? error . message : error ,
154- } )
155- throw error
156- }
142+ private async decryptMessage ( message : EncryptedMessage ) : Promise < DecryptedMessageContext > {
143+ try {
144+ return await this . envelopeService . unpackMessage ( message )
145+ } catch ( error ) {
146+ this . logger . error ( 'Error while decrypting message' , {
147+ error,
148+ encryptedMessage : message ,
149+ errorMessage : error instanceof Error ? error . message : error ,
150+ } )
151+ throw error
157152 }
153+ }
158154
159- // If the message does have an @type field we assume
160- // the message is already unpacked an use it directly
161- else {
162- const unpackedMessage : UnpackedMessageContext = { message : packedMessage }
163- return unpackedMessage
155+ private isPlaintextMessage ( message : unknown ) : message is PlaintextMessage {
156+ if ( typeof message !== 'object' || message == null ) {
157+ throw new AriesFrameworkError ( 'Invalid message received. Message should be object' )
164158 }
159+ // If the message does have an @type field we assume the message is in plaintext and it is not encrypted.
160+ return '@type' in message
165161 }
166162
167- private isUnpackedMessage ( message : Record < string , unknown > ) : message is UnpackedMessage {
168- return '@type' in message
163+ private async transformAndValidate (
164+ plaintextMessage : PlaintextMessage ,
165+ connection ?: ConnectionRecord | null
166+ ) : Promise < AgentMessage > {
167+ let message : AgentMessage
168+ try {
169+ message = await this . transformMessage ( plaintextMessage )
170+ await this . validateMessage ( message )
171+ } catch ( error ) {
172+ if ( connection ) await this . sendProblemReportMessage ( error . message , connection , plaintextMessage )
173+ throw error
174+ }
175+ return message
169176 }
170177
171178 /**
172- * Transform an unpacked DIDComm message into it's corresponding message class. Will look at all message types in the registered handlers.
179+ * Transform an plaintext DIDComm message into it's corresponding message class. Will look at all message types in the registered handlers.
173180 *
174- * @param unpackedMessage the unpacked message for which to transform the message in to a class instance
181+ * @param message the plaintext message for which to transform the message in to a class instance
175182 */
176- private async transformMessage ( unpackedMessage : UnpackedMessageContext ) : Promise < AgentMessage > {
183+ private async transformMessage ( message : PlaintextMessage ) : Promise < AgentMessage > {
177184 // replace did:sov:BzCbsNYhMrjHiqZDTUASHg;spec prefix for message type with https://didcomm.org
178- replaceLegacyDidSovPrefixOnMessage ( unpackedMessage . message )
185+ replaceLegacyDidSovPrefixOnMessage ( message )
179186
180- const messageType = unpackedMessage . message [ '@type' ]
187+ const messageType = message [ '@type' ]
181188 const MessageClass = this . dispatcher . getMessageClassForType ( messageType )
182189
183190 if ( ! MessageClass ) {
@@ -187,9 +194,7 @@ export class MessageReceiver {
187194 }
188195
189196 // Cast the plain JSON object to specific instance of Message extended from AgentMessage
190- const message = JsonTransformer . fromJSON ( unpackedMessage . message , MessageClass )
191-
192- return message
197+ return JsonTransformer . fromJSON ( message , MessageClass )
193198 }
194199
195200 /**
@@ -214,14 +219,14 @@ export class MessageReceiver {
214219 * Send the problem report message (https://didcomm.org/notification/1.0/problem-report) to the recipient.
215220 * @param message error message to send
216221 * @param connection connection to send the message to
217- * @param unpackedMessage received unpackedMessage
222+ * @param plaintextMessage received inbound message
218223 */
219224 private async sendProblemReportMessage (
220225 message : string ,
221226 connection : ConnectionRecord ,
222- unpackedMessage : UnpackedMessageContext
227+ plaintextMessage : PlaintextMessage
223228 ) {
224- if ( unpackedMessage . message [ '@type' ] === CommonMessageType . ProblemReport ) {
229+ if ( plaintextMessage [ '@type' ] === CommonMessageType . ProblemReport ) {
225230 throw new AriesFrameworkError ( message )
226231 }
227232 const problemReportMessage = new ProblemReportMessage ( {
@@ -231,7 +236,7 @@ export class MessageReceiver {
231236 } ,
232237 } )
233238 problemReportMessage . setThread ( {
234- threadId : unpackedMessage . message [ '@id' ] ,
239+ threadId : plaintextMessage [ '@id' ] ,
235240 } )
236241 const outboundMessage = createOutboundMessage ( connection , problemReportMessage )
237242 if ( outboundMessage ) {
0 commit comments