3 * This file defines a TransferSession state machine that contains the main logic governing a Bulk Data Transfer session. It
4 * provides APIs for starting a transfer or preparing to receive a transfer request, providing input to be processed, and
5 * accessing output data (including messages to be sent, message data received by the TransferSession, or state information).
10 #include <core/CHIPError.h>
11 #include <protocols/bdx/BdxMessages.h>
12 #include <system/SystemPacketBuffer.h>
13 #include <transport/raw/MessageHeader.h>
18 enum TransferRole : uint8_t
24 class DLL_EXPORT TransferSession
27 enum OutputEventType : uint16_t
42 struct TransferInitData
44 uint8_t TransferCtlFlagsRaw = 0;
46 uint16_t MaxBlockSize = 0;
47 uint64_t StartOffset = 0;
50 const uint8_t * FileDesignator = nullptr;
51 uint16_t FileDesLength = 0;
53 // Additional metadata (optional, TLV format)
54 const uint8_t * Metadata = nullptr;
55 uint16_t MetadataLength = 0;
58 struct TransferAcceptData
60 TransferControlFlags ControlMode;
62 uint16_t MaxBlockSize = 0;
63 uint64_t StartOffset = 0; ///< Not used for SendAccept message
64 uint64_t Length = 0; ///< Not used for SendAccept message
66 // Additional metadata (optional, TLV format)
67 const uint8_t * Metadata = nullptr;
68 uint16_t MetadataLength = 0;
71 struct StatusReportData
78 const uint8_t * Data = nullptr;
85 * All output data processed by the TransferSession object will be passed to the caller using this struct via PollOutput().
87 * NOTE: Some sub-structs may contain pointers to data in a PacketBuffer. In this case, the MsgData field MUST be populated
88 * with a PacketBufferHandle that encapsulates the respective PacketBuffer, in order to ensure valid memory access.
92 OutputEventType EventType;
93 System::PacketBufferHandle MsgData;
96 TransferInitData transferInitData;
97 TransferAcceptData transferAcceptData;
99 StatusReportData statusData;
102 OutputEvent() : EventType(kNone) { statusData = { kStatus_None }; }
103 OutputEvent(OutputEventType type) : EventType(type) { statusData = { kStatus_None }; }
105 static OutputEvent TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg);
106 static OutputEvent TransferAcceptEvent(TransferAcceptData data);
107 static OutputEvent TransferAcceptEvent(TransferAcceptData data, System::PacketBufferHandle msg);
108 static OutputEvent BlockDataEvent(BlockData data, System::PacketBufferHandle msg);
109 static OutputEvent StatusReportEvent(OutputEventType type, StatusReportData data);
114 * Indicates the presence of pending output and includes any data for the caller to take action on.
116 * This method should be called frequently in order to be notified about any messages received. It should also be called after
117 * most other methods in order to notify the user of any message that needs to be sent, or errors that occurred internally.
119 * It is possible that consecutive calls to this method may emit different outputs depending on the state of the
120 * TransferSession object.
122 * Note that if the type outputted is kMsgToSend, it is assumed that the message will be send immediately, and the
123 * session timeout timer will begin at curTimeMs.
125 * See OutputEventType for all possible output event types.
127 * @param event Reference to an OutputEvent struct that will be filled out with any pending output data
128 * @param curTimeMs Current time indicated by the number of milliseconds since some epoch defined by the platform
130 void PollOutput(OutputEvent & event, uint64_t curTimeMs);
134 * Initializes the TransferSession object and prepares a TransferInit message (emitted via PollOutput()).
136 * A TransferSession object must be initialized with either StartTransfer() or WaitForTransfer().
138 * @param role Inidcates whether this object will be sending or receiving data
139 * @param initData Data for initializing this object and for populating a TransferInit message
140 * The role parameter will determine whether to populate a ReceiveInit or SendInit
141 * @param timeoutMs The amount of time to wait for a response before considering the transfer failed (milliseconds)
142 * @param curTimeMs The current time since epoch in milliseconds. Needed to set a start time for the transfer timeout.
144 * @return CHIP_ERROR Result of initialization and preparation of a TransferInit message. May also indicate if the
145 * TransferSession object is unable to handle this request.
147 CHIP_ERROR StartTransfer(TransferRole role, const TransferInitData & initData, uint32_t timeoutMs);
151 * Initialize the TransferSession object and prepare to receive a TransferInit message at some point.
153 * A TransferSession object must be initialized with either StartTransfer() or WaitForTransfer().
155 * @param role Inidcates whether this object will be sending or receiving data
156 * @param xferControlOpts Indicates all supported control modes. Used to respond to a TransferInit message
157 * @param maxBlockSize The max Block size that this object supports.
158 * @param timeoutMs The amount of time to wait for a response before considering the transfer failed (milliseconds)
160 * @return CHIP_ERROR Result of initialization. May also indicate if the TransferSession object is unable to handle this
163 CHIP_ERROR WaitForTransfer(TransferRole role, BitFlags<uint8_t, TransferControlFlags> xferControlOpts, uint16_t maxBlockSize,
168 * Indicate that all transfer parameters are acceptable and prepare a SendAccept or ReceiveAccept message (depending on role).
170 * @param acceptData Data used to populate an Accept message (some fields may differ from the original Init message)
172 * @return CHIP_ERROR Result of preparation of an Accept message. May also indicate if the TransferSession object is unable to
173 * handle this request.
175 CHIP_ERROR AcceptTransfer(const TransferAcceptData & acceptData);
179 * Reject a TransferInit message. Use Reset() to prepare this object for another transfer.
181 * @param reason A StatusCode indicating the reason for rejecting the transfer
183 * @return CHIP_ERROR The result of the preparation of a StatusReport message. May also indicate if the TransferSession object
184 * is unable to handle this request.
186 CHIP_ERROR RejectTransfer(StatusCode reason);
190 * Prepare a BlockQuery message. The Block counter will be populated automatically.
192 * @return CHIP_ERROR The result of the preparation of a BlockQuery message. May also indicate if the TransferSession object
193 * is unable to handle this request.
195 CHIP_ERROR PrepareBlockQuery();
199 * Prepare a Block message. The Block counter will be populated automatically.
201 * @param inData Contains data for filling out the Block message
203 * @return CHIP_ERROR The result of the preparation of a Block message. May also indicate if the TransferSession object
204 * is unable to handle this request.
206 CHIP_ERROR PrepareBlock(const BlockData & inData);
210 * Prepare a BlockAck message. The Block counter will be populated automatically.
212 * @return CHIP_ERROR The result of the preparation of a BlockAck message. May also indicate if the TransferSession object
213 * is unable to handle this request.
215 CHIP_ERROR PrepareBlockAck();
219 * Prematurely end a transfer with a StatusReport. Must still call Reset() to prepare the TransferSession for another
222 * @param reason The StatusCode reason for ending the transfer.
224 * @return CHIP_ERROR May return an error if there is no transfer in progress.
226 CHIP_ERROR AbortTransfer(StatusCode reason);
230 * Reset all TransferSession parameters. The TransferSession object must then be re-initialized with StartTransfer() or
237 * Process a message intended for this TransferSession object.
239 * @param msg A PacketBufferHandle pointing to the message buffer to process. May be BDX or StatusReport protocol.
240 * @param curTimeMs Current time indicated by the number of milliseconds since some epoch defined by the platform
242 * @return CHIP_ERROR Indicates any problems in decoding the message, or if the message is not of the BDX or StatusReport
245 CHIP_ERROR HandleMessageReceived(System::PacketBufferHandle msg, uint64_t curTimeMs);
247 TransferControlFlags GetControlMode() const { return mControlMode; }
248 uint64_t GetStartOffset() const { return mStartOffset; }
249 uint64_t GetTransferLength() const { return mTransferLength; }
250 uint16_t GetTransferBlockSize() const { return mTransferMaxBlockSize; }
255 enum TransferState : uint8_t
260 kNegotiateTransferParams,
268 // Incoming message handlers
269 CHIP_ERROR HandleBdxMessage(PayloadHeader & header, System::PacketBufferHandle msg);
270 CHIP_ERROR HandleStatusReportMessage(PayloadHeader & header, System::PacketBufferHandle msg);
271 void HandleTransferInit(MessageType msgType, System::PacketBufferHandle msgData);
272 void HandleReceiveAccept(System::PacketBufferHandle msgData);
273 void HandleSendAccept(System::PacketBufferHandle msgData);
274 void HandleBlockQuery(System::PacketBufferHandle msgData);
275 void HandleBlock(System::PacketBufferHandle msgData);
276 void HandleBlockEOF(System::PacketBufferHandle msgData);
277 void HandleBlockAck(System::PacketBufferHandle msgData);
278 void HandleBlockAckEOF(System::PacketBufferHandle msgData);
282 * Used when handling a TransferInit message. Determines if there are any compatible Transfer control modes between the two
285 void ResolveTransferControlOptions(const BitFlags<uint8_t, TransferControlFlags> & proposed);
289 * Used when handling an Accept message. Verifies that the chosen control mode is compatible with the orignal supported modes.
291 CHIP_ERROR VerifyProposedMode(const BitFlags<uint8_t, TransferControlFlags> & proposed);
293 void PrepareStatusReport(StatusCode code);
294 bool IsTransferLengthDefinite();
296 OutputEventType mPendingOutput = kNone;
297 TransferState mState = kUnitialized;
300 // Indicate supported options pre- transfer accept
301 BitFlags<uint8_t, TransferControlFlags> mSuppportedXferOpts;
302 uint16_t mMaxSupportedBlockSize = 0;
304 // Used to govern transfer once it has been accepted
305 TransferControlFlags mControlMode;
306 uint8_t mTransferVersion = 0;
307 uint64_t mStartOffset = 0; ///< 0 represents no offset
308 uint64_t mTransferLength = 0; ///< 0 represents indefinite length
309 uint16_t mTransferMaxBlockSize = 0;
311 System::PacketBufferHandle mPendingMsgHandle;
312 StatusReportData mStatusReportData;
313 TransferInitData mTransferRequestData;
314 TransferAcceptData mTransferAcceptData;
315 BlockData mBlockEventData;
317 uint32_t mNumBytesProcessed = 0;
319 uint32_t mLastBlockNum = 0;
320 uint32_t mNextBlockNum = 0;
321 uint32_t mLastQueryNum = 0;
322 uint32_t mNextQueryNum = 0;
324 uint32_t mTimeoutMs = 0;
325 uint64_t mTimeoutStartTimeMs = 0;
326 bool mShouldInitTimeoutStart = true;
327 bool mAwaitingResponse = false;