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 53 : CHIP_ERROR WriteToPacketBuffer(const ::chip::bdx::BdxMessage & msgStruct, ::chip::System::PacketBufferHandle & msgBuf)
30 : {
31 53 : size_t msgDataSize = msgStruct.MessageSize();
32 53 : ::chip::Encoding::LittleEndian::PacketBufferWriter bbuf(chip::MessagePacketBuffer::New(msgDataSize), msgDataSize);
33 53 : if (bbuf.IsNull())
34 : {
35 0 : return CHIP_ERROR_NO_MEMORY;
36 : }
37 53 : msgStruct.WriteToBuffer(bbuf);
38 53 : msgBuf = bbuf.Finalize();
39 53 : if (msgBuf.IsNull())
40 : {
41 0 : return CHIP_ERROR_NO_MEMORY;
42 : }
43 53 : return CHIP_NO_ERROR;
44 53 : }
45 :
46 : template <typename MessageType>
47 56 : 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 56 : pendingOutput = chip::bdx::TransferSession::OutputEventType::kMsgToSend;
53 56 : outputMsgType.ProtocolId = chip::Protocols::MessageTypeTraits<MessageType>::ProtocolId();
54 56 : outputMsgType.MessageType = static_cast<uint8_t>(messageType);
55 56 : }
56 :
57 : } // anonymous namespace
58 :
59 : namespace chip {
60 : namespace bdx {
61 :
62 21 : TransferSession::TransferSession()
63 : {
64 21 : mSuppportedXferOpts.ClearAll();
65 21 : }
66 :
67 211 : void TransferSession::PollOutput(OutputEvent & event, System::Clock::Timestamp curTime)
68 : {
69 211 : event = OutputEvent(OutputEventType::kNone);
70 :
71 211 : if (mShouldInitTimeoutStart)
72 : {
73 19 : mTimeoutStartTime = curTime;
74 19 : mShouldInitTimeoutStart = false;
75 : }
76 :
77 211 : 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 209 : switch (mPendingOutput)
86 : {
87 103 : case OutputEventType::kNone:
88 103 : event = OutputEvent(OutputEventType::kNone);
89 103 : 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 55 : case OutputEventType::kMsgToSend:
97 55 : event = OutputEvent::MsgToSendEvent(mMsgTypeData, std::move(mPendingMsgHandle));
98 55 : mTimeoutStartTime = curTime;
99 55 : break;
100 8 : case OutputEventType::kInitReceived:
101 8 : event = OutputEvent::TransferInitEvent(mTransferRequestData, std::move(mPendingMsgHandle));
102 8 : 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 209 : if (event.EventType == OutputEventType::kNone && mState == TransferState::kErrorState)
130 : {
131 11 : event = OutputEvent::StatusReportEvent(OutputEventType::kInternalError, mStatusReportData);
132 : }
133 :
134 209 : mPendingOutput = OutputEventType::kNone;
135 : }
136 :
137 0 : void TransferSession::GetNextAction(OutputEvent & event)
138 : {
139 0 : PollOutput(event, System::SystemClock().GetMonotonicTimestamp());
140 0 : }
141 :
142 12 : CHIP_ERROR TransferSession::StartTransfer(TransferRole role, const TransferInitData & initData, System::Clock::Timeout timeout)
143 : {
144 12 : VerifyOrReturnError(mState == TransferState::kUnitialized, CHIP_ERROR_INCORRECT_STATE);
145 :
146 12 : mRole = role;
147 12 : mTimeout = timeout;
148 :
149 : // Set transfer parameters. They may be overridden later by an Accept message
150 12 : mSuppportedXferOpts = initData.TransferCtlFlags;
151 12 : mMaxSupportedBlockSize = initData.MaxBlockSize;
152 12 : mStartOffset = initData.StartOffset;
153 12 : mTransferLength = initData.Length;
154 :
155 : // Prepare TransferInit message
156 12 : TransferInit initMsg;
157 12 : initMsg.TransferCtlOptions = initData.TransferCtlFlags;
158 12 : initMsg.Version = kBdxVersion;
159 12 : initMsg.MaxBlockSize = mMaxSupportedBlockSize;
160 12 : initMsg.StartOffset = mStartOffset;
161 12 : initMsg.MaxLength = mTransferLength;
162 12 : initMsg.FileDesignator = initData.FileDesignator;
163 12 : initMsg.FileDesLength = initData.FileDesLength;
164 12 : initMsg.Metadata = initData.Metadata;
165 12 : initMsg.MetadataLength = initData.MetadataLength;
166 :
167 12 : ReturnErrorOnFailure(WriteToPacketBuffer(initMsg, mPendingMsgHandle));
168 :
169 12 : const MessageType msgType = (mRole == TransferRole::kSender) ? MessageType::SendInit : MessageType::ReceiveInit;
170 :
171 : #if CHIP_AUTOMATION_LOGGING
172 12 : ChipLogAutomation("Sending BDX Message");
173 12 : initMsg.LogMessage(msgType);
174 : #endif // CHIP_AUTOMATION_LOGGING
175 :
176 12 : mState = TransferState::kAwaitingAccept;
177 12 : mAwaitingResponse = true;
178 :
179 12 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
180 :
181 12 : return CHIP_NO_ERROR;
182 12 : }
183 :
184 9 : CHIP_ERROR TransferSession::WaitForTransfer(TransferRole role, BitFlags<TransferControlFlags> xferControlOpts,
185 : uint16_t maxBlockSize, System::Clock::Timeout timeout)
186 : {
187 9 : VerifyOrReturnError(mState == TransferState::kUnitialized, CHIP_ERROR_INCORRECT_STATE);
188 :
189 : // Used to determine compatibility with any future TransferInit parameters
190 9 : mRole = role;
191 9 : mTimeout = timeout;
192 9 : mSuppportedXferOpts = xferControlOpts;
193 9 : mMaxSupportedBlockSize = maxBlockSize;
194 :
195 9 : mState = TransferState::kAwaitingInitMsg;
196 :
197 9 : 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 53 : CHIP_ERROR TransferSession::HandleMessageReceived(const PayloadHeader & payloadHeader, System::PacketBufferHandle msg,
436 : System::Clock::Timestamp curTime)
437 : {
438 53 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
439 :
440 53 : if (payloadHeader.HasProtocol(Protocols::BDX::Id))
441 : {
442 50 : ReturnErrorOnFailure(HandleBdxMessage(payloadHeader, std::move(msg)));
443 :
444 50 : 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 53 : return CHIP_NO_ERROR;
456 : }
457 :
458 : // Return CHIP_ERROR only if there was a problem decoding the message. Otherwise, call PrepareStatusReport().
459 50 : CHIP_ERROR TransferSession::HandleBdxMessage(const PayloadHeader & header, System::PacketBufferHandle msg)
460 : {
461 50 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
462 50 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
463 :
464 50 : const MessageType msgType = static_cast<MessageType>(header.GetMessageType());
465 :
466 50 : switch (msgType)
467 : {
468 9 : case MessageType::SendInit:
469 : case MessageType::ReceiveInit:
470 : #if CHIP_AUTOMATION_LOGGING
471 9 : ChipLogAutomation("Handling received BDX Message");
472 : #endif // CHIP_AUTOMATION_LOGGING
473 9 : HandleTransferInit(msgType, std::move(msg));
474 9 : break;
475 2 : case MessageType::SendAccept:
476 : #if CHIP_AUTOMATION_LOGGING
477 2 : ChipLogAutomation("Handling received BDX Message");
478 : #endif // CHIP_AUTOMATION_LOGGING
479 2 : HandleSendAccept(std::move(msg));
480 2 : break;
481 2 : case MessageType::ReceiveAccept:
482 : #if CHIP_AUTOMATION_LOGGING
483 2 : ChipLogAutomation("Handling received BDX Message");
484 : #endif // CHIP_AUTOMATION_LOGGING
485 2 : HandleReceiveAccept(std::move(msg));
486 2 : 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 50 : 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 9 : void TransferSession::HandleTransferInit(MessageType msgType, System::PacketBufferHandle msgData)
538 : {
539 9 : VerifyOrReturn(mState == TransferState::kAwaitingInitMsg, PrepareStatusReport(StatusCode::kUnexpectedMessage));
540 :
541 9 : if (mRole == TransferRole::kSender)
542 : {
543 4 : VerifyOrReturn(msgType == MessageType::ReceiveInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
544 : }
545 : else
546 : {
547 5 : VerifyOrReturn(msgType == MessageType::SendInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
548 : }
549 :
550 9 : TransferInit transferInit;
551 9 : const CHIP_ERROR err = transferInit.Parse(msgData.Retain());
552 9 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
553 :
554 9 : ResolveTransferControlOptions(transferInit.TransferCtlOptions);
555 9 : mTransferVersion = std::min(kBdxVersion, transferInit.Version);
556 9 : 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 9 : mStartOffset = transferInit.StartOffset;
560 9 : mTransferLength = transferInit.MaxLength;
561 :
562 : // Store the Request data to share with the caller for verification
563 9 : mTransferRequestData.TransferCtlFlags = transferInit.TransferCtlOptions;
564 9 : mTransferRequestData.MaxBlockSize = transferInit.MaxBlockSize;
565 9 : mTransferRequestData.StartOffset = transferInit.StartOffset;
566 9 : mTransferRequestData.Length = transferInit.MaxLength;
567 9 : mTransferRequestData.FileDesignator = transferInit.FileDesignator;
568 9 : mTransferRequestData.FileDesLength = transferInit.FileDesLength;
569 9 : mTransferRequestData.Metadata = transferInit.Metadata;
570 9 : mTransferRequestData.MetadataLength = transferInit.MetadataLength;
571 :
572 9 : mPendingMsgHandle = std::move(msgData);
573 9 : mPendingOutput = OutputEventType::kInitReceived;
574 :
575 9 : mState = TransferState::kNegotiateTransferParams;
576 :
577 : #if CHIP_AUTOMATION_LOGGING
578 9 : transferInit.LogMessage(msgType);
579 : #endif // CHIP_AUTOMATION_LOGGING
580 9 : }
581 :
582 2 : void TransferSession::HandleReceiveAccept(System::PacketBufferHandle msgData)
583 : {
584 2 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
585 2 : VerifyOrReturn(mState == TransferState::kAwaitingAccept, PrepareStatusReport(StatusCode::kUnexpectedMessage));
586 :
587 2 : ReceiveAccept rcvAcceptMsg;
588 2 : const CHIP_ERROR err = rcvAcceptMsg.Parse(msgData.Retain());
589 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
590 :
591 : // Verify that Accept parameters are compatible with the original proposed parameters
592 2 : ReturnOnFailure(VerifyProposedMode(rcvAcceptMsg.TransferCtlFlags));
593 :
594 2 : mTransferMaxBlockSize = rcvAcceptMsg.MaxBlockSize;
595 2 : mStartOffset = rcvAcceptMsg.StartOffset;
596 2 : mTransferLength = rcvAcceptMsg.Length;
597 :
598 : // Note: if VerifyProposedMode() returned with no error, then mControlMode must match the proposed mode in the ReceiveAccept
599 : // message
600 2 : mTransferAcceptData.ControlMode = mControlMode;
601 2 : mTransferAcceptData.MaxBlockSize = rcvAcceptMsg.MaxBlockSize;
602 2 : mTransferAcceptData.StartOffset = rcvAcceptMsg.StartOffset;
603 2 : mTransferAcceptData.Length = rcvAcceptMsg.Length;
604 2 : mTransferAcceptData.Metadata = rcvAcceptMsg.Metadata;
605 2 : mTransferAcceptData.MetadataLength = rcvAcceptMsg.MetadataLength;
606 :
607 2 : mPendingMsgHandle = std::move(msgData);
608 2 : mPendingOutput = OutputEventType::kAcceptReceived;
609 :
610 2 : mAwaitingResponse = (mControlMode == TransferControlFlags::kSenderDrive);
611 2 : mState = TransferState::kTransferInProgress;
612 :
613 : #if CHIP_AUTOMATION_LOGGING
614 2 : rcvAcceptMsg.LogMessage(MessageType::ReceiveAccept);
615 : #endif // CHIP_AUTOMATION_LOGGING
616 2 : }
617 :
618 2 : void TransferSession::HandleSendAccept(System::PacketBufferHandle msgData)
619 : {
620 2 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
621 2 : VerifyOrReturn(mState == TransferState::kAwaitingAccept, PrepareStatusReport(StatusCode::kUnexpectedMessage));
622 :
623 2 : SendAccept sendAcceptMsg;
624 2 : const CHIP_ERROR err = sendAcceptMsg.Parse(msgData.Retain());
625 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
626 :
627 : // Verify that Accept parameters are compatible with the original proposed parameters
628 2 : ReturnOnFailure(VerifyProposedMode(sendAcceptMsg.TransferCtlFlags));
629 :
630 : // Note: if VerifyProposedMode() returned with no error, then mControlMode must match the proposed mode in the SendAccept
631 : // message
632 2 : mTransferMaxBlockSize = sendAcceptMsg.MaxBlockSize;
633 :
634 2 : mTransferAcceptData.ControlMode = mControlMode;
635 2 : mTransferAcceptData.MaxBlockSize = sendAcceptMsg.MaxBlockSize;
636 2 : mTransferAcceptData.StartOffset = mStartOffset; // Not included in SendAccept msg, so use member
637 2 : mTransferAcceptData.Length = mTransferLength; // Not included in SendAccept msg, so use member
638 2 : mTransferAcceptData.Metadata = sendAcceptMsg.Metadata;
639 2 : mTransferAcceptData.MetadataLength = sendAcceptMsg.MetadataLength;
640 :
641 2 : mPendingMsgHandle = std::move(msgData);
642 2 : mPendingOutput = OutputEventType::kAcceptReceived;
643 :
644 2 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
645 2 : mState = TransferState::kTransferInProgress;
646 :
647 : #if CHIP_AUTOMATION_LOGGING
648 2 : sendAcceptMsg.LogMessage(MessageType::SendAccept);
649 : #endif // CHIP_AUTOMATION_LOGGING
650 2 : }
651 :
652 12 : void TransferSession::HandleBlockQuery(System::PacketBufferHandle msgData)
653 : {
654 12 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
655 12 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
656 12 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
657 :
658 12 : BlockQuery query;
659 12 : const CHIP_ERROR err = query.Parse(std::move(msgData));
660 12 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
661 :
662 12 : VerifyOrReturn(query.BlockCounter == mNextBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
663 :
664 12 : mPendingOutput = OutputEventType::kQueryReceived;
665 :
666 12 : mAwaitingResponse = false;
667 12 : mLastQueryNum = query.BlockCounter;
668 12 : }
669 :
670 0 : void TransferSession::HandleBlockQueryWithSkip(System::PacketBufferHandle msgData)
671 : {
672 0 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
673 0 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
674 0 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
675 :
676 0 : BlockQueryWithSkip query;
677 0 : const CHIP_ERROR err = query.Parse(std::move(msgData));
678 0 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
679 :
680 0 : VerifyOrReturn(query.BlockCounter == mNextBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
681 :
682 0 : mPendingOutput = OutputEventType::kQueryWithSkipReceived;
683 :
684 0 : mAwaitingResponse = false;
685 0 : mLastQueryNum = query.BlockCounter;
686 0 : mBytesToSkip.BytesToSkip = query.BytesToSkip;
687 0 : }
688 :
689 16 : void TransferSession::HandleBlock(System::PacketBufferHandle msgData)
690 : {
691 17 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
692 16 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
693 16 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
694 :
695 16 : Block blockMsg;
696 16 : const CHIP_ERROR err = blockMsg.Parse(msgData.Retain());
697 16 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
698 :
699 16 : VerifyOrReturn(blockMsg.BlockCounter == mLastQueryNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
700 15 : VerifyOrReturn((blockMsg.DataLength > 0) && (blockMsg.DataLength <= mTransferMaxBlockSize),
701 : PrepareStatusReport(StatusCode::kBadMessageContents));
702 :
703 15 : if (IsTransferLengthDefinite())
704 : {
705 2 : VerifyOrReturn(mNumBytesProcessed + blockMsg.DataLength <= mTransferLength,
706 : PrepareStatusReport(StatusCode::kLengthMismatch));
707 : }
708 :
709 15 : mBlockEventData.Data = blockMsg.Data;
710 15 : mBlockEventData.Length = blockMsg.DataLength;
711 15 : mBlockEventData.IsEof = false;
712 15 : mBlockEventData.BlockCounter = blockMsg.BlockCounter;
713 :
714 15 : mPendingMsgHandle = std::move(msgData);
715 15 : mPendingOutput = OutputEventType::kBlockReceived;
716 :
717 15 : mNumBytesProcessed += blockMsg.DataLength;
718 15 : mLastBlockNum = blockMsg.BlockCounter;
719 :
720 15 : mAwaitingResponse = false;
721 16 : }
722 :
723 2 : void TransferSession::HandleBlockEOF(System::PacketBufferHandle msgData)
724 : {
725 2 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
726 2 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
727 2 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
728 :
729 2 : BlockEOF blockEOFMsg;
730 2 : const CHIP_ERROR err = blockEOFMsg.Parse(msgData.Retain());
731 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
732 :
733 2 : VerifyOrReturn(blockEOFMsg.BlockCounter == mLastQueryNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
734 2 : VerifyOrReturn(blockEOFMsg.DataLength <= mTransferMaxBlockSize, PrepareStatusReport(StatusCode::kBadMessageContents));
735 :
736 2 : mBlockEventData.Data = blockEOFMsg.Data;
737 2 : mBlockEventData.Length = blockEOFMsg.DataLength;
738 2 : mBlockEventData.IsEof = true;
739 2 : mBlockEventData.BlockCounter = blockEOFMsg.BlockCounter;
740 :
741 2 : mPendingMsgHandle = std::move(msgData);
742 2 : mPendingOutput = OutputEventType::kBlockReceived;
743 :
744 2 : mNumBytesProcessed += blockEOFMsg.DataLength;
745 2 : mLastBlockNum = blockEOFMsg.BlockCounter;
746 :
747 2 : mAwaitingResponse = false;
748 2 : mState = TransferState::kReceivedEOF;
749 :
750 : #if CHIP_AUTOMATION_LOGGING
751 2 : blockEOFMsg.LogMessage(MessageType::BlockEOF);
752 : #endif // CHIP_AUTOMATION_LOGGING
753 2 : }
754 :
755 5 : void TransferSession::HandleBlockAck(System::PacketBufferHandle msgData)
756 : {
757 5 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
758 5 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
759 5 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
760 :
761 5 : BlockAck ackMsg;
762 5 : const CHIP_ERROR err = ackMsg.Parse(std::move(msgData));
763 5 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
764 5 : VerifyOrReturn(ackMsg.BlockCounter == mLastBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
765 :
766 5 : mPendingOutput = OutputEventType::kAckReceived;
767 :
768 : // In Receiver Drive, the Receiver can send a BlockAck to indicate receipt of the message and reset the timeout.
769 : // In this case, the Sender should wait to receive a BlockQuery next.
770 5 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
771 5 : }
772 :
773 2 : void TransferSession::HandleBlockAckEOF(System::PacketBufferHandle msgData)
774 : {
775 2 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
776 2 : VerifyOrReturn(mState == TransferState::kAwaitingEOFAck, PrepareStatusReport(StatusCode::kUnexpectedMessage));
777 2 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
778 :
779 2 : BlockAckEOF ackMsg;
780 2 : const CHIP_ERROR err = ackMsg.Parse(std::move(msgData));
781 2 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
782 2 : VerifyOrReturn(ackMsg.BlockCounter == mLastBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
783 :
784 2 : mPendingOutput = OutputEventType::kAckEOFReceived;
785 :
786 2 : mAwaitingResponse = false;
787 :
788 2 : mState = TransferState::kTransferDone;
789 :
790 : #if CHIP_AUTOMATION_LOGGING
791 2 : ackMsg.LogMessage(MessageType::BlockAckEOF);
792 : #endif // CHIP_AUTOMATION_LOGGING
793 2 : }
794 :
795 9 : void TransferSession::ResolveTransferControlOptions(const BitFlags<TransferControlFlags> & proposed)
796 : {
797 : // Must specify at least one synchronous option
798 : //
799 9 : if (!proposed.HasAny(TransferControlFlags::kSenderDrive, TransferControlFlags::kReceiverDrive))
800 : {
801 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
802 0 : return;
803 : }
804 :
805 : // Ensure there are options supported by both nodes. Async gets priority.
806 : // If there is only one common option, choose that one. Otherwise the application must pick.
807 9 : const BitFlags<TransferControlFlags> commonOpts(proposed & mSuppportedXferOpts);
808 9 : if (!commonOpts.HasAny())
809 : {
810 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
811 : }
812 9 : else if (commonOpts.HasOnly(TransferControlFlags::kAsync))
813 : {
814 0 : mControlMode = TransferControlFlags::kAsync;
815 : }
816 9 : else if (commonOpts.HasOnly(TransferControlFlags::kReceiverDrive))
817 : {
818 4 : mControlMode = TransferControlFlags::kReceiverDrive;
819 : }
820 5 : else if (commonOpts.HasOnly(TransferControlFlags::kSenderDrive))
821 : {
822 5 : mControlMode = TransferControlFlags::kSenderDrive;
823 : }
824 : }
825 :
826 4 : CHIP_ERROR TransferSession::VerifyProposedMode(const BitFlags<TransferControlFlags> & proposed)
827 : {
828 : TransferControlFlags mode;
829 :
830 : // Must specify only one mode in Accept messages
831 4 : if (proposed.HasOnly(TransferControlFlags::kAsync))
832 : {
833 0 : mode = TransferControlFlags::kAsync;
834 : }
835 4 : else if (proposed.HasOnly(TransferControlFlags::kReceiverDrive))
836 : {
837 2 : mode = TransferControlFlags::kReceiverDrive;
838 : }
839 2 : else if (proposed.HasOnly(TransferControlFlags::kSenderDrive))
840 : {
841 2 : mode = TransferControlFlags::kSenderDrive;
842 : }
843 : else
844 : {
845 0 : PrepareStatusReport(StatusCode::kBadMessageContents);
846 0 : return CHIP_ERROR_INTERNAL;
847 : }
848 :
849 : // Verify the proposed mode is supported by this instance
850 4 : if (mSuppportedXferOpts.Has(mode))
851 : {
852 4 : mControlMode = mode;
853 : }
854 : else
855 : {
856 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
857 0 : return CHIP_ERROR_INTERNAL;
858 : }
859 :
860 4 : return CHIP_NO_ERROR;
861 : }
862 :
863 3 : void TransferSession::PrepareStatusReport(StatusCode code)
864 : {
865 3 : mStatusReportData.statusCode = code;
866 :
867 : Protocols::SecureChannel::StatusReport report(Protocols::SecureChannel::GeneralStatusCode::kFailure, Protocols::BDX::Id,
868 3 : to_underlying(code));
869 3 : size_t msgSize = report.Size();
870 3 : Encoding::LittleEndian::PacketBufferWriter bbuf(chip::MessagePacketBuffer::New(msgSize), msgSize);
871 3 : VerifyOrExit(!bbuf.IsNull(), mPendingOutput = OutputEventType::kInternalError);
872 :
873 3 : report.WriteToBuffer(bbuf);
874 3 : mPendingMsgHandle = bbuf.Finalize();
875 3 : if (mPendingMsgHandle.IsNull())
876 : {
877 0 : ChipLogError(BDX, "%s: error preparing message: %" CHIP_ERROR_FORMAT, __FUNCTION__, CHIP_ERROR_NO_MEMORY.Format());
878 0 : mPendingOutput = OutputEventType::kInternalError;
879 : }
880 : else
881 : {
882 3 : PrepareOutgoingMessageEvent(Protocols::SecureChannel::MsgType::StatusReport, mPendingOutput, mMsgTypeData);
883 : }
884 :
885 3 : exit:
886 3 : mState = TransferState::kErrorState;
887 3 : mAwaitingResponse = false; // Prevent triggering timeout
888 3 : }
889 :
890 15 : bool TransferSession::IsTransferLengthDefinite() const
891 : {
892 15 : return (mTransferLength > 0);
893 : }
894 :
895 0 : const char * TransferSession::OutputEvent::ToString(OutputEventType outputEventType)
896 : {
897 0 : return TypeToString(outputEventType);
898 : }
899 :
900 0 : const char * TransferSession::OutputEvent::TypeToString(OutputEventType outputEventType)
901 : {
902 0 : switch (outputEventType)
903 : {
904 0 : case OutputEventType::kNone:
905 0 : return "None";
906 0 : case OutputEventType::kMsgToSend:
907 0 : return "MsgToSend";
908 0 : case OutputEventType::kInitReceived:
909 0 : return "InitReceived";
910 0 : case OutputEventType::kAcceptReceived:
911 0 : return "AcceptReceived";
912 0 : case OutputEventType::kBlockReceived:
913 0 : return "BlockReceived";
914 0 : case OutputEventType::kQueryReceived:
915 0 : return "QueryReceived";
916 0 : case OutputEventType::kQueryWithSkipReceived:
917 0 : return "QueryWithSkipReceived";
918 0 : case OutputEventType::kAckReceived:
919 0 : return "AckReceived";
920 0 : case OutputEventType::kAckEOFReceived:
921 0 : return "AckEOFReceived";
922 0 : case OutputEventType::kStatusReceived:
923 0 : return "StatusReceived";
924 0 : case OutputEventType::kInternalError:
925 0 : return "InternalError";
926 0 : case OutputEventType::kTransferTimeout:
927 0 : return "TransferTimeout";
928 0 : default:
929 0 : return "Unknown";
930 : }
931 : }
932 :
933 8 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg)
934 : {
935 8 : OutputEvent event(OutputEventType::kInitReceived);
936 8 : event.MsgData = std::move(msg);
937 8 : event.transferInitData = data;
938 8 : return event;
939 : }
940 :
941 : /**
942 : * @brief
943 : * Convenience method for constructing an OutputEvent with TransferAcceptData that does not contain Metadata
944 : */
945 4 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data)
946 : {
947 4 : OutputEvent event(OutputEventType::kAcceptReceived);
948 4 : event.transferAcceptData = data;
949 4 : return event;
950 : }
951 : /**
952 : * @brief
953 : * Convenience method for constructing an OutputEvent with TransferAcceptData that contains Metadata
954 : */
955 4 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data,
956 : System::PacketBufferHandle msg)
957 : {
958 4 : OutputEvent event = TransferAcceptEvent(data);
959 4 : event.MsgData = std::move(msg);
960 4 : return event;
961 : }
962 :
963 17 : TransferSession::OutputEvent TransferSession::OutputEvent::BlockDataEvent(BlockData data, System::PacketBufferHandle msg)
964 : {
965 17 : OutputEvent event(OutputEventType::kBlockReceived);
966 17 : event.MsgData = std::move(msg);
967 17 : event.blockdata = data;
968 17 : return event;
969 : }
970 :
971 : /**
972 : * @brief
973 : * Convenience method for constructing an event with kInternalError or kOutputStatusReceived
974 : */
975 14 : TransferSession::OutputEvent TransferSession::OutputEvent::StatusReportEvent(OutputEventType type, StatusReportData data)
976 : {
977 14 : OutputEvent event(type);
978 14 : event.statusData = data;
979 14 : return event;
980 : }
981 :
982 55 : TransferSession::OutputEvent TransferSession::OutputEvent::MsgToSendEvent(MessageTypeData typeData, System::PacketBufferHandle msg)
983 : {
984 55 : OutputEvent event(OutputEventType::kMsgToSend);
985 55 : event.MsgData = std::move(msg);
986 55 : event.msgTypeData = typeData;
987 55 : return event;
988 : }
989 :
990 0 : TransferSession::OutputEvent TransferSession::OutputEvent::QueryWithSkipEvent(TransferSkipData bytesToSkip)
991 : {
992 0 : OutputEvent event(OutputEventType::kQueryWithSkipReceived);
993 0 : event.bytesToSkip = bytesToSkip;
994 0 : return event;
995 : }
996 :
997 : } // namespace bdx
998 : } // namespace chip
|