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