Line data Source code
1 : /**
2 : * @file
3 : * Implementation for the TransferSession class.
4 : * // TODO: Support Asynchronous mode. Currently, only Synchronous mode is supported.
5 : */
6 :
7 : #include <protocols/bdx/BdxTransferSession.h>
8 :
9 : #include <lib/support/BufferReader.h>
10 : #include <lib/support/CodeUtils.h>
11 : #include <lib/support/TypeTraits.h>
12 : #include <lib/support/logging/CHIPLogging.h>
13 : #include <protocols/Protocols.h>
14 : #include <protocols/bdx/BdxMessages.h>
15 : #include <protocols/secure_channel/Constants.h>
16 : #include <protocols/secure_channel/StatusReport.h>
17 : #include <system/SystemPacketBuffer.h>
18 : #include <transport/SessionManager.h>
19 :
20 : #include <type_traits>
21 :
22 : namespace {
23 : constexpr uint8_t kBdxVersion = 0; ///< The version of this implementation of the BDX spec
24 :
25 : /**
26 : * @brief
27 : * Allocate a new PacketBuffer and write data from a BDX message struct.
28 : */
29 42 : CHIP_ERROR WriteToPacketBuffer(const ::chip::bdx::BdxMessage & msgStruct, ::chip::System::PacketBufferHandle & msgBuf)
30 : {
31 42 : size_t msgDataSize = msgStruct.MessageSize();
32 42 : ::chip::Encoding::LittleEndian::PacketBufferWriter bbuf(chip::MessagePacketBuffer::New(msgDataSize), msgDataSize);
33 42 : if (bbuf.IsNull())
34 : {
35 0 : return CHIP_ERROR_NO_MEMORY;
36 : }
37 42 : msgStruct.WriteToBuffer(bbuf);
38 42 : msgBuf = bbuf.Finalize();
39 42 : if (msgBuf.IsNull())
40 : {
41 0 : return CHIP_ERROR_NO_MEMORY;
42 : }
43 42 : return CHIP_NO_ERROR;
44 42 : }
45 :
46 : template <typename MessageType>
47 44 : void PrepareOutgoingMessageEvent(MessageType messageType, chip::bdx::TransferSession::OutputEventType & pendingOutput,
48 : chip::bdx::TransferSession::MessageTypeData & outputMsgType)
49 : {
50 : static_assert(std::is_same<std::underlying_type_t<decltype(messageType)>, uint8_t>::value, "Cast is not safe");
51 :
52 44 : pendingOutput = chip::bdx::TransferSession::OutputEventType::kMsgToSend;
53 44 : outputMsgType.ProtocolId = chip::Protocols::MessageTypeTraits<MessageType>::ProtocolId();
54 44 : outputMsgType.MessageType = static_cast<uint8_t>(messageType);
55 44 : }
56 :
57 : } // anonymous namespace
58 :
59 : namespace chip {
60 : namespace bdx {
61 :
62 11 : TransferSession::TransferSession()
63 : {
64 11 : mSuppportedXferOpts.ClearAll();
65 11 : }
66 :
67 188 : void TransferSession::PollOutput(OutputEvent & event, System::Clock::Timestamp curTime)
68 : {
69 188 : event = OutputEvent(OutputEventType::kNone);
70 :
71 188 : if (mShouldInitTimeoutStart)
72 : {
73 11 : mTimeoutStartTime = curTime;
74 11 : mShouldInitTimeoutStart = false;
75 : }
76 :
77 188 : if (mAwaitingResponse && ((curTime - mTimeoutStartTime) >= mTimeout))
78 : {
79 1 : event = OutputEvent(OutputEventType::kTransferTimeout);
80 1 : mState = TransferState::kErrorState;
81 1 : mAwaitingResponse = false;
82 1 : return;
83 : }
84 :
85 187 : switch (mPendingOutput)
86 : {
87 100 : case OutputEventType::kNone:
88 100 : event = OutputEvent(OutputEventType::kNone);
89 100 : break;
90 0 : case OutputEventType::kInternalError:
91 0 : event = OutputEvent::StatusReportEvent(OutputEventType::kInternalError, mStatusReportData);
92 0 : break;
93 2 : case OutputEventType::kStatusReceived:
94 2 : event = OutputEvent::StatusReportEvent(OutputEventType::kStatusReceived, mStatusReportData);
95 2 : break;
96 44 : case OutputEventType::kMsgToSend:
97 44 : event = OutputEvent::MsgToSendEvent(mMsgTypeData, std::move(mPendingMsgHandle));
98 44 : mTimeoutStartTime = curTime;
99 44 : break;
100 5 : case OutputEventType::kInitReceived:
101 5 : event = OutputEvent::TransferInitEvent(mTransferRequestData, std::move(mPendingMsgHandle));
102 5 : break;
103 3 : case OutputEventType::kAcceptReceived:
104 3 : event = OutputEvent::TransferAcceptEvent(mTransferAcceptData, std::move(mPendingMsgHandle));
105 3 : break;
106 12 : case OutputEventType::kQueryReceived:
107 12 : event = OutputEvent(OutputEventType::kQueryReceived);
108 12 : break;
109 0 : case OutputEventType::kQueryWithSkipReceived:
110 0 : event = OutputEvent::QueryWithSkipEvent(mBytesToSkip);
111 0 : break;
112 15 : case OutputEventType::kBlockReceived:
113 15 : event = OutputEvent::BlockDataEvent(mBlockEventData, std::move(mPendingMsgHandle));
114 15 : break;
115 4 : case OutputEventType::kAckReceived:
116 4 : event = OutputEvent(OutputEventType::kAckReceived);
117 4 : break;
118 2 : case OutputEventType::kAckEOFReceived:
119 2 : event = OutputEvent(OutputEventType::kAckEOFReceived);
120 2 : break;
121 0 : default:
122 0 : event = OutputEvent(OutputEventType::kNone);
123 0 : break;
124 : }
125 :
126 : // If there's no other pending output but an error occurred or was received, then continue to output the error.
127 : // This ensures that when the TransferSession encounters an error and needs to send a StatusReport, both a kMsgToSend and a
128 : // kInternalError output event will be emitted.
129 187 : if (event.EventType == OutputEventType::kNone && mState == TransferState::kErrorState)
130 : {
131 11 : event = OutputEvent::StatusReportEvent(OutputEventType::kInternalError, mStatusReportData);
132 : }
133 :
134 187 : mPendingOutput = OutputEventType::kNone;
135 : }
136 :
137 0 : void TransferSession::GetNextAction(OutputEvent & event)
138 : {
139 0 : PollOutput(event, System::SystemClock().GetMonotonicTimestamp());
140 0 : }
141 :
142 6 : CHIP_ERROR TransferSession::StartTransfer(TransferRole role, const TransferInitData & initData, System::Clock::Timeout timeout)
143 : {
144 6 : VerifyOrReturnError(mState == TransferState::kUnitialized, CHIP_ERROR_INCORRECT_STATE);
145 :
146 6 : mRole = role;
147 6 : mTimeout = timeout;
148 :
149 : // Set transfer parameters. They may be overridden later by an Accept message
150 6 : mSuppportedXferOpts = initData.TransferCtlFlags;
151 6 : mMaxSupportedBlockSize = initData.MaxBlockSize;
152 6 : mStartOffset = initData.StartOffset;
153 6 : mTransferLength = initData.Length;
154 :
155 : // Prepare TransferInit message
156 6 : TransferInit initMsg;
157 6 : initMsg.TransferCtlOptions = initData.TransferCtlFlags;
158 6 : initMsg.Version = kBdxVersion;
159 6 : initMsg.MaxBlockSize = mMaxSupportedBlockSize;
160 6 : initMsg.StartOffset = mStartOffset;
161 6 : initMsg.MaxLength = mTransferLength;
162 6 : initMsg.FileDesignator = initData.FileDesignator;
163 6 : initMsg.FileDesLength = initData.FileDesLength;
164 6 : initMsg.Metadata = initData.Metadata;
165 6 : initMsg.MetadataLength = initData.MetadataLength;
166 :
167 6 : ReturnErrorOnFailure(WriteToPacketBuffer(initMsg, mPendingMsgHandle));
168 :
169 6 : const MessageType msgType = (mRole == TransferRole::kSender) ? MessageType::SendInit : MessageType::ReceiveInit;
170 :
171 : #if CHIP_AUTOMATION_LOGGING
172 6 : ChipLogAutomation("Sending BDX Message");
173 6 : initMsg.LogMessage(msgType);
174 : #endif // CHIP_AUTOMATION_LOGGING
175 :
176 6 : mState = TransferState::kAwaitingAccept;
177 6 : mAwaitingResponse = true;
178 :
179 6 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
180 :
181 6 : return CHIP_NO_ERROR;
182 6 : }
183 :
184 5 : CHIP_ERROR TransferSession::WaitForTransfer(TransferRole role, BitFlags<TransferControlFlags> xferControlOpts,
185 : uint16_t maxBlockSize, System::Clock::Timeout timeout)
186 : {
187 5 : VerifyOrReturnError(mState == TransferState::kUnitialized, CHIP_ERROR_INCORRECT_STATE);
188 :
189 : // Used to determine compatibility with any future TransferInit parameters
190 5 : mRole = role;
191 5 : mTimeout = timeout;
192 5 : mSuppportedXferOpts = xferControlOpts;
193 5 : mMaxSupportedBlockSize = maxBlockSize;
194 :
195 5 : mState = TransferState::kAwaitingInitMsg;
196 :
197 5 : return CHIP_NO_ERROR;
198 : }
199 :
200 5 : CHIP_ERROR TransferSession::AcceptTransfer(const TransferAcceptData & acceptData)
201 : {
202 : MessageType msgType;
203 :
204 5 : const BitFlags<TransferControlFlags> proposedControlOpts(mTransferRequestData.TransferCtlFlags);
205 :
206 5 : VerifyOrReturnError(mState == TransferState::kNegotiateTransferParams, CHIP_ERROR_INCORRECT_STATE);
207 5 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
208 :
209 : // Don't allow a Control method that wasn't supported by the initiator
210 : // MaxBlockSize can't be larger than the proposed value
211 5 : VerifyOrReturnError(proposedControlOpts.Has(acceptData.ControlMode), CHIP_ERROR_INVALID_ARGUMENT);
212 4 : VerifyOrReturnError(acceptData.MaxBlockSize <= mTransferRequestData.MaxBlockSize, CHIP_ERROR_INVALID_ARGUMENT);
213 :
214 3 : mTransferMaxBlockSize = acceptData.MaxBlockSize;
215 :
216 3 : if (mRole == TransferRole::kSender)
217 : {
218 2 : mStartOffset = acceptData.StartOffset;
219 2 : mTransferLength = acceptData.Length;
220 :
221 2 : ReceiveAccept acceptMsg;
222 2 : acceptMsg.TransferCtlFlags.Set(acceptData.ControlMode);
223 2 : acceptMsg.Version = mTransferVersion;
224 2 : acceptMsg.MaxBlockSize = acceptData.MaxBlockSize;
225 2 : acceptMsg.StartOffset = acceptData.StartOffset;
226 2 : acceptMsg.Length = acceptData.Length;
227 2 : acceptMsg.Metadata = acceptData.Metadata;
228 2 : acceptMsg.MetadataLength = acceptData.MetadataLength;
229 :
230 2 : ReturnErrorOnFailure(WriteToPacketBuffer(acceptMsg, mPendingMsgHandle));
231 2 : msgType = MessageType::ReceiveAccept;
232 :
233 : #if CHIP_AUTOMATION_LOGGING
234 2 : ChipLogAutomation("Sending BDX Message");
235 2 : acceptMsg.LogMessage(msgType);
236 : #endif // CHIP_AUTOMATION_LOGGING
237 2 : }
238 : else
239 : {
240 1 : SendAccept acceptMsg;
241 1 : acceptMsg.TransferCtlFlags.Set(acceptData.ControlMode);
242 1 : acceptMsg.Version = mTransferVersion;
243 1 : acceptMsg.MaxBlockSize = acceptData.MaxBlockSize;
244 1 : acceptMsg.Metadata = acceptData.Metadata;
245 1 : acceptMsg.MetadataLength = acceptData.MetadataLength;
246 :
247 1 : ReturnErrorOnFailure(WriteToPacketBuffer(acceptMsg, mPendingMsgHandle));
248 1 : msgType = MessageType::SendAccept;
249 :
250 : #if CHIP_AUTOMATION_LOGGING
251 1 : ChipLogAutomation("Sending BDX Message");
252 1 : acceptMsg.LogMessage(msgType);
253 : #endif // CHIP_AUTOMATION_LOGGING
254 1 : }
255 :
256 3 : mState = TransferState::kTransferInProgress;
257 :
258 3 : if ((mRole == TransferRole::kReceiver && mControlMode == TransferControlFlags::kSenderDrive) ||
259 2 : (mRole == TransferRole::kSender && mControlMode == TransferControlFlags::kReceiverDrive))
260 : {
261 3 : mAwaitingResponse = true;
262 : }
263 :
264 3 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
265 :
266 3 : return CHIP_NO_ERROR;
267 : }
268 :
269 1 : CHIP_ERROR TransferSession::RejectTransfer(StatusCode reason)
270 : {
271 1 : VerifyOrReturnError(mState == TransferState::kNegotiateTransferParams, CHIP_ERROR_INCORRECT_STATE);
272 1 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
273 :
274 1 : PrepareStatusReport(reason);
275 1 : mState = TransferState::kTransferDone;
276 :
277 1 : return CHIP_NO_ERROR;
278 : }
279 :
280 12 : CHIP_ERROR TransferSession::PrepareBlockQuery()
281 : {
282 12 : const MessageType msgType = MessageType::BlockQuery;
283 :
284 12 : VerifyOrReturnError(mState == TransferState::kTransferInProgress, CHIP_ERROR_INCORRECT_STATE);
285 12 : VerifyOrReturnError(mRole == TransferRole::kReceiver, CHIP_ERROR_INCORRECT_STATE);
286 12 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
287 12 : VerifyOrReturnError(!mAwaitingResponse, CHIP_ERROR_INCORRECT_STATE);
288 :
289 12 : BlockQuery queryMsg;
290 12 : queryMsg.BlockCounter = mNextQueryNum;
291 :
292 12 : ReturnErrorOnFailure(WriteToPacketBuffer(queryMsg, mPendingMsgHandle));
293 :
294 : #if CHIP_AUTOMATION_LOGGING
295 12 : ChipLogAutomation("Sending BDX Message");
296 12 : queryMsg.LogMessage(msgType);
297 : #endif // CHIP_AUTOMATION_LOGGING
298 :
299 12 : mAwaitingResponse = true;
300 12 : mLastQueryNum = mNextQueryNum++;
301 :
302 12 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
303 :
304 12 : return CHIP_NO_ERROR;
305 12 : }
306 :
307 0 : CHIP_ERROR TransferSession::PrepareBlockQueryWithSkip(const uint64_t & bytesToSkip)
308 : {
309 0 : const MessageType msgType = MessageType::BlockQueryWithSkip;
310 :
311 0 : VerifyOrReturnError(mState == TransferState::kTransferInProgress, CHIP_ERROR_INCORRECT_STATE);
312 0 : VerifyOrReturnError(mRole == TransferRole::kReceiver, CHIP_ERROR_INCORRECT_STATE);
313 0 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
314 0 : VerifyOrReturnError(!mAwaitingResponse, CHIP_ERROR_INCORRECT_STATE);
315 :
316 0 : BlockQueryWithSkip queryMsg;
317 0 : queryMsg.BlockCounter = mNextQueryNum;
318 0 : queryMsg.BytesToSkip = bytesToSkip;
319 :
320 0 : ReturnErrorOnFailure(WriteToPacketBuffer(queryMsg, mPendingMsgHandle));
321 :
322 : #if CHIP_AUTOMATION_LOGGING
323 0 : ChipLogAutomation("Sending BDX Message");
324 0 : queryMsg.LogMessage(msgType);
325 : #endif // CHIP_AUTOMATION_LOGGING
326 :
327 0 : mAwaitingResponse = true;
328 0 : mLastQueryNum = mNextQueryNum++;
329 :
330 0 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
331 :
332 0 : return CHIP_NO_ERROR;
333 0 : }
334 :
335 16 : CHIP_ERROR TransferSession::PrepareBlock(const BlockData & inData)
336 : {
337 16 : VerifyOrReturnError(mState == TransferState::kTransferInProgress, CHIP_ERROR_INCORRECT_STATE);
338 16 : VerifyOrReturnError(mRole == TransferRole::kSender, CHIP_ERROR_INCORRECT_STATE);
339 16 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
340 16 : VerifyOrReturnError(!mAwaitingResponse, CHIP_ERROR_INCORRECT_STATE);
341 :
342 : // Verify non-zero data is provided and is no longer than MaxBlockSize (BlockEOF may contain 0 length data)
343 15 : VerifyOrReturnError((inData.Data != nullptr) && (inData.Length <= mTransferMaxBlockSize), CHIP_ERROR_INVALID_ARGUMENT);
344 :
345 15 : DataBlock blockMsg;
346 15 : blockMsg.BlockCounter = mNextBlockNum;
347 15 : blockMsg.Data = inData.Data;
348 15 : blockMsg.DataLength = inData.Length;
349 :
350 15 : ReturnErrorOnFailure(WriteToPacketBuffer(blockMsg, mPendingMsgHandle));
351 :
352 15 : const MessageType msgType = inData.IsEof ? MessageType::BlockEOF : MessageType::Block;
353 :
354 : #if CHIP_AUTOMATION_LOGGING
355 15 : ChipLogAutomation("Sending BDX Message");
356 15 : blockMsg.LogMessage(msgType);
357 : #endif // CHIP_AUTOMATION_LOGGING
358 :
359 15 : if (msgType == MessageType::BlockEOF)
360 : {
361 2 : mState = TransferState::kAwaitingEOFAck;
362 : }
363 :
364 15 : mAwaitingResponse = true;
365 15 : mLastBlockNum = mNextBlockNum++;
366 :
367 15 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
368 :
369 15 : return CHIP_NO_ERROR;
370 15 : }
371 :
372 6 : CHIP_ERROR TransferSession::PrepareBlockAck()
373 : {
374 6 : VerifyOrReturnError(mRole == TransferRole::kReceiver, CHIP_ERROR_INCORRECT_STATE);
375 6 : VerifyOrReturnError((mState == TransferState::kTransferInProgress) || (mState == TransferState::kReceivedEOF),
376 : CHIP_ERROR_INCORRECT_STATE);
377 6 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
378 :
379 6 : CounterMessage ackMsg;
380 6 : ackMsg.BlockCounter = mLastBlockNum;
381 6 : const MessageType msgType = (mState == TransferState::kReceivedEOF) ? MessageType::BlockAckEOF : MessageType::BlockAck;
382 :
383 6 : ReturnErrorOnFailure(WriteToPacketBuffer(ackMsg, mPendingMsgHandle));
384 :
385 : #if CHIP_AUTOMATION_LOGGING
386 6 : ChipLogAutomation("Sending BDX Message");
387 6 : ackMsg.LogMessage(msgType);
388 : #endif // CHIP_AUTOMATION_LOGGING
389 :
390 6 : if (mState == TransferState::kTransferInProgress)
391 : {
392 4 : if (mControlMode == TransferControlFlags::kSenderDrive)
393 : {
394 : // In Sender Drive, a BlockAck is implied to also be a query for the next Block, so expect to receive a Block
395 : // message.
396 3 : mLastQueryNum = ackMsg.BlockCounter + 1;
397 3 : mAwaitingResponse = true;
398 : }
399 : }
400 2 : else if (mState == TransferState::kReceivedEOF)
401 : {
402 2 : mState = TransferState::kTransferDone;
403 2 : mAwaitingResponse = false;
404 : }
405 :
406 6 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
407 :
408 6 : return CHIP_NO_ERROR;
409 6 : }
410 :
411 0 : CHIP_ERROR TransferSession::AbortTransfer(StatusCode reason)
412 : {
413 0 : VerifyOrReturnError((mState != TransferState::kUnitialized) && (mState != TransferState::kTransferDone) &&
414 : (mState != TransferState::kErrorState),
415 : CHIP_ERROR_INCORRECT_STATE);
416 :
417 0 : PrepareStatusReport(reason);
418 :
419 0 : return CHIP_NO_ERROR;
420 : }
421 :
422 0 : void TransferSession::Reset()
423 : {
424 0 : mPendingOutput = OutputEventType::kNone;
425 0 : mState = TransferState::kUnitialized;
426 0 : mSuppportedXferOpts.ClearAll();
427 0 : mTransferVersion = 0;
428 0 : mMaxSupportedBlockSize = 0;
429 0 : mStartOffset = 0;
430 0 : mTransferLength = 0;
431 0 : mTransferMaxBlockSize = 0;
432 :
433 0 : mPendingMsgHandle = nullptr;
434 :
435 0 : mNumBytesProcessed = 0;
436 0 : mLastBlockNum = 0;
437 0 : mNextBlockNum = 0;
438 0 : mLastQueryNum = 0;
439 0 : mNextQueryNum = 0;
440 :
441 0 : mTimeout = System::Clock::kZero;
442 0 : mTimeoutStartTime = System::Clock::kZero;
443 0 : mShouldInitTimeoutStart = true;
444 0 : mAwaitingResponse = false;
445 0 : }
446 :
447 44 : CHIP_ERROR TransferSession::HandleMessageReceived(const PayloadHeader & payloadHeader, System::PacketBufferHandle msg,
448 : System::Clock::Timestamp curTime)
449 : {
450 44 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
451 :
452 44 : if (payloadHeader.HasProtocol(Protocols::BDX::Id))
453 : {
454 42 : ReturnErrorOnFailure(HandleBdxMessage(payloadHeader, std::move(msg)));
455 :
456 42 : mTimeoutStartTime = curTime;
457 : }
458 2 : else if (payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport))
459 : {
460 2 : ReturnErrorOnFailure(HandleStatusReportMessage(payloadHeader, std::move(msg)));
461 : }
462 : else
463 : {
464 0 : return CHIP_ERROR_INVALID_MESSAGE_TYPE;
465 : }
466 :
467 44 : return CHIP_NO_ERROR;
468 : }
469 :
470 : // Return CHIP_ERROR only if there was a problem decoding the message. Otherwise, call PrepareStatusReport().
471 42 : CHIP_ERROR TransferSession::HandleBdxMessage(const PayloadHeader & header, System::PacketBufferHandle msg)
472 : {
473 42 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
474 42 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
475 :
476 42 : const MessageType msgType = static_cast<MessageType>(header.GetMessageType());
477 :
478 : #if CHIP_AUTOMATION_LOGGING
479 42 : ChipLogAutomation("Handling received BDX Message");
480 : #endif // CHIP_AUTOMATION_LOGGING
481 :
482 42 : switch (msgType)
483 : {
484 5 : case MessageType::SendInit:
485 : case MessageType::ReceiveInit:
486 5 : HandleTransferInit(msgType, std::move(msg));
487 5 : break;
488 1 : case MessageType::SendAccept:
489 1 : HandleSendAccept(std::move(msg));
490 1 : break;
491 2 : case MessageType::ReceiveAccept:
492 2 : HandleReceiveAccept(std::move(msg));
493 2 : break;
494 12 : case MessageType::BlockQuery:
495 12 : HandleBlockQuery(std::move(msg));
496 12 : break;
497 0 : case MessageType::BlockQueryWithSkip:
498 0 : HandleBlockQueryWithSkip(std::move(msg));
499 0 : break;
500 14 : case MessageType::Block:
501 14 : HandleBlock(std::move(msg));
502 14 : break;
503 2 : case MessageType::BlockEOF:
504 2 : HandleBlockEOF(std::move(msg));
505 2 : break;
506 4 : case MessageType::BlockAck:
507 4 : HandleBlockAck(std::move(msg));
508 4 : break;
509 2 : case MessageType::BlockAckEOF:
510 2 : HandleBlockAckEOF(std::move(msg));
511 2 : break;
512 0 : default:
513 0 : return CHIP_ERROR_INVALID_MESSAGE_TYPE;
514 : }
515 :
516 42 : return CHIP_NO_ERROR;
517 : }
518 :
519 : /**
520 : * @brief
521 : * Parse a StatusReport message and prepare to emit an OutputEvent with the message data.
522 : *
523 : * NOTE: BDX does not currently expect to ever use a "Success" general code, so it will be treated as an error along with any
524 : * other code.
525 : */
526 2 : CHIP_ERROR TransferSession::HandleStatusReportMessage(const PayloadHeader & header, System::PacketBufferHandle msg)
527 : {
528 2 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
529 :
530 2 : mState = TransferState::kErrorState;
531 2 : mAwaitingResponse = false;
532 :
533 2 : Protocols::SecureChannel::StatusReport report;
534 2 : ReturnErrorOnFailure(report.Parse(std::move(msg)));
535 2 : VerifyOrReturnError((report.GetProtocolId() == Protocols::BDX::Id), CHIP_ERROR_INVALID_MESSAGE_TYPE);
536 :
537 2 : mStatusReportData.statusCode = static_cast<StatusCode>(report.GetProtocolCode());
538 :
539 2 : mPendingOutput = OutputEventType::kStatusReceived;
540 :
541 2 : return CHIP_NO_ERROR;
542 2 : }
543 :
544 5 : void TransferSession::HandleTransferInit(MessageType msgType, System::PacketBufferHandle msgData)
545 : {
546 5 : VerifyOrReturn(mState == TransferState::kAwaitingInitMsg, PrepareStatusReport(StatusCode::kUnexpectedMessage));
547 :
548 5 : if (mRole == TransferRole::kSender)
549 : {
550 4 : VerifyOrReturn(msgType == MessageType::ReceiveInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
551 : }
552 : else
553 : {
554 1 : VerifyOrReturn(msgType == MessageType::SendInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
555 : }
556 :
557 5 : TransferInit transferInit;
558 5 : const CHIP_ERROR err = transferInit.Parse(msgData.Retain());
559 5 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
560 :
561 5 : ResolveTransferControlOptions(transferInit.TransferCtlOptions);
562 5 : mTransferVersion = std::min(kBdxVersion, transferInit.Version);
563 5 : mTransferMaxBlockSize = std::min(mMaxSupportedBlockSize, transferInit.MaxBlockSize);
564 :
565 : // Accept for now, they may be changed or rejected by the peer if this is a ReceiveInit
566 5 : mStartOffset = transferInit.StartOffset;
567 5 : mTransferLength = transferInit.MaxLength;
568 :
569 : // Store the Request data to share with the caller for verification
570 5 : mTransferRequestData.TransferCtlFlags = transferInit.TransferCtlOptions;
571 5 : mTransferRequestData.MaxBlockSize = transferInit.MaxBlockSize;
572 5 : mTransferRequestData.StartOffset = transferInit.StartOffset;
573 5 : mTransferRequestData.Length = transferInit.MaxLength;
574 5 : mTransferRequestData.FileDesignator = transferInit.FileDesignator;
575 5 : mTransferRequestData.FileDesLength = transferInit.FileDesLength;
576 5 : mTransferRequestData.Metadata = transferInit.Metadata;
577 5 : mTransferRequestData.MetadataLength = transferInit.MetadataLength;
578 :
579 5 : mPendingMsgHandle = std::move(msgData);
580 5 : mPendingOutput = OutputEventType::kInitReceived;
581 :
582 5 : mState = TransferState::kNegotiateTransferParams;
583 :
584 : #if CHIP_AUTOMATION_LOGGING
585 5 : transferInit.LogMessage(msgType);
586 : #endif // CHIP_AUTOMATION_LOGGING
587 5 : }
588 :
589 2 : void TransferSession::HandleReceiveAccept(System::PacketBufferHandle msgData)
590 : {
591 2 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
592 2 : VerifyOrReturn(mState == TransferState::kAwaitingAccept, PrepareStatusReport(StatusCode::kUnexpectedMessage));
593 :
594 2 : ReceiveAccept rcvAcceptMsg;
595 2 : const CHIP_ERROR err = rcvAcceptMsg.Parse(msgData.Retain());
596 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
597 :
598 : // Verify that Accept parameters are compatible with the original proposed parameters
599 2 : ReturnOnFailure(VerifyProposedMode(rcvAcceptMsg.TransferCtlFlags));
600 :
601 2 : mTransferMaxBlockSize = rcvAcceptMsg.MaxBlockSize;
602 2 : mStartOffset = rcvAcceptMsg.StartOffset;
603 2 : mTransferLength = rcvAcceptMsg.Length;
604 :
605 : // Note: if VerifyProposedMode() returned with no error, then mControlMode must match the proposed mode in the ReceiveAccept
606 : // message
607 2 : mTransferAcceptData.ControlMode = mControlMode;
608 2 : mTransferAcceptData.MaxBlockSize = rcvAcceptMsg.MaxBlockSize;
609 2 : mTransferAcceptData.StartOffset = rcvAcceptMsg.StartOffset;
610 2 : mTransferAcceptData.Length = rcvAcceptMsg.Length;
611 2 : mTransferAcceptData.Metadata = rcvAcceptMsg.Metadata;
612 2 : mTransferAcceptData.MetadataLength = rcvAcceptMsg.MetadataLength;
613 :
614 2 : mPendingMsgHandle = std::move(msgData);
615 2 : mPendingOutput = OutputEventType::kAcceptReceived;
616 :
617 2 : mAwaitingResponse = (mControlMode == TransferControlFlags::kSenderDrive);
618 2 : mState = TransferState::kTransferInProgress;
619 :
620 : #if CHIP_AUTOMATION_LOGGING
621 2 : rcvAcceptMsg.LogMessage(MessageType::ReceiveAccept);
622 : #endif // CHIP_AUTOMATION_LOGGING
623 2 : }
624 :
625 1 : void TransferSession::HandleSendAccept(System::PacketBufferHandle msgData)
626 : {
627 1 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
628 1 : VerifyOrReturn(mState == TransferState::kAwaitingAccept, PrepareStatusReport(StatusCode::kUnexpectedMessage));
629 :
630 1 : SendAccept sendAcceptMsg;
631 1 : const CHIP_ERROR err = sendAcceptMsg.Parse(msgData.Retain());
632 1 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
633 :
634 : // Verify that Accept parameters are compatible with the original proposed parameters
635 1 : ReturnOnFailure(VerifyProposedMode(sendAcceptMsg.TransferCtlFlags));
636 :
637 : // Note: if VerifyProposedMode() returned with no error, then mControlMode must match the proposed mode in the SendAccept
638 : // message
639 1 : mTransferMaxBlockSize = sendAcceptMsg.MaxBlockSize;
640 :
641 1 : mTransferAcceptData.ControlMode = mControlMode;
642 1 : mTransferAcceptData.MaxBlockSize = sendAcceptMsg.MaxBlockSize;
643 1 : mTransferAcceptData.StartOffset = mStartOffset; // Not included in SendAccept msg, so use member
644 1 : mTransferAcceptData.Length = mTransferLength; // Not included in SendAccept msg, so use member
645 1 : mTransferAcceptData.Metadata = sendAcceptMsg.Metadata;
646 1 : mTransferAcceptData.MetadataLength = sendAcceptMsg.MetadataLength;
647 :
648 1 : mPendingMsgHandle = std::move(msgData);
649 1 : mPendingOutput = OutputEventType::kAcceptReceived;
650 :
651 1 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
652 1 : mState = TransferState::kTransferInProgress;
653 :
654 : #if CHIP_AUTOMATION_LOGGING
655 1 : sendAcceptMsg.LogMessage(MessageType::SendAccept);
656 : #endif // CHIP_AUTOMATION_LOGGING
657 1 : }
658 :
659 12 : void TransferSession::HandleBlockQuery(System::PacketBufferHandle msgData)
660 : {
661 12 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
662 12 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
663 12 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
664 :
665 12 : BlockQuery query;
666 12 : const CHIP_ERROR err = query.Parse(std::move(msgData));
667 12 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
668 :
669 12 : VerifyOrReturn(query.BlockCounter == mNextBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
670 :
671 12 : mPendingOutput = OutputEventType::kQueryReceived;
672 :
673 12 : mAwaitingResponse = false;
674 12 : mLastQueryNum = query.BlockCounter;
675 :
676 : #if CHIP_AUTOMATION_LOGGING
677 12 : query.LogMessage(MessageType::BlockQuery);
678 : #endif // CHIP_AUTOMATION_LOGGING
679 12 : }
680 :
681 0 : void TransferSession::HandleBlockQueryWithSkip(System::PacketBufferHandle msgData)
682 : {
683 0 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
684 0 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
685 0 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
686 :
687 0 : BlockQueryWithSkip query;
688 0 : const CHIP_ERROR err = query.Parse(std::move(msgData));
689 0 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
690 :
691 0 : VerifyOrReturn(query.BlockCounter == mNextBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
692 :
693 0 : mPendingOutput = OutputEventType::kQueryWithSkipReceived;
694 :
695 0 : mAwaitingResponse = false;
696 0 : mLastQueryNum = query.BlockCounter;
697 0 : mBytesToSkip.BytesToSkip = query.BytesToSkip;
698 :
699 : #if CHIP_AUTOMATION_LOGGING
700 0 : query.LogMessage(MessageType::BlockQueryWithSkip);
701 : #endif // CHIP_AUTOMATION_LOGGING
702 0 : }
703 :
704 14 : void TransferSession::HandleBlock(System::PacketBufferHandle msgData)
705 : {
706 15 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
707 14 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
708 14 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
709 :
710 14 : Block blockMsg;
711 14 : const CHIP_ERROR err = blockMsg.Parse(msgData.Retain());
712 14 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
713 :
714 14 : VerifyOrReturn(blockMsg.BlockCounter == mLastQueryNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
715 13 : VerifyOrReturn((blockMsg.DataLength > 0) && (blockMsg.DataLength <= mTransferMaxBlockSize),
716 : PrepareStatusReport(StatusCode::kBadMessageContents));
717 :
718 13 : if (IsTransferLengthDefinite())
719 : {
720 0 : VerifyOrReturn(mNumBytesProcessed + blockMsg.DataLength <= mTransferLength,
721 : PrepareStatusReport(StatusCode::kLengthMismatch));
722 : }
723 :
724 13 : mBlockEventData.Data = blockMsg.Data;
725 13 : mBlockEventData.Length = blockMsg.DataLength;
726 13 : mBlockEventData.IsEof = false;
727 13 : mBlockEventData.BlockCounter = blockMsg.BlockCounter;
728 :
729 13 : mPendingMsgHandle = std::move(msgData);
730 13 : mPendingOutput = OutputEventType::kBlockReceived;
731 :
732 13 : mNumBytesProcessed += blockMsg.DataLength;
733 13 : mLastBlockNum = blockMsg.BlockCounter;
734 :
735 13 : mAwaitingResponse = false;
736 :
737 : #if CHIP_AUTOMATION_LOGGING
738 13 : blockMsg.LogMessage(MessageType::Block);
739 : #endif // CHIP_AUTOMATION_LOGGING
740 14 : }
741 :
742 2 : void TransferSession::HandleBlockEOF(System::PacketBufferHandle msgData)
743 : {
744 2 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
745 2 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
746 2 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
747 :
748 2 : BlockEOF blockEOFMsg;
749 2 : const CHIP_ERROR err = blockEOFMsg.Parse(msgData.Retain());
750 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
751 :
752 2 : VerifyOrReturn(blockEOFMsg.BlockCounter == mLastQueryNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
753 2 : VerifyOrReturn(blockEOFMsg.DataLength <= mTransferMaxBlockSize, PrepareStatusReport(StatusCode::kBadMessageContents));
754 :
755 2 : mBlockEventData.Data = blockEOFMsg.Data;
756 2 : mBlockEventData.Length = blockEOFMsg.DataLength;
757 2 : mBlockEventData.IsEof = true;
758 2 : mBlockEventData.BlockCounter = blockEOFMsg.BlockCounter;
759 :
760 2 : mPendingMsgHandle = std::move(msgData);
761 2 : mPendingOutput = OutputEventType::kBlockReceived;
762 :
763 2 : mNumBytesProcessed += blockEOFMsg.DataLength;
764 2 : mLastBlockNum = blockEOFMsg.BlockCounter;
765 :
766 2 : mAwaitingResponse = false;
767 2 : mState = TransferState::kReceivedEOF;
768 :
769 : #if CHIP_AUTOMATION_LOGGING
770 2 : blockEOFMsg.LogMessage(MessageType::BlockEOF);
771 : #endif // CHIP_AUTOMATION_LOGGING
772 2 : }
773 :
774 4 : void TransferSession::HandleBlockAck(System::PacketBufferHandle msgData)
775 : {
776 4 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
777 4 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
778 4 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
779 :
780 4 : BlockAck ackMsg;
781 4 : const CHIP_ERROR err = ackMsg.Parse(std::move(msgData));
782 4 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
783 4 : VerifyOrReturn(ackMsg.BlockCounter == mLastBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
784 :
785 4 : mPendingOutput = OutputEventType::kAckReceived;
786 :
787 : // In Receiver Drive, the Receiver can send a BlockAck to indicate receipt of the message and reset the timeout.
788 : // In this case, the Sender should wait to receive a BlockQuery next.
789 4 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
790 :
791 : #if CHIP_AUTOMATION_LOGGING
792 4 : ackMsg.LogMessage(MessageType::BlockAck);
793 : #endif // CHIP_AUTOMATION_LOGGING
794 4 : }
795 :
796 2 : void TransferSession::HandleBlockAckEOF(System::PacketBufferHandle msgData)
797 : {
798 2 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
799 2 : VerifyOrReturn(mState == TransferState::kAwaitingEOFAck, PrepareStatusReport(StatusCode::kUnexpectedMessage));
800 2 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
801 :
802 2 : BlockAckEOF ackMsg;
803 2 : const CHIP_ERROR err = ackMsg.Parse(std::move(msgData));
804 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
805 2 : VerifyOrReturn(ackMsg.BlockCounter == mLastBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
806 :
807 2 : mPendingOutput = OutputEventType::kAckEOFReceived;
808 :
809 2 : mAwaitingResponse = false;
810 :
811 2 : mState = TransferState::kTransferDone;
812 :
813 : #if CHIP_AUTOMATION_LOGGING
814 2 : ackMsg.LogMessage(MessageType::BlockAckEOF);
815 : #endif // CHIP_AUTOMATION_LOGGING
816 2 : }
817 :
818 5 : void TransferSession::ResolveTransferControlOptions(const BitFlags<TransferControlFlags> & proposed)
819 : {
820 : // Must specify at least one synchronous option
821 : //
822 5 : if (!proposed.HasAny(TransferControlFlags::kSenderDrive, TransferControlFlags::kReceiverDrive))
823 : {
824 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
825 0 : return;
826 : }
827 :
828 : // Ensure there are options supported by both nodes. Async gets priority.
829 : // If there is only one common option, choose that one. Otherwise the application must pick.
830 5 : const BitFlags<TransferControlFlags> commonOpts(proposed & mSuppportedXferOpts);
831 5 : if (!commonOpts.HasAny())
832 : {
833 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
834 : }
835 5 : else if (commonOpts.HasOnly(TransferControlFlags::kAsync))
836 : {
837 0 : mControlMode = TransferControlFlags::kAsync;
838 : }
839 5 : else if (commonOpts.HasOnly(TransferControlFlags::kReceiverDrive))
840 : {
841 4 : mControlMode = TransferControlFlags::kReceiverDrive;
842 : }
843 1 : else if (commonOpts.HasOnly(TransferControlFlags::kSenderDrive))
844 : {
845 1 : mControlMode = TransferControlFlags::kSenderDrive;
846 : }
847 : }
848 :
849 3 : CHIP_ERROR TransferSession::VerifyProposedMode(const BitFlags<TransferControlFlags> & proposed)
850 : {
851 : TransferControlFlags mode;
852 :
853 : // Must specify only one mode in Accept messages
854 3 : if (proposed.HasOnly(TransferControlFlags::kAsync))
855 : {
856 0 : mode = TransferControlFlags::kAsync;
857 : }
858 3 : else if (proposed.HasOnly(TransferControlFlags::kReceiverDrive))
859 : {
860 2 : mode = TransferControlFlags::kReceiverDrive;
861 : }
862 1 : else if (proposed.HasOnly(TransferControlFlags::kSenderDrive))
863 : {
864 1 : mode = TransferControlFlags::kSenderDrive;
865 : }
866 : else
867 : {
868 0 : PrepareStatusReport(StatusCode::kBadMessageContents);
869 0 : return CHIP_ERROR_INTERNAL;
870 : }
871 :
872 : // Verify the proposed mode is supported by this instance
873 3 : if (mSuppportedXferOpts.Has(mode))
874 : {
875 3 : mControlMode = mode;
876 : }
877 : else
878 : {
879 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
880 0 : return CHIP_ERROR_INTERNAL;
881 : }
882 :
883 3 : return CHIP_NO_ERROR;
884 : }
885 :
886 2 : void TransferSession::PrepareStatusReport(StatusCode code)
887 : {
888 2 : mStatusReportData.statusCode = code;
889 :
890 : Protocols::SecureChannel::StatusReport report(Protocols::SecureChannel::GeneralStatusCode::kFailure, Protocols::BDX::Id,
891 2 : to_underlying(code));
892 2 : size_t msgSize = report.Size();
893 2 : Encoding::LittleEndian::PacketBufferWriter bbuf(chip::MessagePacketBuffer::New(msgSize), msgSize);
894 2 : VerifyOrExit(!bbuf.IsNull(), mPendingOutput = OutputEventType::kInternalError);
895 :
896 2 : report.WriteToBuffer(bbuf);
897 2 : mPendingMsgHandle = bbuf.Finalize();
898 2 : if (mPendingMsgHandle.IsNull())
899 : {
900 0 : ChipLogError(BDX, "%s: error preparing message: %" CHIP_ERROR_FORMAT, __FUNCTION__, CHIP_ERROR_NO_MEMORY.Format());
901 0 : mPendingOutput = OutputEventType::kInternalError;
902 : }
903 : else
904 : {
905 2 : PrepareOutgoingMessageEvent(Protocols::SecureChannel::MsgType::StatusReport, mPendingOutput, mMsgTypeData);
906 : }
907 :
908 2 : exit:
909 2 : mState = TransferState::kErrorState;
910 2 : mAwaitingResponse = false; // Prevent triggering timeout
911 2 : }
912 :
913 13 : bool TransferSession::IsTransferLengthDefinite() const
914 : {
915 13 : return (mTransferLength > 0);
916 : }
917 :
918 0 : const char * TransferSession::OutputEvent::ToString(OutputEventType outputEventType)
919 : {
920 0 : return TypeToString(outputEventType);
921 : }
922 :
923 0 : const char * TransferSession::OutputEvent::TypeToString(OutputEventType outputEventType)
924 : {
925 0 : switch (outputEventType)
926 : {
927 0 : case OutputEventType::kNone:
928 0 : return "None";
929 0 : case OutputEventType::kMsgToSend:
930 0 : return "MsgToSend";
931 0 : case OutputEventType::kInitReceived:
932 0 : return "InitReceived";
933 0 : case OutputEventType::kAcceptReceived:
934 0 : return "AcceptReceived";
935 0 : case OutputEventType::kBlockReceived:
936 0 : return "BlockReceived";
937 0 : case OutputEventType::kQueryReceived:
938 0 : return "QueryReceived";
939 0 : case OutputEventType::kQueryWithSkipReceived:
940 0 : return "QueryWithSkipReceived";
941 0 : case OutputEventType::kAckReceived:
942 0 : return "AckReceived";
943 0 : case OutputEventType::kAckEOFReceived:
944 0 : return "AckEOFReceived";
945 0 : case OutputEventType::kStatusReceived:
946 0 : return "StatusReceived";
947 0 : case OutputEventType::kInternalError:
948 0 : return "InternalError";
949 0 : case OutputEventType::kTransferTimeout:
950 0 : return "TransferTimeout";
951 0 : default:
952 0 : return "Unknown";
953 : }
954 : }
955 :
956 5 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg)
957 : {
958 5 : OutputEvent event(OutputEventType::kInitReceived);
959 5 : event.MsgData = std::move(msg);
960 5 : event.transferInitData = data;
961 5 : return event;
962 : }
963 :
964 : /**
965 : * @brief
966 : * Convenience method for constructing an OutputEvent with TransferAcceptData that does not contain Metadata
967 : */
968 3 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data)
969 : {
970 3 : OutputEvent event(OutputEventType::kAcceptReceived);
971 3 : event.transferAcceptData = data;
972 3 : return event;
973 : }
974 : /**
975 : * @brief
976 : * Convenience method for constructing an OutputEvent with TransferAcceptData that contains Metadata
977 : */
978 3 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data,
979 : System::PacketBufferHandle msg)
980 : {
981 3 : OutputEvent event = TransferAcceptEvent(data);
982 3 : event.MsgData = std::move(msg);
983 3 : return event;
984 : }
985 :
986 15 : TransferSession::OutputEvent TransferSession::OutputEvent::BlockDataEvent(BlockData data, System::PacketBufferHandle msg)
987 : {
988 15 : OutputEvent event(OutputEventType::kBlockReceived);
989 15 : event.MsgData = std::move(msg);
990 15 : event.blockdata = data;
991 15 : return event;
992 : }
993 :
994 : /**
995 : * @brief
996 : * Convenience method for constructing an event with kInternalError or kOutputStatusReceived
997 : */
998 13 : TransferSession::OutputEvent TransferSession::OutputEvent::StatusReportEvent(OutputEventType type, StatusReportData data)
999 : {
1000 13 : OutputEvent event(type);
1001 13 : event.statusData = data;
1002 13 : return event;
1003 : }
1004 :
1005 44 : TransferSession::OutputEvent TransferSession::OutputEvent::MsgToSendEvent(MessageTypeData typeData, System::PacketBufferHandle msg)
1006 : {
1007 44 : OutputEvent event(OutputEventType::kMsgToSend);
1008 44 : event.MsgData = std::move(msg);
1009 44 : event.msgTypeData = typeData;
1010 44 : return event;
1011 : }
1012 :
1013 0 : TransferSession::OutputEvent TransferSession::OutputEvent::QueryWithSkipEvent(TransferSkipData bytesToSkip)
1014 : {
1015 0 : OutputEvent event(OutputEventType::kQueryWithSkipReceived);
1016 0 : event.bytesToSkip = bytesToSkip;
1017 0 : return event;
1018 : }
1019 :
1020 : } // namespace bdx
1021 : } // namespace chip
|