xref: /aosp_15_r20/external/pigweed/pw_transfer/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker===========
4*61c4878aSAndroid Build Coastguard Workerpw_transfer
5*61c4878aSAndroid Build Coastguard Worker===========
6*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` is a reliable data transfer protocol which runs on top of
7*61c4878aSAndroid Build Coastguard WorkerPigweed RPC.
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker.. attention::
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker  ``pw_transfer`` is under construction and so is its documentation.
12*61c4878aSAndroid Build Coastguard Worker
13*61c4878aSAndroid Build Coastguard Worker-----
14*61c4878aSAndroid Build Coastguard WorkerUsage
15*61c4878aSAndroid Build Coastguard Worker-----
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard WorkerC++
18*61c4878aSAndroid Build Coastguard Worker===
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard WorkerTransfer thread
21*61c4878aSAndroid Build Coastguard Worker---------------
22*61c4878aSAndroid Build Coastguard WorkerTo run transfers as either a client or server (or both), a dedicated thread is
23*61c4878aSAndroid Build Coastguard Workerrequired. The transfer thread is used to process all transfer-related events
24*61c4878aSAndroid Build Coastguard Workersafely. The same transfer thread can be shared by a transfer client and service
25*61c4878aSAndroid Build Coastguard Workerrunning on the same system.
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker.. note::
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard Worker   All user-defined transfer callbacks (i.e. the virtual interface of a
30*61c4878aSAndroid Build Coastguard Worker   ``Handler`` or completion function in a transfer client) will be
31*61c4878aSAndroid Build Coastguard Worker   invoked from the transfer thread's context.
32*61c4878aSAndroid Build Coastguard Worker
33*61c4878aSAndroid Build Coastguard WorkerIn order to operate, a transfer thread requires two buffers:
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker- The first is a *chunk buffer*. This is used to stage transfer packets received
36*61c4878aSAndroid Build Coastguard Worker  by the RPC system to be processed by the transfer thread. It must be large
37*61c4878aSAndroid Build Coastguard Worker  enough to store the largest possible chunk the system supports.
38*61c4878aSAndroid Build Coastguard Worker
39*61c4878aSAndroid Build Coastguard Worker- The second is an *encode buffer*. This is used by the transfer thread to
40*61c4878aSAndroid Build Coastguard Worker  encode outgoing RPC packets. It is necessarily larger than the chunk buffer.
41*61c4878aSAndroid Build Coastguard Worker  Typically, this is sized to the system's maximum transmission unit at the
42*61c4878aSAndroid Build Coastguard Worker  transport layer.
43*61c4878aSAndroid Build Coastguard Worker
44*61c4878aSAndroid Build Coastguard WorkerA transfer thread is created by instantiating a ``pw::transfer::Thread``. This
45*61c4878aSAndroid Build Coastguard Workerclass derives from ``pw::thread::ThreadCore``, allowing it to directly be used
46*61c4878aSAndroid Build Coastguard Workerwhen creating a system thread. Refer to :ref:`module-pw_thread-thread-creation`
47*61c4878aSAndroid Build Coastguard Workerfor additional information.
48*61c4878aSAndroid Build Coastguard Worker
49*61c4878aSAndroid Build Coastguard Worker**Example thread configuration**
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
52*61c4878aSAndroid Build Coastguard Worker
53*61c4878aSAndroid Build Coastguard Worker   #include "pw_transfer/transfer_thread.h"
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker   namespace {
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker   // The maximum number of concurrent transfers the thread should support as
58*61c4878aSAndroid Build Coastguard Worker   // either a client or a server. These can be set to 0 (if only using one or
59*61c4878aSAndroid Build Coastguard Worker   // the other).
60*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxConcurrentClientTransfers = 5;
61*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxConcurrentServerTransfers = 3;
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker   // The maximum payload size that can be transmitted by the system's
64*61c4878aSAndroid Build Coastguard Worker   // transport stack. This would typically be defined within some transport
65*61c4878aSAndroid Build Coastguard Worker   // header.
66*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxTransmissionUnit = 512;
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker   // The maximum amount of data that should be sent within a single transfer
69*61c4878aSAndroid Build Coastguard Worker   // packet. By necessity, this should be less than the max transmission unit.
70*61c4878aSAndroid Build Coastguard Worker   //
71*61c4878aSAndroid Build Coastguard Worker   // pw_transfer requires some additional per-packet overhead, so the actual
72*61c4878aSAndroid Build Coastguard Worker   // amount of data it sends may be lower than this.
73*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxTransferChunkSizeBytes = 480;
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard Worker   // Buffers for storing and encoding chunks (see documentation above).
76*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kMaxTransferChunkSizeBytes> chunk_buffer;
77*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kMaxTransmissionUnit> encode_buffer;
78*61c4878aSAndroid Build Coastguard Worker
79*61c4878aSAndroid Build Coastguard Worker   pw::transfer::Thread<kMaxConcurrentClientTransfers,
80*61c4878aSAndroid Build Coastguard Worker                        kMaxConcurrentServerTransfers>
81*61c4878aSAndroid Build Coastguard Worker       transfer_thread(chunk_buffer, encode_buffer);
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard Worker   }  // namespace
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker   // pw::transfer::TransferThread is the generic, non-templated version of the
86*61c4878aSAndroid Build Coastguard Worker   // Thread class. A Thread can implicitly convert to a TransferThread.
87*61c4878aSAndroid Build Coastguard Worker   pw::transfer::TransferThread& GetSystemTransferThread() {
88*61c4878aSAndroid Build Coastguard Worker     return transfer_thread;
89*61c4878aSAndroid Build Coastguard Worker   }
90*61c4878aSAndroid Build Coastguard Worker
91*61c4878aSAndroid Build Coastguard Worker.. _pw_transfer-transfer-server:
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard WorkerTransfer server
94*61c4878aSAndroid Build Coastguard Worker---------------
95*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` provides an RPC service for running transfers through an RPC
96*61c4878aSAndroid Build Coastguard Workerserver.
97*61c4878aSAndroid Build Coastguard Worker
98*61c4878aSAndroid Build Coastguard WorkerTo know how to read data from or write data to device, a ``Handler`` interface
99*61c4878aSAndroid Build Coastguard Workeris defined (``pw_transfer/public/pw_transfer/handler.h``). Transfer handlers
100*61c4878aSAndroid Build Coastguard Workerrepresent a transferable resource, wrapping a stream reader and/or writer with
101*61c4878aSAndroid Build Coastguard Workerinitialization and completion code. Custom transfer handler implementations
102*61c4878aSAndroid Build Coastguard Workershould derive from ``ReadOnlyHandler``, ``WriteOnlyHandler``, or
103*61c4878aSAndroid Build Coastguard Worker``ReadWriteHandler`` as appropriate and override Prepare and Finalize methods
104*61c4878aSAndroid Build Coastguard Workerif necessary.
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard WorkerA transfer handler should be implemented and instantiated for each unique
107*61c4878aSAndroid Build Coastguard Workerresource that can be transferred to or from a device. Each instantiated handler
108*61c4878aSAndroid Build Coastguard Workermust have a globally-unique integer ID used to identify the resource.
109*61c4878aSAndroid Build Coastguard Worker
110*61c4878aSAndroid Build Coastguard WorkerHandlers are registered with the transfer service. This may be done during
111*61c4878aSAndroid Build Coastguard Workersystem initialization (for static resources), or dynamically at runtime to
112*61c4878aSAndroid Build Coastguard Workersupport ephemeral transfer resources. A boolean is returned with registration/
113*61c4878aSAndroid Build Coastguard Workerunregistration to indicate success or failure.
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker**Example transfer handler implementation**
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard Worker   #include "pw_stream/memory_stream.h"
120*61c4878aSAndroid Build Coastguard Worker   #include "pw_transfer/transfer.h"
121*61c4878aSAndroid Build Coastguard Worker
122*61c4878aSAndroid Build Coastguard Worker   // A simple transfer handler which reads data from an in-memory buffer.
123*61c4878aSAndroid Build Coastguard Worker   class SimpleBufferReadHandler : public pw::transfer::ReadOnlyHandler {
124*61c4878aSAndroid Build Coastguard Worker    public:
125*61c4878aSAndroid Build Coastguard Worker     SimpleReadTransfer(uint32_t resource_id, pw::ConstByteSpan data)
126*61c4878aSAndroid Build Coastguard Worker         : ReadOnlyHandler(resource_id), reader_(data) {
127*61c4878aSAndroid Build Coastguard Worker       set_reader(reader_);
128*61c4878aSAndroid Build Coastguard Worker     }
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker    private:
131*61c4878aSAndroid Build Coastguard Worker     pw::stream::MemoryReader reader_;
132*61c4878aSAndroid Build Coastguard Worker   };
133*61c4878aSAndroid Build Coastguard Worker
134*61c4878aSAndroid Build Coastguard WorkerHandlers may optionally implement a `GetStatus` method, which allows clients to
135*61c4878aSAndroid Build Coastguard Workerquery the status of a resource with a handler registered. The application layer
136*61c4878aSAndroid Build Coastguard Workerabove transfer can choose how to fill and interpret this information. The status
137*61c4878aSAndroid Build Coastguard Workerinformation is `readable_offset`, `writeable_offset`, `read_checksum`, and
138*61c4878aSAndroid Build Coastguard Worker`write_checksum`.
139*61c4878aSAndroid Build Coastguard Worker
140*61c4878aSAndroid Build Coastguard Worker**Example GetStatus implementation**
141*61c4878aSAndroid Build Coastguard Worker
142*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard Worker   Status GetStatus(uint64_t& readable_offset,
145*61c4878aSAndroid Build Coastguard Worker                    uint64_t& writeable_offset,
146*61c4878aSAndroid Build Coastguard Worker                    uint64_t& read_checksum,
147*61c4878aSAndroid Build Coastguard Worker                    uint64_t& write_checksum) {
148*61c4878aSAndroid Build Coastguard Worker     readable_offset = resource.get_size();
149*61c4878aSAndroid Build Coastguard Worker     writeable_offset = resource.get_writeable_offset();
150*61c4878aSAndroid Build Coastguard Worker     read_checksum = resource.get_crc();
151*61c4878aSAndroid Build Coastguard Worker     write_checksum = resource.calculate_crc(0, writeable_offset);
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
154*61c4878aSAndroid Build Coastguard Worker   }
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard WorkerThe transfer service is instantiated with a reference to the system's transfer
157*61c4878aSAndroid Build Coastguard Workerthread and registered with the system's RPC server.
158*61c4878aSAndroid Build Coastguard Worker
159*61c4878aSAndroid Build Coastguard Worker**Example transfer service initialization**
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard Worker   #include "pw_transfer/transfer.h"
164*61c4878aSAndroid Build Coastguard Worker
165*61c4878aSAndroid Build Coastguard Worker   namespace {
166*61c4878aSAndroid Build Coastguard Worker
167*61c4878aSAndroid Build Coastguard Worker   // In a write transfer, the maximum number of bytes to receive at one time
168*61c4878aSAndroid Build Coastguard Worker   // (potentially across multiple chunks), unless specified otherwise by the
169*61c4878aSAndroid Build Coastguard Worker   // transfer handler's stream::Writer. Should be set reasonably high; the
170*61c4878aSAndroid Build Coastguard Worker   // transfer will attempt to determine an optimal window size based on the
171*61c4878aSAndroid Build Coastguard Worker   // link.
172*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kDefaultMaxBytesToReceive = 16384;
173*61c4878aSAndroid Build Coastguard Worker
174*61c4878aSAndroid Build Coastguard Worker   pw::transfer::TransferService transfer_service(
175*61c4878aSAndroid Build Coastguard Worker       GetSystemTransferThread(), kDefaultMaxBytesToReceive);
176*61c4878aSAndroid Build Coastguard Worker
177*61c4878aSAndroid Build Coastguard Worker   // Instantiate a handler for the data to be transferred. The resource ID will
178*61c4878aSAndroid Build Coastguard Worker   // be used by the transfer client and server to identify the handler.
179*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t kMagicBufferResourceId = 1;
180*61c4878aSAndroid Build Coastguard Worker   char magic_buffer_to_transfer[256] = { /* ... */ };
181*61c4878aSAndroid Build Coastguard Worker   SimpleBufferReadHandler magic_buffer_handler(
182*61c4878aSAndroid Build Coastguard Worker       kMagicBufferResourceId, magic_buffer_to_transfer);
183*61c4878aSAndroid Build Coastguard Worker
184*61c4878aSAndroid Build Coastguard Worker   }  // namespace
185*61c4878aSAndroid Build Coastguard Worker
186*61c4878aSAndroid Build Coastguard Worker   void InitTransferService() {
187*61c4878aSAndroid Build Coastguard Worker     // Register the handler with the transfer service, then the transfer service
188*61c4878aSAndroid Build Coastguard Worker     // with an RPC server.
189*61c4878aSAndroid Build Coastguard Worker     bool success = transfer_service.RegisterHandler(magic_buffer_handler);
190*61c4878aSAndroid Build Coastguard Worker     GetSystemRpcServer().RegisterService(transfer_service);
191*61c4878aSAndroid Build Coastguard Worker   }
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard WorkerTransfer client
194*61c4878aSAndroid Build Coastguard Worker---------------
195*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` provides a transfer client capable of running transfers through
196*61c4878aSAndroid Build Coastguard Workeran RPC client.
197*61c4878aSAndroid Build Coastguard Worker
198*61c4878aSAndroid Build Coastguard Worker.. note::
199*61c4878aSAndroid Build Coastguard Worker
200*61c4878aSAndroid Build Coastguard Worker   Currently, a transfer client is only capable of running transfers on a single
201*61c4878aSAndroid Build Coastguard Worker   RPC channel. This may be expanded in the future.
202*61c4878aSAndroid Build Coastguard Worker
203*61c4878aSAndroid Build Coastguard WorkerThe transfer client provides the following APIs for managing data transfers:
204*61c4878aSAndroid Build Coastguard Worker
205*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<pw::Transfer::Client::Handle> pw::transfer::Client::Read(uint32_t resource_id, pw::stream::Writer& output, CompletionFunc&& on_completion, pw::transfer::ProtocolVersion version = kDefaultProtocolVersion, pw::chrono::SystemClock::duration timeout = cfg::kDefaultClientTimeout, pw::chrono::SystemClock::duration initial_chunk_timeout = cfg::kDefaultInitialChunkTimeout, uint32_t initial_offset = 0u)
206*61c4878aSAndroid Build Coastguard Worker
207*61c4878aSAndroid Build Coastguard Worker  Reads data from a transfer server to the specified ``pw::stream::Writer``.
208*61c4878aSAndroid Build Coastguard Worker  Invokes the provided callback function with the overall status of the
209*61c4878aSAndroid Build Coastguard Worker  transfer.
210*61c4878aSAndroid Build Coastguard Worker
211*61c4878aSAndroid Build Coastguard Worker  Due to the asynchronous nature of transfer operations, this function will only
212*61c4878aSAndroid Build Coastguard Worker  return a non-OK status if it is called with bad arguments. Otherwise, it will
213*61c4878aSAndroid Build Coastguard Worker  return OK and errors will be reported through the completion callback.
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard Worker  For using the offset parameter, please see :ref:`pw_transfer-nonzero-transfers`.
216*61c4878aSAndroid Build Coastguard Worker
217*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<pw::Transfer::Client::Handle> pw::transfer::Client::Write(uint32_t resource_id, pw::stream::Reader& input, CompletionFunc&& on_completion, pw::transfer::ProtocolVersion version = kDefaultProtocolVersion, pw::chrono::SystemClock::duration timeout = cfg::kDefaultClientTimeout, pw::chrono::SystemClock::duration initial_chunk_timeout = cfg::kDefaultInitialChunkTimeout, uint32_t initial_offset = 0u)
218*61c4878aSAndroid Build Coastguard Worker
219*61c4878aSAndroid Build Coastguard Worker  Writes data from a source ``pw::stream::Reader`` to a transfer server.
220*61c4878aSAndroid Build Coastguard Worker  Invokes the provided callback function with the overall status of the
221*61c4878aSAndroid Build Coastguard Worker  transfer.
222*61c4878aSAndroid Build Coastguard Worker
223*61c4878aSAndroid Build Coastguard Worker  Due to the asynchronous nature of transfer operations, this function will only
224*61c4878aSAndroid Build Coastguard Worker  return a non-OK status if it is called with bad arguments. Otherwise, it will
225*61c4878aSAndroid Build Coastguard Worker  return OK and errors will be reported through the completion callback.
226*61c4878aSAndroid Build Coastguard Worker
227*61c4878aSAndroid Build Coastguard Worker  For using the offset parameter, please see :ref:`pw_transfer-nonzero-transfers`.
228*61c4878aSAndroid Build Coastguard Worker
229*61c4878aSAndroid Build Coastguard WorkerTransfer handles
230*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^
231*61c4878aSAndroid Build Coastguard WorkerEach transfer session initiated by a client returns a ``Handle`` object which
232*61c4878aSAndroid Build Coastguard Workeris used to manage the transfer. These handles support the following operations:
233*61c4878aSAndroid Build Coastguard Worker
234*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::Transfer::Client::Handle::Cancel()
235*61c4878aSAndroid Build Coastguard Worker
236*61c4878aSAndroid Build Coastguard Worker   Terminates the ongoing transfer.
237*61c4878aSAndroid Build Coastguard Worker
238*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::Transfer::Client::Handle::SetTransferSize(size_t size_bytes)
239*61c4878aSAndroid Build Coastguard Worker
240*61c4878aSAndroid Build Coastguard Worker   In a write transfer, indicates the total size of the transfer resource.
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker**Example client setup**
243*61c4878aSAndroid Build Coastguard Worker
244*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
245*61c4878aSAndroid Build Coastguard Worker
246*61c4878aSAndroid Build Coastguard Worker   #include "pw_transfer/client.h"
247*61c4878aSAndroid Build Coastguard Worker
248*61c4878aSAndroid Build Coastguard Worker   namespace {
249*61c4878aSAndroid Build Coastguard Worker
250*61c4878aSAndroid Build Coastguard Worker   // RPC channel on which transfers should be run.
251*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t kChannelId = 42;
252*61c4878aSAndroid Build Coastguard Worker
253*61c4878aSAndroid Build Coastguard Worker   // In a read transfer, the maximum number of bytes to receive at one time
254*61c4878aSAndroid Build Coastguard Worker   // (potentially across multiple chunks), unless specified otherwise by the
255*61c4878aSAndroid Build Coastguard Worker   // transfer's stream. Should be set reasonably high; the transfer will
256*61c4878aSAndroid Build Coastguard Worker   // attempt to determine an optimal window size based on the link.
257*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kDefaultMaxBytesToReceive = 16384;
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker   pw::transfer::Client transfer_client(GetSystemRpcClient(),
260*61c4878aSAndroid Build Coastguard Worker                                        kChannelId,
261*61c4878aSAndroid Build Coastguard Worker                                        GetSystemTransferThread(),
262*61c4878aSAndroid Build Coastguard Worker                                        kDefaultMaxBytesToReceive);
263*61c4878aSAndroid Build Coastguard Worker
264*61c4878aSAndroid Build Coastguard Worker   }  // namespace
265*61c4878aSAndroid Build Coastguard Worker
266*61c4878aSAndroid Build Coastguard Worker   Status ReadMagicBufferSync(pw::ByteSpan sink) {
267*61c4878aSAndroid Build Coastguard Worker     pw::stream::Writer writer(sink);
268*61c4878aSAndroid Build Coastguard Worker
269*61c4878aSAndroid Build Coastguard Worker     struct {
270*61c4878aSAndroid Build Coastguard Worker       pw::sync::ThreadNotification notification;
271*61c4878aSAndroid Build Coastguard Worker       pw::Status status;
272*61c4878aSAndroid Build Coastguard Worker     } transfer_state;
273*61c4878aSAndroid Build Coastguard Worker
274*61c4878aSAndroid Build Coastguard Worker     Result<pw::transfer::Client::Handle> handle = transfer_client.Read(
275*61c4878aSAndroid Build Coastguard Worker         kMagicBufferResourceId,
276*61c4878aSAndroid Build Coastguard Worker         writer,
277*61c4878aSAndroid Build Coastguard Worker         [&transfer_state](pw::Status status) {
278*61c4878aSAndroid Build Coastguard Worker           transfer_state.status = status;
279*61c4878aSAndroid Build Coastguard Worker           transfer_state.notification.release();
280*61c4878aSAndroid Build Coastguard Worker         });
281*61c4878aSAndroid Build Coastguard Worker     if (!handle.ok()) {
282*61c4878aSAndroid Build Coastguard Worker       return handle.status();
283*61c4878aSAndroid Build Coastguard Worker     }
284*61c4878aSAndroid Build Coastguard Worker
285*61c4878aSAndroid Build Coastguard Worker     // Block until the transfer completes.
286*61c4878aSAndroid Build Coastguard Worker     transfer_state.notification.acquire();
287*61c4878aSAndroid Build Coastguard Worker     return transfer_state.status;
288*61c4878aSAndroid Build Coastguard Worker   }
289*61c4878aSAndroid Build Coastguard Worker
290*61c4878aSAndroid Build Coastguard WorkerSpecifying Resource Sizes
291*61c4878aSAndroid Build Coastguard Worker-------------------------
292*61c4878aSAndroid Build Coastguard WorkerTransfer data is sent and received through the ``pw::Stream`` interface, which
293*61c4878aSAndroid Build Coastguard Workerdoes not have a concept of overall stream size. Users of transfers that are
294*61c4878aSAndroid Build Coastguard Workerfixed-size may optionally indicate this to the transfer client and server,
295*61c4878aSAndroid Build Coastguard Workerwhich will be shared with the transfer peer to enable features such as progress
296*61c4878aSAndroid Build Coastguard Workerreporting.
297*61c4878aSAndroid Build Coastguard Worker
298*61c4878aSAndroid Build Coastguard WorkerThe transfer size can only be set on the transmitting side of the transfer;
299*61c4878aSAndroid Build Coastguard Workerthat is, the client in a ``Write`` transfer or the server in a ``Read``
300*61c4878aSAndroid Build Coastguard Workertransfer.
301*61c4878aSAndroid Build Coastguard Worker
302*61c4878aSAndroid Build Coastguard WorkerIf the specified resource size is smaller than the available transferrable data,
303*61c4878aSAndroid Build Coastguard Workeronly a slice of the data up to the resource size will be transferred. If the
304*61c4878aSAndroid Build Coastguard Workerspecified size is equal to or larger than the data size, all of the data will
305*61c4878aSAndroid Build Coastguard Workerbe sent.
306*61c4878aSAndroid Build Coastguard Worker
307*61c4878aSAndroid Build Coastguard Worker**Setting a transfer size from a transmitting client**
308*61c4878aSAndroid Build Coastguard Worker
309*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
310*61c4878aSAndroid Build Coastguard Worker
311*61c4878aSAndroid Build Coastguard Worker   Result<pw::transfer::Client::Handle> handle = client.Write(...);
312*61c4878aSAndroid Build Coastguard Worker   if (handle.ok()) {
313*61c4878aSAndroid Build Coastguard Worker     handle->SetTransferSize(kMyResourceSize);
314*61c4878aSAndroid Build Coastguard Worker   }
315*61c4878aSAndroid Build Coastguard Worker
316*61c4878aSAndroid Build Coastguard Worker**Setting a transfer size on a server resource**
317*61c4878aSAndroid Build Coastguard Worker
318*61c4878aSAndroid Build Coastguard Worker  The ``TransferHandler`` interface allows overriding its ``ResourceSize``
319*61c4878aSAndroid Build Coastguard Worker  function to return the size of its transfer resource.
320*61c4878aSAndroid Build Coastguard Worker
321*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
322*61c4878aSAndroid Build Coastguard Worker
323*61c4878aSAndroid Build Coastguard Worker   class MyResourceHandler : public pw::transfer::ReadOnlyHandler {
324*61c4878aSAndroid Build Coastguard Worker    public:
325*61c4878aSAndroid Build Coastguard Worker     Status PrepareRead() final;
326*61c4878aSAndroid Build Coastguard Worker
327*61c4878aSAndroid Build Coastguard Worker     virtual size_t ResourceSize() const final {
328*61c4878aSAndroid Build Coastguard Worker       return kMyResourceSize;
329*61c4878aSAndroid Build Coastguard Worker     }
330*61c4878aSAndroid Build Coastguard Worker
331*61c4878aSAndroid Build Coastguard Worker  };
332*61c4878aSAndroid Build Coastguard Worker
333*61c4878aSAndroid Build Coastguard WorkerAtomic File Transfer Handler
334*61c4878aSAndroid Build Coastguard Worker----------------------------
335*61c4878aSAndroid Build Coastguard WorkerTransfers are handled using the generic `Handler` interface. A specialized
336*61c4878aSAndroid Build Coastguard Worker`Handler`, `AtomicFileTransferHandler` is available to handle file transfers
337*61c4878aSAndroid Build Coastguard Workerwith atomic semantics. It guarantees that the target file of the transfer is
338*61c4878aSAndroid Build Coastguard Workeralways in a correct state. A temporary file is written to prior to updating the
339*61c4878aSAndroid Build Coastguard Workertarget file. If any transfer failure occurs, the transfer is aborted and the
340*61c4878aSAndroid Build Coastguard Workertarget file is either not created or not updated.
341*61c4878aSAndroid Build Coastguard Worker
342*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer-config:
343*61c4878aSAndroid Build Coastguard Worker
344*61c4878aSAndroid Build Coastguard WorkerModule Configuration Options
345*61c4878aSAndroid Build Coastguard Worker----------------------------
346*61c4878aSAndroid Build Coastguard WorkerThe following configurations can be adjusted via compile-time configuration of
347*61c4878aSAndroid Build Coastguard Workerthis module, see the
348*61c4878aSAndroid Build Coastguard Worker:ref:`module documentation <module-structure-compile-time-configuration>` for
349*61c4878aSAndroid Build Coastguard Workermore details.
350*61c4878aSAndroid Build Coastguard Worker
351*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES
352*61c4878aSAndroid Build Coastguard Worker
353*61c4878aSAndroid Build Coastguard Worker  The default maximum number of times a transfer client should retry sending a
354*61c4878aSAndroid Build Coastguard Worker  chunk when no response is received. Can later be configured per-transfer when
355*61c4878aSAndroid Build Coastguard Worker  starting one.
356*61c4878aSAndroid Build Coastguard Worker
357*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES
358*61c4878aSAndroid Build Coastguard Worker
359*61c4878aSAndroid Build Coastguard Worker  The default maximum number of times a transfer server should retry sending a
360*61c4878aSAndroid Build Coastguard Worker  chunk when no response is received.
361*61c4878aSAndroid Build Coastguard Worker
362*61c4878aSAndroid Build Coastguard Worker  In typical setups, retries are driven by the client, and timeouts on the
363*61c4878aSAndroid Build Coastguard Worker  server are used only to clean up resources, so this defaults to 0.
364*61c4878aSAndroid Build Coastguard Worker
365*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES
366*61c4878aSAndroid Build Coastguard Worker
367*61c4878aSAndroid Build Coastguard Worker  The default maximum number of times a transfer should retry sending any chunk
368*61c4878aSAndroid Build Coastguard Worker  over the course of its entire lifetime.
369*61c4878aSAndroid Build Coastguard Worker
370*61c4878aSAndroid Build Coastguard Worker  This number should be high, particularly if long-running transfers are
371*61c4878aSAndroid Build Coastguard Worker  expected. Its purpose is to prevent transfers from getting stuck in an
372*61c4878aSAndroid Build Coastguard Worker  infinite loop.
373*61c4878aSAndroid Build Coastguard Worker
374*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS
375*61c4878aSAndroid Build Coastguard Worker
376*61c4878aSAndroid Build Coastguard Worker  The default amount of time, in milliseconds, to wait for a chunk to arrive
377*61c4878aSAndroid Build Coastguard Worker  in a transfer client before retrying. This can later be configured
378*61c4878aSAndroid Build Coastguard Worker  per-transfer.
379*61c4878aSAndroid Build Coastguard Worker
380*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS
381*61c4878aSAndroid Build Coastguard Worker
382*61c4878aSAndroid Build Coastguard Worker  The default amount of time, in milliseconds, to wait for a chunk to arrive
383*61c4878aSAndroid Build Coastguard Worker  on the server before retrying. This can later be configured per-transfer.
384*61c4878aSAndroid Build Coastguard Worker
385*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS
386*61c4878aSAndroid Build Coastguard Worker
387*61c4878aSAndroid Build Coastguard Worker  The default amount of time, in milliseconds, to wait for an initial server
388*61c4878aSAndroid Build Coastguard Worker  response to a transfer before retrying. This can later be configured
389*61c4878aSAndroid Build Coastguard Worker  per-transfer.
390*61c4878aSAndroid Build Coastguard Worker
391*61c4878aSAndroid Build Coastguard Worker  This is set separately to PW_TRANSFER_DEFAULT_TIMEOUT_MS as transfers may
392*61c4878aSAndroid Build Coastguard Worker  require additional time for resource initialization (e.g. erasing a flash
393*61c4878aSAndroid Build Coastguard Worker  region before writing to it).
394*61c4878aSAndroid Build Coastguard Worker
395*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard Worker  The fractional position within a window at which a receive transfer should
398*61c4878aSAndroid Build Coastguard Worker  extend its window size to minimize the amount of time the transmitter
399*61c4878aSAndroid Build Coastguard Worker  spends blocked.
400*61c4878aSAndroid Build Coastguard Worker
401*61c4878aSAndroid Build Coastguard Worker  For example, a divisor of 2 will extend the window when half of the
402*61c4878aSAndroid Build Coastguard Worker  requested data has been received, a divisor of three will extend at a third
403*61c4878aSAndroid Build Coastguard Worker  of the window, and so on.
404*61c4878aSAndroid Build Coastguard Worker
405*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT
406*61c4878aSAndroid Build Coastguard Worker
407*61c4878aSAndroid Build Coastguard Worker  Number of chunks to send repetitive logs at full rate before reducing to
408*61c4878aSAndroid Build Coastguard Worker  rate_limit. Retransmit parameter chunks will restart at this chunk count
409*61c4878aSAndroid Build Coastguard Worker  limit.
410*61c4878aSAndroid Build Coastguard Worker  Default is first 10 parameter logs will be sent, then reduced to one log
411*61c4878aSAndroid Build Coastguard Worker  every ``PW_TRANSFER_RATE_PERIOD_MS``
412*61c4878aSAndroid Build Coastguard Worker
413*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_LOG_DEFAULT_RATE_PERIOD_MS
414*61c4878aSAndroid Build Coastguard Worker
415*61c4878aSAndroid Build Coastguard Worker  The minimum time between repetative logs after the rate limit has been
416*61c4878aSAndroid Build Coastguard Worker  applied (after CHUNKS_BEFORE_RATE_LIMIT parameter chunks).
417*61c4878aSAndroid Build Coastguard Worker  Default is to reduce repetative logs to once every 10 seconds after
418*61c4878aSAndroid Build Coastguard Worker  CHUNKS_BEFORE_RATE_LIMIT parameter chunks have been sent.
419*61c4878aSAndroid Build Coastguard Worker
420*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_CONFIG_LOG_LEVEL
421*61c4878aSAndroid Build Coastguard Worker
422*61c4878aSAndroid Build Coastguard Worker  Configurable log level for the entire transfer module.
423*61c4878aSAndroid Build Coastguard Worker
424*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_CONFIG_DEBUG_CHUNKS
425*61c4878aSAndroid Build Coastguard Worker
426*61c4878aSAndroid Build Coastguard Worker  Turns on logging of individual non-data or non-parameter chunks. Default is
427*61c4878aSAndroid Build Coastguard Worker  false, to disable logging.
428*61c4878aSAndroid Build Coastguard Worker
429*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_CONFIG_DEBUG_DATA_CHUNKS
430*61c4878aSAndroid Build Coastguard Worker
431*61c4878aSAndroid Build Coastguard Worker  Turns on logging of individual data and parameter chunks. Default is false to
432*61c4878aSAndroid Build Coastguard Worker  disable logging. These chunks are moderated (rate-limited) by the same
433*61c4878aSAndroid Build Coastguard Worker  ``PW_TRANSFER_RATE_PERIOD_MS`` as other repetitive logs.
434*61c4878aSAndroid Build Coastguard Worker
435*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS
436*61c4878aSAndroid Build Coastguard Worker
437*61c4878aSAndroid Build Coastguard Worker   Maximum time to wait for a transfer event to be processed before dropping
438*61c4878aSAndroid Build Coastguard Worker   further queued events. In systems which can perform long-running operations
439*61c4878aSAndroid Build Coastguard Worker   to process transfer data, this can be used to prevent threads from blocking
440*61c4878aSAndroid Build Coastguard Worker   for extended periods. A value of 0 results in indefinite blocking.
441*61c4878aSAndroid Build Coastguard Worker
442*61c4878aSAndroid Build Coastguard Worker.. _pw_transfer-nonzero-transfers:
443*61c4878aSAndroid Build Coastguard Worker
444*61c4878aSAndroid Build Coastguard WorkerNon-zero Starting Offset Transfers
445*61c4878aSAndroid Build Coastguard Worker----------------------------------
446*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` provides for transfers which read from or
447*61c4878aSAndroid Build Coastguard Workerwrite to a server resource starting from a point after the beginning.
448*61c4878aSAndroid Build Coastguard WorkerHandling of read/write/erase boundaries of the resource storage backend must
449*61c4878aSAndroid Build Coastguard Workerbe handled by the user through the transfer handler interfaces of `GetStatus`
450*61c4878aSAndroid Build Coastguard Workerand `PrepareRead/Write(uint32_t offset)`.
451*61c4878aSAndroid Build Coastguard Worker
452*61c4878aSAndroid Build Coastguard WorkerA resource can be read or written from a non-zero starting offset simply by
453*61c4878aSAndroid Build Coastguard Workerhaving the transfer client calling `read()` or `write()` with an offset
454*61c4878aSAndroid Build Coastguard Workerparameter. The offset gets included in the starting handshake.
455*61c4878aSAndroid Build Coastguard Worker
456*61c4878aSAndroid Build Coastguard Worker.. note::
457*61c4878aSAndroid Build Coastguard Worker  The data or stream passed to `read()` or `write()` will be used as-is. I.e.
458*61c4878aSAndroid Build Coastguard Worker  no seeking will be applied; the user is expected to seek to the desired
459*61c4878aSAndroid Build Coastguard Worker  location.
460*61c4878aSAndroid Build Coastguard Worker
461*61c4878aSAndroid Build Coastguard WorkerOn the server side, the offset is accepted, and passed to the transfer
462*61c4878aSAndroid Build Coastguard Workerhandler's `Prepare(uint32_t)` method. This method must be implemented
463*61c4878aSAndroid Build Coastguard Workerspecifically by the handler in order to support the offset transfer. The
464*61c4878aSAndroid Build Coastguard Workertransfer handler confirms that the start offset is valid for the read/write
465*61c4878aSAndroid Build Coastguard Workeroperation, and the server responds with the offset to confirm the non-zero
466*61c4878aSAndroid Build Coastguard Workertransfer operation. Older server sw will ignore the offset, so the clients
467*61c4878aSAndroid Build Coastguard Workercheck that the server has accepted the non-zero offset during the handshake, so
468*61c4878aSAndroid Build Coastguard Workerusers may elect to catch such errors. Clients return `Status.UNIMPLEMENTED` in
469*61c4878aSAndroid Build Coastguard Workersuch cases.
470*61c4878aSAndroid Build Coastguard Worker
471*61c4878aSAndroid Build Coastguard WorkerDue to the need to seek streams by the handler to support the non-zero offset,
472*61c4878aSAndroid Build Coastguard Workerit is recommended to return `Status.RESOURCE_EXHAUSTED` if a seek is requested
473*61c4878aSAndroid Build Coastguard Workerpast the end of the stream.
474*61c4878aSAndroid Build Coastguard Worker
475*61c4878aSAndroid Build Coastguard WorkerSee the :ref:`transfer handler <pw_transfer-transfer-server>` documentation for
476*61c4878aSAndroid Build Coastguard Workerfurther information about configuring resources for non-zero transfers and the
477*61c4878aSAndroid Build Coastguard Workerinterface documentation in
478*61c4878aSAndroid Build Coastguard Worker``pw/transfer/public/pw_transfer/handler.h``
479*61c4878aSAndroid Build Coastguard Worker
480*61c4878aSAndroid Build Coastguard WorkerPython
481*61c4878aSAndroid Build Coastguard Worker======
482*61c4878aSAndroid Build Coastguard Worker.. automodule:: pw_transfer
483*61c4878aSAndroid Build Coastguard Worker  :members: ProgressStats, ProtocolVersion, Manager, Error
484*61c4878aSAndroid Build Coastguard Worker
485*61c4878aSAndroid Build Coastguard Worker**Example**
486*61c4878aSAndroid Build Coastguard Worker
487*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
488*61c4878aSAndroid Build Coastguard Worker
489*61c4878aSAndroid Build Coastguard Worker   import pw_transfer
490*61c4878aSAndroid Build Coastguard Worker
491*61c4878aSAndroid Build Coastguard Worker   # Initialize a Pigweed RPC client; see pw_rpc docs for more info.
492*61c4878aSAndroid Build Coastguard Worker   rpc_client = CustomRpcClient()
493*61c4878aSAndroid Build Coastguard Worker   rpcs = rpc_client.channel(1).rpcs
494*61c4878aSAndroid Build Coastguard Worker
495*61c4878aSAndroid Build Coastguard Worker   transfer_service = rpcs.pw.transfer.Transfer
496*61c4878aSAndroid Build Coastguard Worker   transfer_manager = pw_transfer.Manager(transfer_service)
497*61c4878aSAndroid Build Coastguard Worker
498*61c4878aSAndroid Build Coastguard Worker   try:
499*61c4878aSAndroid Build Coastguard Worker     # Read the transfer resource with ID 3 from the server.
500*61c4878aSAndroid Build Coastguard Worker     data = transfer_manager.read(3)
501*61c4878aSAndroid Build Coastguard Worker   except pw_transfer.Error as err:
502*61c4878aSAndroid Build Coastguard Worker     print('Failed to read:', err.status)
503*61c4878aSAndroid Build Coastguard Worker
504*61c4878aSAndroid Build Coastguard Worker   try:
505*61c4878aSAndroid Build Coastguard Worker     # Send some data to the server. The transfer manager does not have to be
506*61c4878aSAndroid Build Coastguard Worker     # reinitialized.
507*61c4878aSAndroid Build Coastguard Worker     transfer_manager.write(2, b'hello, world')
508*61c4878aSAndroid Build Coastguard Worker   except pw_transfer.Error as err:
509*61c4878aSAndroid Build Coastguard Worker     print('Failed to write:', err.status)
510*61c4878aSAndroid Build Coastguard Worker
511*61c4878aSAndroid Build Coastguard WorkerTypescript
512*61c4878aSAndroid Build Coastguard Worker==========
513*61c4878aSAndroid Build Coastguard WorkerProvides a simple interface for transferring bulk data over pw_rpc.
514*61c4878aSAndroid Build Coastguard Worker
515*61c4878aSAndroid Build Coastguard Worker**Example**
516*61c4878aSAndroid Build Coastguard Worker
517*61c4878aSAndroid Build Coastguard Worker.. code-block:: typescript
518*61c4878aSAndroid Build Coastguard Worker
519*61c4878aSAndroid Build Coastguard Worker   import { pw_transfer } from 'pigweedjs';
520*61c4878aSAndroid Build Coastguard Worker   const { Manager } from pw_transfer;
521*61c4878aSAndroid Build Coastguard Worker
522*61c4878aSAndroid Build Coastguard Worker   const client = new CustomRpcClient();
523*61c4878aSAndroid Build Coastguard Worker   service = client.channel()!.service('pw.transfer.Transfer')!;
524*61c4878aSAndroid Build Coastguard Worker
525*61c4878aSAndroid Build Coastguard Worker   const manager = new Manager(service, DEFAULT_TIMEOUT_S);
526*61c4878aSAndroid Build Coastguard Worker
527*61c4878aSAndroid Build Coastguard Worker   manager.read(3, (stats: ProgressStats) => {
528*61c4878aSAndroid Build Coastguard Worker     console.log(`Progress Update: ${stats}`);
529*61c4878aSAndroid Build Coastguard Worker   }).then((data: Uint8Array) => {
530*61c4878aSAndroid Build Coastguard Worker     console.log(`Completed read: ${data}`);
531*61c4878aSAndroid Build Coastguard Worker   }).catch(error => {
532*61c4878aSAndroid Build Coastguard Worker     console.log(`Failed to read: ${error.status}`);
533*61c4878aSAndroid Build Coastguard Worker   });
534*61c4878aSAndroid Build Coastguard Worker
535*61c4878aSAndroid Build Coastguard Worker   manager.write(2, textEncoder.encode('hello world'))
536*61c4878aSAndroid Build Coastguard Worker     .catch(error => {
537*61c4878aSAndroid Build Coastguard Worker       console.log(`Failed to read: ${error.status}`);
538*61c4878aSAndroid Build Coastguard Worker     });
539*61c4878aSAndroid Build Coastguard Worker
540*61c4878aSAndroid Build Coastguard WorkerJava
541*61c4878aSAndroid Build Coastguard Worker====
542*61c4878aSAndroid Build Coastguard Workerpw_transfer provides a Java client. The transfer client returns a
543*61c4878aSAndroid Build Coastguard Worker`ListenableFuture <https://guava.dev/releases/21.0/api/docs/com/google/common/util/concurrent/ListenableFuture>`_
544*61c4878aSAndroid Build Coastguard Workerto represent the results of a read or write transfer.
545*61c4878aSAndroid Build Coastguard Worker
546*61c4878aSAndroid Build Coastguard Worker.. code-block:: java
547*61c4878aSAndroid Build Coastguard Worker
548*61c4878aSAndroid Build Coastguard Worker   import dev.pigweed.pw_transfer.TransferClient;
549*61c4878aSAndroid Build Coastguard Worker
550*61c4878aSAndroid Build Coastguard Worker   public class TheClass  {
551*61c4878aSAndroid Build Coastguard Worker     public void DoTransfer(MethodClient transferReadMethodClient,
552*61c4878aSAndroid Build Coastguard Worker                            MethodClient transferWriteMethodClient) {
553*61c4878aSAndroid Build Coastguard Worker       // Create a new transfer client.
554*61c4878aSAndroid Build Coastguard Worker       TransferClient client = new TransferClient(
555*61c4878aSAndroid Build Coastguard Worker           transferReadMethodClient,
556*61c4878aSAndroid Build Coastguard Worker           transferWriteMethodClient,
557*61c4878aSAndroid Build Coastguard Worker           TransferTimeoutSettings.builder()
558*61c4878aSAndroid Build Coastguard Worker               .setTimeoutMillis(TRANSFER_TIMEOUT_MS)
559*61c4878aSAndroid Build Coastguard Worker               .setMaxRetries(MAX_RETRIES)
560*61c4878aSAndroid Build Coastguard Worker               .build());
561*61c4878aSAndroid Build Coastguard Worker
562*61c4878aSAndroid Build Coastguard Worker       // Start a read transfer.
563*61c4878aSAndroid Build Coastguard Worker       ListenableFuture<byte[]> readTransfer = client.read(123);
564*61c4878aSAndroid Build Coastguard Worker
565*61c4878aSAndroid Build Coastguard Worker       // Start a write transfer.
566*61c4878aSAndroid Build Coastguard Worker       ListenableFuture<Void> writeTransfer = client.write(123, dataToWrite);
567*61c4878aSAndroid Build Coastguard Worker
568*61c4878aSAndroid Build Coastguard Worker       // Get the data from the read transfer.
569*61c4878aSAndroid Build Coastguard Worker       byte[] readData = readTransfer.get();
570*61c4878aSAndroid Build Coastguard Worker
571*61c4878aSAndroid Build Coastguard Worker       // Wait for the write transfer to complete.
572*61c4878aSAndroid Build Coastguard Worker       writeTransfer.get();
573*61c4878aSAndroid Build Coastguard Worker     }
574*61c4878aSAndroid Build Coastguard Worker   }
575*61c4878aSAndroid Build Coastguard Worker
576*61c4878aSAndroid Build Coastguard Worker--------
577*61c4878aSAndroid Build Coastguard WorkerProtocol
578*61c4878aSAndroid Build Coastguard Worker--------
579*61c4878aSAndroid Build Coastguard Worker
580*61c4878aSAndroid Build Coastguard WorkerChunks
581*61c4878aSAndroid Build Coastguard Worker======
582*61c4878aSAndroid Build Coastguard WorkerTransfers run as a series of *chunks* exchanged over an RPC stream. Chunks can
583*61c4878aSAndroid Build Coastguard Workercontain transferable data, metadata, and control parameters. Each chunk has an
584*61c4878aSAndroid Build Coastguard Workerassociated type, which determines what information it holds and the semantics of
585*61c4878aSAndroid Build Coastguard Workerits fields.
586*61c4878aSAndroid Build Coastguard Worker
587*61c4878aSAndroid Build Coastguard WorkerThe chunk is a protobuf message, whose definition can be found
588*61c4878aSAndroid Build Coastguard Worker:ref:`here <module-pw_transfer-proto-definition>`.
589*61c4878aSAndroid Build Coastguard Worker
590*61c4878aSAndroid Build Coastguard WorkerResources and sessions
591*61c4878aSAndroid Build Coastguard Worker======================
592*61c4878aSAndroid Build Coastguard WorkerTransfers are run for a specific *resource* --- a stream of data which can be
593*61c4878aSAndroid Build Coastguard Workerread from or written to. Resources have a system-specific integral identifier
594*61c4878aSAndroid Build Coastguard Workerdefined by the implementers of the server-side transfer node.
595*61c4878aSAndroid Build Coastguard Worker
596*61c4878aSAndroid Build Coastguard WorkerThe series of chunks exchanged in an individual transfer operation for a
597*61c4878aSAndroid Build Coastguard Workerresource constitute a transfer *session*. The session runs from its opening
598*61c4878aSAndroid Build Coastguard Workerchunk until either a terminating chunk is received or the transfer times out.
599*61c4878aSAndroid Build Coastguard WorkerSessions are assigned IDs by the client that starts them, which are unique over
600*61c4878aSAndroid Build Coastguard Workerthe RPC channel between the client and server, allowing the server to identify
601*61c4878aSAndroid Build Coastguard Workertransfers across multiple clients.
602*61c4878aSAndroid Build Coastguard Worker
603*61c4878aSAndroid Build Coastguard WorkerReliability
604*61c4878aSAndroid Build Coastguard Worker===========
605*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` attempts to be a reliable data transfer protocol.
606*61c4878aSAndroid Build Coastguard Worker
607*61c4878aSAndroid Build Coastguard WorkerAs Pigweed RPC is considered an unreliable communications system,
608*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` implements its own mechanisms for reliability. These include
609*61c4878aSAndroid Build Coastguard Workertimeouts, data retransmissions, and handshakes.
610*61c4878aSAndroid Build Coastguard Worker
611*61c4878aSAndroid Build Coastguard Worker.. note::
612*61c4878aSAndroid Build Coastguard Worker
613*61c4878aSAndroid Build Coastguard Worker   A transfer can only be reliable if its underlying data stream is seekable.
614*61c4878aSAndroid Build Coastguard Worker   A non-seekable stream could prematurely terminate a transfer following a
615*61c4878aSAndroid Build Coastguard Worker   packet drop.
616*61c4878aSAndroid Build Coastguard Worker
617*61c4878aSAndroid Build Coastguard WorkerAt present, ``pw_transfer`` requires in-order data transmission. If packets are
618*61c4878aSAndroid Build Coastguard Workerreceived out-of-order, the receiver will request that the transmitter re-send
619*61c4878aSAndroid Build Coastguard Workerdata from the last received position.
620*61c4878aSAndroid Build Coastguard Worker
621*61c4878aSAndroid Build Coastguard WorkerOpening handshake
622*61c4878aSAndroid Build Coastguard Worker=================
623*61c4878aSAndroid Build Coastguard WorkerTransfers begin with a three-way handshake, whose purpose is to identify the
624*61c4878aSAndroid Build Coastguard Workerresource being transferred, assign a session ID, and synchronize the protocol
625*61c4878aSAndroid Build Coastguard Workerversion to use.
626*61c4878aSAndroid Build Coastguard Worker
627*61c4878aSAndroid Build Coastguard WorkerA read or write transfer for a resource is initiated by a transfer client. The
628*61c4878aSAndroid Build Coastguard Workerclient sends the ID of the resource to the server alongside a unique session ID
629*61c4878aSAndroid Build Coastguard Workerin a ``START`` chunk, indicating that it wishes to begin a new transfer. This
630*61c4878aSAndroid Build Coastguard Workerchunk additionally encodes the protocol version which the client is configured
631*61c4878aSAndroid Build Coastguard Workerto use.
632*61c4878aSAndroid Build Coastguard Worker
633*61c4878aSAndroid Build Coastguard WorkerUpon receiving a ``START`` chunk, the transfer server checks whether the
634*61c4878aSAndroid Build Coastguard Workerrequested resource is available. If so, it prepares the resource for the
635*61c4878aSAndroid Build Coastguard Workeroperation, which typically involves opening a data stream, alongside any
636*61c4878aSAndroid Build Coastguard Workeradditional user-specified setup. The server accepts the client's session ID,
637*61c4878aSAndroid Build Coastguard Workerthen responds to the client with a ``START_ACK`` chunk containing the resource,
638*61c4878aSAndroid Build Coastguard Workersession, and configured protocol version for the transfer.
639*61c4878aSAndroid Build Coastguard Worker
640*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer-windowing:
641*61c4878aSAndroid Build Coastguard Worker
642*61c4878aSAndroid Build Coastguard WorkerWindowing
643*61c4878aSAndroid Build Coastguard Worker=========
644*61c4878aSAndroid Build Coastguard WorkerThroughout a transfer, the receiver maintains a window of how much data it can
645*61c4878aSAndroid Build Coastguard Workerreceive at a given time. This window is a multiple of the maximum size of a
646*61c4878aSAndroid Build Coastguard Workersingle data chunk, and is adjusted dynamically in response to the ongoing status
647*61c4878aSAndroid Build Coastguard Workerof the transfer.
648*61c4878aSAndroid Build Coastguard Worker
649*61c4878aSAndroid Build Coastguard Workerpw_transfer uses a congestion control algorithm similar to that of TCP
650*61c4878aSAndroid Build Coastguard Worker`(RFC 5681 §3.1) <https://datatracker.ietf.org/doc/html/rfc5681#section-3.1>`_,
651*61c4878aSAndroid Build Coastguard Workeradapted to pw_transfer's mode of operation that tunes parameters per window.
652*61c4878aSAndroid Build Coastguard Worker
653*61c4878aSAndroid Build Coastguard WorkerOnce a portion of a window has successfully been received, it is acknowledged by
654*61c4878aSAndroid Build Coastguard Workerthe receiver and the window size is extended. Transfers begin in a "slow start"
655*61c4878aSAndroid Build Coastguard Workerphase, during which the window is doubled on each ACK. This continues until the
656*61c4878aSAndroid Build Coastguard Workertransfer detects a packet loss or times out. Once this occurs, the window size
657*61c4878aSAndroid Build Coastguard Workeris halved and the transfer enters a "congestion avoidance" phase for the
658*61c4878aSAndroid Build Coastguard Workerremainder of its run. During this phase, successful ACKs increase the window
659*61c4878aSAndroid Build Coastguard Workersize by a single chunk, whereas packet loss continues to half it.
660*61c4878aSAndroid Build Coastguard Worker
661*61c4878aSAndroid Build Coastguard WorkerTransfer completion
662*61c4878aSAndroid Build Coastguard Worker===================
663*61c4878aSAndroid Build Coastguard WorkerEither side of a transfer can terminate the operation at any time by sending a
664*61c4878aSAndroid Build Coastguard Worker``COMPLETION`` chunk containing the final status of the transfer. When a
665*61c4878aSAndroid Build Coastguard Worker``COMPLETION`` chunk is sent, the terminator of the transfer performs local
666*61c4878aSAndroid Build Coastguard Workercleanup, then waits for its peer to acknowledge the completion.
667*61c4878aSAndroid Build Coastguard Worker
668*61c4878aSAndroid Build Coastguard WorkerUpon receving a ``COMPLETION`` chunk, the transfer peer cancels any pending
669*61c4878aSAndroid Build Coastguard Workeroperations, runs its set of cleanups, and responds with a ``COMPLETION_ACK``,
670*61c4878aSAndroid Build Coastguard Workerfully ending the session from the peer's side.
671*61c4878aSAndroid Build Coastguard Worker
672*61c4878aSAndroid Build Coastguard WorkerThe terminator's session remains active waiting for a ``COMPLETION_ACK``. If not
673*61c4878aSAndroid Build Coastguard Workerreceived after a timeout, it re-sends its ``COMPLETION`` chunk. The session ends
674*61c4878aSAndroid Build Coastguard Workereither following receipt of the acknowledgement or if a maximum number of
675*61c4878aSAndroid Build Coastguard Workerretries is hit.
676*61c4878aSAndroid Build Coastguard Worker
677*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer-proto-definition:
678*61c4878aSAndroid Build Coastguard Worker
679*61c4878aSAndroid Build Coastguard WorkerServer to client transfer (read)
680*61c4878aSAndroid Build Coastguard Worker================================
681*61c4878aSAndroid Build Coastguard Worker.. image:: read.svg
682*61c4878aSAndroid Build Coastguard Worker
683*61c4878aSAndroid Build Coastguard WorkerClient to server transfer (write)
684*61c4878aSAndroid Build Coastguard Worker=================================
685*61c4878aSAndroid Build Coastguard Worker.. image:: write.svg
686*61c4878aSAndroid Build Coastguard Worker
687*61c4878aSAndroid Build Coastguard WorkerProtocol buffer definition
688*61c4878aSAndroid Build Coastguard Worker==========================
689*61c4878aSAndroid Build Coastguard Worker.. literalinclude:: transfer.proto
690*61c4878aSAndroid Build Coastguard Worker  :language: protobuf
691*61c4878aSAndroid Build Coastguard Worker  :lines: 14-
692*61c4878aSAndroid Build Coastguard Worker
693*61c4878aSAndroid Build Coastguard WorkerErrors
694*61c4878aSAndroid Build Coastguard Worker======
695*61c4878aSAndroid Build Coastguard Worker
696*61c4878aSAndroid Build Coastguard WorkerProtocol errors
697*61c4878aSAndroid Build Coastguard Worker---------------
698*61c4878aSAndroid Build Coastguard WorkerThe following table describes the meaning of each status code when sent by the
699*61c4878aSAndroid Build Coastguard Workersender or the receiver (see `Transfer roles`_).
700*61c4878aSAndroid Build Coastguard Worker
701*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::stream
702*61c4878aSAndroid Build Coastguard Worker
703*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
704*61c4878aSAndroid Build Coastguard Worker| Status                  | Sent by sender          | Sent by receiver        |
705*61c4878aSAndroid Build Coastguard Worker+=========================+=========================+=========================+
706*61c4878aSAndroid Build Coastguard Worker| ``OK``                  | (not sent)              | All data was received   |
707*61c4878aSAndroid Build Coastguard Worker|                         |                         | and handled             |
708*61c4878aSAndroid Build Coastguard Worker|                         |                         | successfully.           |
709*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
710*61c4878aSAndroid Build Coastguard Worker| ``ABORTED``             | The service aborted the transfer because the      |
711*61c4878aSAndroid Build Coastguard Worker|                         | client restarted it. This status is passed to the |
712*61c4878aSAndroid Build Coastguard Worker|                         | transfer handler, but not sent to the client      |
713*61c4878aSAndroid Build Coastguard Worker|                         | because it restarted the transfer.                |
714*61c4878aSAndroid Build Coastguard Worker+-------------------------+---------------------------------------------------+
715*61c4878aSAndroid Build Coastguard Worker| ``CANCELLED``           | The client cancelled the transfer.                |
716*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
717*61c4878aSAndroid Build Coastguard Worker| ``DATA_LOSS``           | Failed to read the data | Failed to write the     |
718*61c4878aSAndroid Build Coastguard Worker|                         | to send. The            | received data. The      |
719*61c4878aSAndroid Build Coastguard Worker|                         | :cpp:class:`Reader`     | :cpp:class:`Writer`     |
720*61c4878aSAndroid Build Coastguard Worker|                         | returned an error.      | returned an error.      |
721*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
722*61c4878aSAndroid Build Coastguard Worker| ``FAILED_PRECONDITION`` | Received chunk for transfer that is not active.   |
723*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
724*61c4878aSAndroid Build Coastguard Worker| ``INVALID_ARGUMENT``    | Received a malformed packet.                      |
725*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
726*61c4878aSAndroid Build Coastguard Worker| ``INTERNAL``            | An assumption of the protocol was violated.       |
727*61c4878aSAndroid Build Coastguard Worker|                         | Encountering ``INTERNAL`` indicates that there is |
728*61c4878aSAndroid Build Coastguard Worker|                         | a bug in the service or client implementation.    |
729*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
730*61c4878aSAndroid Build Coastguard Worker| ``PERMISSION_DENIED``   | The transfer does not support the requested       |
731*61c4878aSAndroid Build Coastguard Worker|                         | operation (either reading or writing).            |
732*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
733*61c4878aSAndroid Build Coastguard Worker| ``RESOURCE_EXHAUSTED``  | The receiver requested  | Storage is full.        |
734*61c4878aSAndroid Build Coastguard Worker|                         | zero bytes, indicating  |                         |
735*61c4878aSAndroid Build Coastguard Worker|                         | their storage is full,  |                         |
736*61c4878aSAndroid Build Coastguard Worker|                         | but there is still data |                         |
737*61c4878aSAndroid Build Coastguard Worker|                         | to send.                |                         |
738*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
739*61c4878aSAndroid Build Coastguard Worker| ``UNAVAILABLE``         | The service is busy with other transfers and      |
740*61c4878aSAndroid Build Coastguard Worker|                         | cannot begin a new transfer at this time.         |
741*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
742*61c4878aSAndroid Build Coastguard Worker| ``UNIMPLEMENTED``       | Out-of-order chunk was  | (not sent)              |
743*61c4878aSAndroid Build Coastguard Worker|                         | requested, but seeking  |                         |
744*61c4878aSAndroid Build Coastguard Worker|                         | is not supported.       |                         |
745*61c4878aSAndroid Build Coastguard Worker+-------------------------+-------------------------+-------------------------+
746*61c4878aSAndroid Build Coastguard Worker
747*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
748*61c4878aSAndroid Build Coastguard Worker
749*61c4878aSAndroid Build Coastguard Worker
750*61c4878aSAndroid Build Coastguard WorkerTransfer roles
751*61c4878aSAndroid Build Coastguard Worker==============
752*61c4878aSAndroid Build Coastguard WorkerEvery transfer has two participants: the sender and the receiver. The sender
753*61c4878aSAndroid Build Coastguard Workertransmits data to the receiver. The receiver controls how the data is
754*61c4878aSAndroid Build Coastguard Workertransferred and sends the final status when the transfer is complete.
755*61c4878aSAndroid Build Coastguard Worker
756*61c4878aSAndroid Build Coastguard WorkerIn read transfers, the client is the receiver and the service is the sender. In
757*61c4878aSAndroid Build Coastguard Workerwrite transfers, the client is the sender and the service is the receiver.
758*61c4878aSAndroid Build Coastguard Worker
759*61c4878aSAndroid Build Coastguard WorkerSender flow
760*61c4878aSAndroid Build Coastguard Worker-----------
761*61c4878aSAndroid Build Coastguard Worker.. mermaid::
762*61c4878aSAndroid Build Coastguard Worker
763*61c4878aSAndroid Build Coastguard Worker  graph TD
764*61c4878aSAndroid Build Coastguard Worker    start([Client initiates<br>transfer]) -->data_request
765*61c4878aSAndroid Build Coastguard Worker    data_request[Receive transfer<br>parameters]-->send_chunk
766*61c4878aSAndroid Build Coastguard Worker
767*61c4878aSAndroid Build Coastguard Worker    send_chunk[Send chunk]-->sent_all
768*61c4878aSAndroid Build Coastguard Worker
769*61c4878aSAndroid Build Coastguard Worker    sent_all{Sent final<br>chunk?} -->|yes|wait
770*61c4878aSAndroid Build Coastguard Worker    sent_all-->|no|sent_requested
771*61c4878aSAndroid Build Coastguard Worker
772*61c4878aSAndroid Build Coastguard Worker    sent_requested{Sent all<br>pending?}-->|yes|data_request
773*61c4878aSAndroid Build Coastguard Worker    sent_requested-->|no|send_chunk
774*61c4878aSAndroid Build Coastguard Worker
775*61c4878aSAndroid Build Coastguard Worker    wait[Wait for receiver]-->is_done
776*61c4878aSAndroid Build Coastguard Worker
777*61c4878aSAndroid Build Coastguard Worker    is_done{Received<br>final chunk?}-->|yes|done
778*61c4878aSAndroid Build Coastguard Worker    is_done-->|no|data_request
779*61c4878aSAndroid Build Coastguard Worker
780*61c4878aSAndroid Build Coastguard Worker    done([Transfer complete])
781*61c4878aSAndroid Build Coastguard Worker
782*61c4878aSAndroid Build Coastguard WorkerReceiver flow
783*61c4878aSAndroid Build Coastguard Worker-------------
784*61c4878aSAndroid Build Coastguard Worker.. mermaid::
785*61c4878aSAndroid Build Coastguard Worker
786*61c4878aSAndroid Build Coastguard Worker  graph TD
787*61c4878aSAndroid Build Coastguard Worker    start([Client initiates<br>transfer]) -->request_bytes
788*61c4878aSAndroid Build Coastguard Worker    request_bytes[Set transfer<br>parameters]-->wait
789*61c4878aSAndroid Build Coastguard Worker
790*61c4878aSAndroid Build Coastguard Worker    wait[Wait for chunk]-->received_chunk
791*61c4878aSAndroid Build Coastguard Worker
792*61c4878aSAndroid Build Coastguard Worker    received_chunk{Received<br>chunk by<br>deadline?}-->|no|request_bytes
793*61c4878aSAndroid Build Coastguard Worker    received_chunk-->|yes|check_chunk
794*61c4878aSAndroid Build Coastguard Worker
795*61c4878aSAndroid Build Coastguard Worker    check_chunk{Correct<br>offset?} -->|yes|process_chunk
796*61c4878aSAndroid Build Coastguard Worker    check_chunk --> |no|request_bytes
797*61c4878aSAndroid Build Coastguard Worker
798*61c4878aSAndroid Build Coastguard Worker    process_chunk[Process chunk]-->final_chunk
799*61c4878aSAndroid Build Coastguard Worker
800*61c4878aSAndroid Build Coastguard Worker    final_chunk{Final<br>chunk?}-->|yes|signal_completion
801*61c4878aSAndroid Build Coastguard Worker    final_chunk{Final<br>chunk?}-->|no|received_requested
802*61c4878aSAndroid Build Coastguard Worker
803*61c4878aSAndroid Build Coastguard Worker    received_requested{Received all<br>pending?}-->|yes|request_bytes
804*61c4878aSAndroid Build Coastguard Worker    received_requested-->|no|wait
805*61c4878aSAndroid Build Coastguard Worker
806*61c4878aSAndroid Build Coastguard Worker    signal_completion[Signal completion]-->done
807*61c4878aSAndroid Build Coastguard Worker
808*61c4878aSAndroid Build Coastguard Worker    done([Transfer complete])
809*61c4878aSAndroid Build Coastguard Worker
810*61c4878aSAndroid Build Coastguard WorkerLegacy protocol
811*61c4878aSAndroid Build Coastguard Worker===============
812*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` was initially released into production prior to several of the
813*61c4878aSAndroid Build Coastguard Workerreliability improvements of its modern protocol. As a result of this, transfer
814*61c4878aSAndroid Build Coastguard Workerimplementations support a "legacy" protocol mode, in which transfers run without
815*61c4878aSAndroid Build Coastguard Workerutilizing these features.
816*61c4878aSAndroid Build Coastguard Worker
817*61c4878aSAndroid Build Coastguard WorkerThe primary differences between the legacy and modern protocols are listed
818*61c4878aSAndroid Build Coastguard Workerbelow.
819*61c4878aSAndroid Build Coastguard Worker
820*61c4878aSAndroid Build Coastguard Worker- There is no distinction between a transfer resource and session --- a single
821*61c4878aSAndroid Build Coastguard Worker  ``transfer_id`` field represents both. Only one transfer for a given resource
822*61c4878aSAndroid Build Coastguard Worker  can run at a time, and it is not possible to determine where one transfer for
823*61c4878aSAndroid Build Coastguard Worker  a resource ends and the next begins.
824*61c4878aSAndroid Build Coastguard Worker- The legacy protocol has no opening handshake phase. The client initiates with
825*61c4878aSAndroid Build Coastguard Worker  a transfer ID and starting transfer parameters (during a read), and the data
826*61c4878aSAndroid Build Coastguard Worker  transfer phase begins immediately.
827*61c4878aSAndroid Build Coastguard Worker- The legacy protocol has no terminating handshake phase. When either end
828*61c4878aSAndroid Build Coastguard Worker  completes a transfer by sending a status chunk, it does not wait for the peer
829*61c4878aSAndroid Build Coastguard Worker  to acknowledge. Resources used by the transfer are immediately freed, and
830*61c4878aSAndroid Build Coastguard Worker  there is no guarantee that the peer is notified of completion.
831*61c4878aSAndroid Build Coastguard Worker
832*61c4878aSAndroid Build Coastguard WorkerTransfer clients request the latest transfer protocol version by default, but
833*61c4878aSAndroid Build Coastguard Workermay be configured to request the legacy protocol. Transfer server and client
834*61c4878aSAndroid Build Coastguard Workerimplementations detect if their transfer peer is running the legacy protocol and
835*61c4878aSAndroid Build Coastguard Workerautomatically switch to it if required, even if they requested a newer protocol
836*61c4878aSAndroid Build Coastguard Workerversion. It is **strongly** unadvised to use the legacy protocol in new code.
837*61c4878aSAndroid Build Coastguard Worker
838*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer-integration-tests:
839*61c4878aSAndroid Build Coastguard Worker
840*61c4878aSAndroid Build Coastguard Worker-----------------
841*61c4878aSAndroid Build Coastguard WorkerIntegration tests
842*61c4878aSAndroid Build Coastguard Worker-----------------
843*61c4878aSAndroid Build Coastguard WorkerThe ``pw_transfer`` module has a set of integration tests that verify the
844*61c4878aSAndroid Build Coastguard Workercorrectness of implementations in different languages.
845*61c4878aSAndroid Build Coastguard Worker`Test source code <https://cs.pigweed.dev/pigweed/+/main:pw_transfer/integration_test/>`_.
846*61c4878aSAndroid Build Coastguard Worker
847*61c4878aSAndroid Build Coastguard WorkerTo run the tests on your machine, run
848*61c4878aSAndroid Build Coastguard Worker
849*61c4878aSAndroid Build Coastguard Worker.. code-block:: bash
850*61c4878aSAndroid Build Coastguard Worker
851*61c4878aSAndroid Build Coastguard Worker   $ bazel test \
852*61c4878aSAndroid Build Coastguard Worker         pw_transfer/integration_test:cross_language_small_test \
853*61c4878aSAndroid Build Coastguard Worker         pw_transfer/integration_test:cross_language_medium_test
854*61c4878aSAndroid Build Coastguard Worker
855*61c4878aSAndroid Build Coastguard Worker.. note:: There is a large test that tests transfers that are megabytes in size.
856*61c4878aSAndroid Build Coastguard Worker  These are not run automatically, but can be run manually via the
857*61c4878aSAndroid Build Coastguard Worker  ``pw_transfer/integration_test:cross_language_large_test`` test. These are
858*61c4878aSAndroid Build Coastguard Worker  VERY slow, but exist for manual validation of real-world use cases.
859*61c4878aSAndroid Build Coastguard Worker
860*61c4878aSAndroid Build Coastguard WorkerThe integration tests permit injection of client/server/proxy binaries to use
861*61c4878aSAndroid Build Coastguard Workerwhen running the tests. This allows manual testing of older versions of
862*61c4878aSAndroid Build Coastguard Workerpw_transfer against newer versions.
863*61c4878aSAndroid Build Coastguard Worker
864*61c4878aSAndroid Build Coastguard Worker.. code-block:: bash
865*61c4878aSAndroid Build Coastguard Worker
866*61c4878aSAndroid Build Coastguard Worker   # Test a newer version of pw_transfer against an old C++ client that was
867*61c4878aSAndroid Build Coastguard Worker   # backed up to another directory.
868*61c4878aSAndroid Build Coastguard Worker   $ bazel run pw_transfer/integration_test:cross_language_medium_test -- \
869*61c4878aSAndroid Build Coastguard Worker       --cpp-client-binary ../old_pw_transfer_version/cpp_client
870*61c4878aSAndroid Build Coastguard Worker
871*61c4878aSAndroid Build Coastguard WorkerBackwards compatibility tests
872*61c4878aSAndroid Build Coastguard Worker=============================
873*61c4878aSAndroid Build Coastguard Worker``pw_transfer`` includes a `suite of backwards-compatibility tests
874*61c4878aSAndroid Build Coastguard Worker<https://cs.pigweed.dev/pigweed/+/main:pw_transfer/integration_test/legacy_binaries_test.py>`_
875*61c4878aSAndroid Build Coastguard Workerthat are intended to continuously validate a degree of backwards-compatibility
876*61c4878aSAndroid Build Coastguard Workerwith older pw_transfer servers and clients. This is done by retrieving older
877*61c4878aSAndroid Build Coastguard Workerbinaries hosted in CIPD and running tests between the older client/server
878*61c4878aSAndroid Build Coastguard Workerbinaries and the latest binaries.
879*61c4878aSAndroid Build Coastguard Worker
880*61c4878aSAndroid Build Coastguard WorkerThe CIPD package contents can be created with this command:
881*61c4878aSAndroid Build Coastguard Worker
882*61c4878aSAndroid Build Coastguard Worker.. code-block::bash
883*61c4878aSAndroid Build Coastguard Worker
884*61c4878aSAndroid Build Coastguard Worker   $ bazel build pw_transfer/integration_test:server \
885*61c4878aSAndroid Build Coastguard Worker                 pw_transfer/integration_test:cpp_client
886*61c4878aSAndroid Build Coastguard Worker   $ mkdir pw_transfer_test_binaries
887*61c4878aSAndroid Build Coastguard Worker   $ cp bazel-bin/pw_transfer/integration_test/server \
888*61c4878aSAndroid Build Coastguard Worker        pw_transfer_test_binaries
889*61c4878aSAndroid Build Coastguard Worker   $ cp bazel-bin/pw_transfer/integration_test/cpp_client \
890*61c4878aSAndroid Build Coastguard Worker        pw_transfer_test_binaries
891*61c4878aSAndroid Build Coastguard Worker
892*61c4878aSAndroid Build Coastguard WorkerTo update the CIPD package itself, follow the `internal documentation for
893*61c4878aSAndroid Build Coastguard Workerupdating a CIPD package <http://go/pigweed-cipd#installing-packages-into-cipd>`_.
894*61c4878aSAndroid Build Coastguard Worker
895*61c4878aSAndroid Build Coastguard WorkerCI/CQ integration
896*61c4878aSAndroid Build Coastguard Worker=================
897*61c4878aSAndroid Build Coastguard Worker`Current status of the test in CI <https://ci.chromium.org/ui/p/pigweed/builders/luci.pigweed.pigweed.ci/pigweed-linux-bzl-integration>`_.
898*61c4878aSAndroid Build Coastguard Worker
899*61c4878aSAndroid Build Coastguard WorkerBy default, these tests are not run in CQ (on presubmit) because they are too
900*61c4878aSAndroid Build Coastguard Workerslow. However, you can request that the tests be run in presubmit on your
901*61c4878aSAndroid Build Coastguard Workerchange by adding to following line to the commit message footer:
902*61c4878aSAndroid Build Coastguard Worker
903*61c4878aSAndroid Build Coastguard Worker.. code-block::
904*61c4878aSAndroid Build Coastguard Worker
905*61c4878aSAndroid Build Coastguard Worker   Cq-Include-Trybots: luci.pigweed.try:pigweed-linux-bzl-integration
906*61c4878aSAndroid Build Coastguard Worker
907*61c4878aSAndroid Build Coastguard Worker.. _module-pw_transfer-parallel-tests:
908*61c4878aSAndroid Build Coastguard Worker
909*61c4878aSAndroid Build Coastguard WorkerRunning the tests many times
910*61c4878aSAndroid Build Coastguard Worker============================
911*61c4878aSAndroid Build Coastguard WorkerBecause the tests bind to network ports, you cannot run more than one instance
912*61c4878aSAndroid Build Coastguard Workerof each test in parallel. However, you might want to do so, e.g. to debug
913*61c4878aSAndroid Build Coastguard Workerflakes. This section describes a manual process that makes this possible.
914*61c4878aSAndroid Build Coastguard Worker
915*61c4878aSAndroid Build Coastguard WorkerLinux
916*61c4878aSAndroid Build Coastguard Worker-----
917*61c4878aSAndroid Build Coastguard WorkerOn Linux, you can add the ``"block-network"`` tag to the tests (`example
918*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/181297>`_). This
919*61c4878aSAndroid Build Coastguard Workerenables network isolation for the tests, allowing you to run them in parallel
920*61c4878aSAndroid Build Coastguard Workervia,
921*61c4878aSAndroid Build Coastguard Worker
922*61c4878aSAndroid Build Coastguard Worker.. code-block::
923*61c4878aSAndroid Build Coastguard Worker
924*61c4878aSAndroid Build Coastguard Worker   bazel test --runs_per_test=10 //pw_transfer/integration_tests/...
925*61c4878aSAndroid Build Coastguard Worker
926*61c4878aSAndroid Build Coastguard WorkerMacOS
927*61c4878aSAndroid Build Coastguard Worker-----
928*61c4878aSAndroid Build Coastguard WorkerNetwork isolation is not supported on MacOS because the OS doesn't support
929*61c4878aSAndroid Build Coastguard Workernetwork virtualization (`gh#2669
930*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/bazel/issues/2669>`_). The best you can do is to
931*61c4878aSAndroid Build Coastguard Workertag the tests ``"exclusive"``. This allows you to use ``--runs_per_test``, but
932*61c4878aSAndroid Build Coastguard Workerwill force each test to run by itself, with no parallelism.
933*61c4878aSAndroid Build Coastguard Worker
934*61c4878aSAndroid Build Coastguard WorkerWhy is this manual?
935*61c4878aSAndroid Build Coastguard Worker-------------------
936*61c4878aSAndroid Build Coastguard WorkerIdeally, we would apply either the ``"block-network"`` or ``"exclusive"`` tag
937*61c4878aSAndroid Build Coastguard Workerto the tests depending on the OS. But this is not supported, `gh#2971
938*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/bazel/issues/2971>`_.
939*61c4878aSAndroid Build Coastguard Worker
940*61c4878aSAndroid Build Coastguard WorkerWe don't want to tag the tests ``"exclusive"`` by default because that will
941*61c4878aSAndroid Build Coastguard Workerprevent *different* tests from running in parallel, significantly slowing them
942*61c4878aSAndroid Build Coastguard Workerdown.
943*61c4878aSAndroid Build Coastguard Worker
944*61c4878aSAndroid Build Coastguard Worker.. toctree::
945*61c4878aSAndroid Build Coastguard Worker   :hidden:
946*61c4878aSAndroid Build Coastguard Worker
947*61c4878aSAndroid Build Coastguard Worker   API reference <api>
948