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