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 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 16 : CHIP_ERROR TransferSession::PrepareBlock(const BlockData & inData)
326 : {
327 16 : VerifyOrReturnError(mState == TransferState::kTransferInProgress, CHIP_ERROR_INCORRECT_STATE);
328 16 : VerifyOrReturnError(mRole == TransferRole::kSender, CHIP_ERROR_INCORRECT_STATE);
329 16 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
330 16 : 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 15 : VerifyOrReturnError((inData.Data != nullptr) && (inData.Length <= mTransferMaxBlockSize), CHIP_ERROR_INVALID_ARGUMENT);
334 :
335 15 : DataBlock blockMsg;
336 15 : blockMsg.BlockCounter = mNextBlockNum;
337 15 : blockMsg.Data = inData.Data;
338 15 : blockMsg.DataLength = inData.Length;
339 :
340 15 : ReturnErrorOnFailure(WriteToPacketBuffer(blockMsg, mPendingMsgHandle));
341 :
342 15 : const MessageType msgType = inData.IsEof ? MessageType::BlockEOF : MessageType::Block;
343 :
344 15 : 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 15 : mAwaitingResponse = true;
354 15 : mLastBlockNum = mNextBlockNum++;
355 :
356 15 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
357 :
358 15 : return CHIP_NO_ERROR;
359 15 : }
360 :
361 6 : CHIP_ERROR TransferSession::PrepareBlockAck()
362 : {
363 6 : VerifyOrReturnError(mRole == TransferRole::kReceiver, CHIP_ERROR_INCORRECT_STATE);
364 6 : VerifyOrReturnError((mState == TransferState::kTransferInProgress) || (mState == TransferState::kReceivedEOF),
365 : CHIP_ERROR_INCORRECT_STATE);
366 6 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
367 :
368 6 : CounterMessage ackMsg;
369 6 : ackMsg.BlockCounter = mLastBlockNum;
370 6 : const MessageType msgType = (mState == TransferState::kReceivedEOF) ? MessageType::BlockAckEOF : MessageType::BlockAck;
371 :
372 6 : ReturnErrorOnFailure(WriteToPacketBuffer(ackMsg, mPendingMsgHandle));
373 :
374 6 : if (mState == TransferState::kTransferInProgress)
375 : {
376 4 : 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 3 : mLastQueryNum = ackMsg.BlockCounter + 1;
381 3 : 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 6 : PrepareOutgoingMessageEvent(msgType, mPendingOutput, mMsgTypeData);
395 :
396 6 : return CHIP_NO_ERROR;
397 6 : }
398 :
399 0 : CHIP_ERROR TransferSession::AbortTransfer(StatusCode reason)
400 : {
401 0 : VerifyOrReturnError((mState != TransferState::kUnitialized) && (mState != TransferState::kTransferDone) &&
402 : (mState != TransferState::kErrorState),
403 : CHIP_ERROR_INCORRECT_STATE);
404 :
405 0 : PrepareStatusReport(reason);
406 :
407 0 : return CHIP_NO_ERROR;
408 : }
409 :
410 0 : void TransferSession::Reset()
411 : {
412 0 : mPendingOutput = OutputEventType::kNone;
413 0 : mState = TransferState::kUnitialized;
414 0 : mSuppportedXferOpts.ClearAll();
415 0 : mTransferVersion = 0;
416 0 : mMaxSupportedBlockSize = 0;
417 0 : mStartOffset = 0;
418 0 : mTransferLength = 0;
419 0 : mTransferMaxBlockSize = 0;
420 :
421 0 : mPendingMsgHandle = nullptr;
422 :
423 0 : mNumBytesProcessed = 0;
424 0 : mLastBlockNum = 0;
425 0 : mNextBlockNum = 0;
426 0 : mLastQueryNum = 0;
427 0 : mNextQueryNum = 0;
428 :
429 0 : mTimeout = System::Clock::kZero;
430 0 : mTimeoutStartTime = System::Clock::kZero;
431 0 : mShouldInitTimeoutStart = true;
432 0 : mAwaitingResponse = false;
433 0 : }
434 :
435 44 : CHIP_ERROR TransferSession::HandleMessageReceived(const PayloadHeader & payloadHeader, System::PacketBufferHandle msg,
436 : System::Clock::Timestamp curTime)
437 : {
438 44 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
439 :
440 44 : if (payloadHeader.HasProtocol(Protocols::BDX::Id))
441 : {
442 42 : ReturnErrorOnFailure(HandleBdxMessage(payloadHeader, std::move(msg)));
443 :
444 42 : mTimeoutStartTime = curTime;
445 : }
446 2 : else if (payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport))
447 : {
448 2 : ReturnErrorOnFailure(HandleStatusReportMessage(payloadHeader, std::move(msg)));
449 : }
450 : else
451 : {
452 0 : return CHIP_ERROR_INVALID_MESSAGE_TYPE;
453 : }
454 :
455 44 : return CHIP_NO_ERROR;
456 : }
457 :
458 : // Return CHIP_ERROR only if there was a problem decoding the message. Otherwise, call PrepareStatusReport().
459 42 : CHIP_ERROR TransferSession::HandleBdxMessage(const PayloadHeader & header, System::PacketBufferHandle msg)
460 : {
461 42 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
462 42 : VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE);
463 :
464 42 : const MessageType msgType = static_cast<MessageType>(header.GetMessageType());
465 :
466 42 : switch (msgType)
467 : {
468 5 : case MessageType::SendInit:
469 : case MessageType::ReceiveInit:
470 : #if CHIP_AUTOMATION_LOGGING
471 5 : ChipLogAutomation("Handling received BDX Message");
472 : #endif // CHIP_AUTOMATION_LOGGING
473 5 : HandleTransferInit(msgType, std::move(msg));
474 5 : break;
475 1 : case MessageType::SendAccept:
476 : #if CHIP_AUTOMATION_LOGGING
477 1 : ChipLogAutomation("Handling received BDX Message");
478 : #endif // CHIP_AUTOMATION_LOGGING
479 1 : HandleSendAccept(std::move(msg));
480 1 : 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 14 : case MessageType::Block:
494 14 : HandleBlock(std::move(msg));
495 14 : break;
496 2 : case MessageType::BlockEOF:
497 2 : HandleBlockEOF(std::move(msg));
498 2 : break;
499 4 : case MessageType::BlockAck:
500 4 : HandleBlockAck(std::move(msg));
501 4 : 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 42 : 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 2 : CHIP_ERROR TransferSession::HandleStatusReportMessage(const PayloadHeader & header, System::PacketBufferHandle msg)
520 : {
521 2 : VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
522 :
523 2 : mState = TransferState::kErrorState;
524 2 : mAwaitingResponse = false;
525 :
526 2 : Protocols::SecureChannel::StatusReport report;
527 2 : ReturnErrorOnFailure(report.Parse(std::move(msg)));
528 2 : VerifyOrReturnError((report.GetProtocolId() == Protocols::BDX::Id), CHIP_ERROR_INVALID_MESSAGE_TYPE);
529 :
530 2 : mStatusReportData.statusCode = static_cast<StatusCode>(report.GetProtocolCode());
531 :
532 2 : mPendingOutput = OutputEventType::kStatusReceived;
533 :
534 2 : return CHIP_NO_ERROR;
535 2 : }
536 :
537 5 : void TransferSession::HandleTransferInit(MessageType msgType, System::PacketBufferHandle msgData)
538 : {
539 5 : VerifyOrReturn(mState == TransferState::kAwaitingInitMsg, PrepareStatusReport(StatusCode::kUnexpectedMessage));
540 :
541 5 : if (mRole == TransferRole::kSender)
542 : {
543 4 : VerifyOrReturn(msgType == MessageType::ReceiveInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
544 : }
545 : else
546 : {
547 1 : VerifyOrReturn(msgType == MessageType::SendInit, PrepareStatusReport(StatusCode::kUnexpectedMessage));
548 : }
549 :
550 5 : TransferInit transferInit;
551 5 : const CHIP_ERROR err = transferInit.Parse(msgData.Retain());
552 5 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
553 :
554 5 : ResolveTransferControlOptions(transferInit.TransferCtlOptions);
555 5 : mTransferVersion = std::min(kBdxVersion, transferInit.Version);
556 5 : 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 5 : mStartOffset = transferInit.StartOffset;
560 5 : mTransferLength = transferInit.MaxLength;
561 :
562 : // Store the Request data to share with the caller for verification
563 5 : mTransferRequestData.TransferCtlFlags = transferInit.TransferCtlOptions;
564 5 : mTransferRequestData.MaxBlockSize = transferInit.MaxBlockSize;
565 5 : mTransferRequestData.StartOffset = transferInit.StartOffset;
566 5 : mTransferRequestData.Length = transferInit.MaxLength;
567 5 : mTransferRequestData.FileDesignator = transferInit.FileDesignator;
568 5 : mTransferRequestData.FileDesLength = transferInit.FileDesLength;
569 5 : mTransferRequestData.Metadata = transferInit.Metadata;
570 5 : mTransferRequestData.MetadataLength = transferInit.MetadataLength;
571 :
572 5 : mPendingMsgHandle = std::move(msgData);
573 5 : mPendingOutput = OutputEventType::kInitReceived;
574 :
575 5 : mState = TransferState::kNegotiateTransferParams;
576 :
577 : #if CHIP_AUTOMATION_LOGGING
578 5 : transferInit.LogMessage(msgType);
579 : #endif // CHIP_AUTOMATION_LOGGING
580 5 : }
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 1 : void TransferSession::HandleSendAccept(System::PacketBufferHandle msgData)
619 : {
620 1 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
621 1 : VerifyOrReturn(mState == TransferState::kAwaitingAccept, PrepareStatusReport(StatusCode::kUnexpectedMessage));
622 :
623 1 : SendAccept sendAcceptMsg;
624 1 : const CHIP_ERROR err = sendAcceptMsg.Parse(msgData.Retain());
625 1 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
626 :
627 : // Verify that Accept parameters are compatible with the original proposed parameters
628 1 : 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 1 : mTransferMaxBlockSize = sendAcceptMsg.MaxBlockSize;
633 :
634 1 : mTransferAcceptData.ControlMode = mControlMode;
635 1 : mTransferAcceptData.MaxBlockSize = sendAcceptMsg.MaxBlockSize;
636 1 : mTransferAcceptData.StartOffset = mStartOffset; // Not included in SendAccept msg, so use member
637 1 : mTransferAcceptData.Length = mTransferLength; // Not included in SendAccept msg, so use member
638 1 : mTransferAcceptData.Metadata = sendAcceptMsg.Metadata;
639 1 : mTransferAcceptData.MetadataLength = sendAcceptMsg.MetadataLength;
640 :
641 1 : mPendingMsgHandle = std::move(msgData);
642 1 : mPendingOutput = OutputEventType::kAcceptReceived;
643 :
644 1 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
645 1 : mState = TransferState::kTransferInProgress;
646 :
647 : #if CHIP_AUTOMATION_LOGGING
648 1 : sendAcceptMsg.LogMessage(MessageType::SendAccept);
649 : #endif // CHIP_AUTOMATION_LOGGING
650 1 : }
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 14 : void TransferSession::HandleBlock(System::PacketBufferHandle msgData)
690 : {
691 15 : VerifyOrReturn(mRole == TransferRole::kReceiver, PrepareStatusReport(StatusCode::kUnexpectedMessage));
692 14 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
693 14 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
694 :
695 14 : Block blockMsg;
696 14 : const CHIP_ERROR err = blockMsg.Parse(msgData.Retain());
697 14 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
698 :
699 14 : VerifyOrReturn(blockMsg.BlockCounter == mLastQueryNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
700 13 : VerifyOrReturn((blockMsg.DataLength > 0) && (blockMsg.DataLength <= mTransferMaxBlockSize),
701 : PrepareStatusReport(StatusCode::kBadMessageContents));
702 :
703 13 : if (IsTransferLengthDefinite())
704 : {
705 0 : VerifyOrReturn(mNumBytesProcessed + blockMsg.DataLength <= mTransferLength,
706 : PrepareStatusReport(StatusCode::kLengthMismatch));
707 : }
708 :
709 13 : mBlockEventData.Data = blockMsg.Data;
710 13 : mBlockEventData.Length = blockMsg.DataLength;
711 13 : mBlockEventData.IsEof = false;
712 13 : mBlockEventData.BlockCounter = blockMsg.BlockCounter;
713 :
714 13 : mPendingMsgHandle = std::move(msgData);
715 13 : mPendingOutput = OutputEventType::kBlockReceived;
716 :
717 13 : mNumBytesProcessed += blockMsg.DataLength;
718 13 : mLastBlockNum = blockMsg.BlockCounter;
719 :
720 13 : mAwaitingResponse = false;
721 14 : }
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 4 : void TransferSession::HandleBlockAck(System::PacketBufferHandle msgData)
756 : {
757 4 : VerifyOrReturn(mRole == TransferRole::kSender, PrepareStatusReport(StatusCode::kUnexpectedMessage));
758 4 : VerifyOrReturn(mState == TransferState::kTransferInProgress, PrepareStatusReport(StatusCode::kUnexpectedMessage));
759 4 : VerifyOrReturn(mAwaitingResponse, PrepareStatusReport(StatusCode::kUnexpectedMessage));
760 :
761 4 : BlockAck ackMsg;
762 4 : const CHIP_ERROR err = ackMsg.Parse(std::move(msgData));
763 4 : VerifyOrReturn(err == CHIP_NO_ERROR, PrepareStatusReport(StatusCode::kBadMessageContents));
764 4 : VerifyOrReturn(ackMsg.BlockCounter == mLastBlockNum, PrepareStatusReport(StatusCode::kBadBlockCounter));
765 :
766 4 : 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 4 : mAwaitingResponse = (mControlMode == TransferControlFlags::kReceiverDrive);
771 4 : }
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 5 : void TransferSession::ResolveTransferControlOptions(const BitFlags<TransferControlFlags> & proposed)
796 : {
797 : // Must specify at least one synchronous option
798 : //
799 5 : 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 5 : const BitFlags<TransferControlFlags> commonOpts(proposed & mSuppportedXferOpts);
808 5 : if (!commonOpts.HasAny())
809 : {
810 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
811 : }
812 5 : else if (commonOpts.HasOnly(TransferControlFlags::kAsync))
813 : {
814 0 : mControlMode = TransferControlFlags::kAsync;
815 : }
816 5 : else if (commonOpts.HasOnly(TransferControlFlags::kReceiverDrive))
817 : {
818 4 : mControlMode = TransferControlFlags::kReceiverDrive;
819 : }
820 1 : else if (commonOpts.HasOnly(TransferControlFlags::kSenderDrive))
821 : {
822 1 : mControlMode = TransferControlFlags::kSenderDrive;
823 : }
824 : }
825 :
826 3 : CHIP_ERROR TransferSession::VerifyProposedMode(const BitFlags<TransferControlFlags> & proposed)
827 : {
828 : TransferControlFlags mode;
829 :
830 : // Must specify only one mode in Accept messages
831 3 : if (proposed.HasOnly(TransferControlFlags::kAsync))
832 : {
833 0 : mode = TransferControlFlags::kAsync;
834 : }
835 3 : else if (proposed.HasOnly(TransferControlFlags::kReceiverDrive))
836 : {
837 2 : mode = TransferControlFlags::kReceiverDrive;
838 : }
839 1 : else if (proposed.HasOnly(TransferControlFlags::kSenderDrive))
840 : {
841 1 : 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 3 : if (mSuppportedXferOpts.Has(mode))
851 : {
852 3 : mControlMode = mode;
853 : }
854 : else
855 : {
856 0 : PrepareStatusReport(StatusCode::kTransferMethodNotSupported);
857 0 : return CHIP_ERROR_INTERNAL;
858 : }
859 :
860 3 : return CHIP_NO_ERROR;
861 : }
862 :
863 2 : void TransferSession::PrepareStatusReport(StatusCode code)
864 : {
865 2 : mStatusReportData.statusCode = code;
866 :
867 : Protocols::SecureChannel::StatusReport report(Protocols::SecureChannel::GeneralStatusCode::kFailure, Protocols::BDX::Id,
868 2 : to_underlying(code));
869 2 : size_t msgSize = report.Size();
870 2 : Encoding::LittleEndian::PacketBufferWriter bbuf(chip::MessagePacketBuffer::New(msgSize), msgSize);
871 2 : VerifyOrExit(!bbuf.IsNull(), mPendingOutput = OutputEventType::kInternalError);
872 :
873 2 : report.WriteToBuffer(bbuf);
874 2 : mPendingMsgHandle = bbuf.Finalize();
875 2 : 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 2 : PrepareOutgoingMessageEvent(Protocols::SecureChannel::MsgType::StatusReport, mPendingOutput, mMsgTypeData);
883 : }
884 :
885 2 : exit:
886 2 : mState = TransferState::kErrorState;
887 2 : mAwaitingResponse = false; // Prevent triggering timeout
888 2 : }
889 :
890 13 : bool TransferSession::IsTransferLengthDefinite() const
891 : {
892 13 : 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 5 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg)
934 : {
935 5 : OutputEvent event(OutputEventType::kInitReceived);
936 5 : event.MsgData = std::move(msg);
937 5 : event.transferInitData = data;
938 5 : return event;
939 : }
940 :
941 : /**
942 : * @brief
943 : * Convenience method for constructing an OutputEvent with TransferAcceptData that does not contain Metadata
944 : */
945 3 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data)
946 : {
947 3 : OutputEvent event(OutputEventType::kAcceptReceived);
948 3 : event.transferAcceptData = data;
949 3 : return event;
950 : }
951 : /**
952 : * @brief
953 : * Convenience method for constructing an OutputEvent with TransferAcceptData that contains Metadata
954 : */
955 3 : TransferSession::OutputEvent TransferSession::OutputEvent::TransferAcceptEvent(TransferAcceptData data,
956 : System::PacketBufferHandle msg)
957 : {
958 3 : OutputEvent event = TransferAcceptEvent(data);
959 3 : event.MsgData = std::move(msg);
960 3 : return event;
961 : }
962 :
963 15 : TransferSession::OutputEvent TransferSession::OutputEvent::BlockDataEvent(BlockData data, System::PacketBufferHandle msg)
964 : {
965 15 : OutputEvent event(OutputEventType::kBlockReceived);
966 15 : event.MsgData = std::move(msg);
967 15 : event.blockdata = data;
968 15 : return event;
969 : }
970 :
971 : /**
972 : * @brief
973 : * Convenience method for constructing an event with kInternalError or kOutputStatusReceived
974 : */
975 13 : TransferSession::OutputEvent TransferSession::OutputEvent::StatusReportEvent(OutputEventType type, StatusReportData data)
976 : {
977 13 : OutputEvent event(type);
978 13 : event.statusData = data;
979 13 : return event;
980 : }
981 :
982 44 : TransferSession::OutputEvent TransferSession::OutputEvent::MsgToSendEvent(MessageTypeData typeData, System::PacketBufferHandle msg)
983 : {
984 44 : OutputEvent event(OutputEventType::kMsgToSend);
985 44 : event.MsgData = std::move(msg);
986 44 : event.msgTypeData = typeData;
987 44 : 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
|