mirror of
https://fuchsia.googlesource.com/third_party/pigweed.googlesource.com/pigweed/pigweed
synced 2024-09-20 22:00:58 +00:00
0c94fc22f9
This implements a basic version of the client-side pw_transfer protocol in Python (theoretically). Both read and write transfers are supported. Not all possible error cases are handled yet. Change-Id: I96d56251951ec5c17fae67bf5eb623d2e3f5b7dc Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/50280 Commit-Queue: Alexei Frolov <frolv@google.com> Reviewed-by: Wyatt Hepler <hepler@google.com>
193 lines
4.5 KiB
ReStructuredText
193 lines
4.5 KiB
ReStructuredText
.. _module-pw_transfer:
|
|
|
|
===========
|
|
pw_transfer
|
|
===========
|
|
|
|
.. attention::
|
|
|
|
``pw_transfer`` is under construction and so is its documentation.
|
|
|
|
-----
|
|
Usage
|
|
-----
|
|
|
|
Python
|
|
======
|
|
.. automodule:: pw_transfer.transfer
|
|
:members: Manager, Error
|
|
|
|
**Example**
|
|
|
|
.. code-block:: python
|
|
|
|
from pw_transfer import transfer
|
|
|
|
# Initialize a Pigweed RPC client; see pw_rpc docs for more info.
|
|
rpc_client = CustomRpcClient()
|
|
rpcs = rpc_client.channel(1).rpcs
|
|
|
|
transfer_service = rpcs.pw.transfer.Transfer
|
|
transfer_manager = transfer.Manager(transfer_service)
|
|
|
|
try:
|
|
# Read transfer_id 3 from the server.
|
|
data = transfer_manager.read(3)
|
|
except transfer.Error as err:
|
|
print('Failed to read:', err.status)
|
|
|
|
try:
|
|
# Send some data to the server. The transfer manager does not have to be
|
|
# reinitialized.
|
|
transfer_manager.write(2, b'hello, world')
|
|
except transfer.Error as err:
|
|
print('Failed to write:', err.status)
|
|
|
|
--------
|
|
Protocol
|
|
--------
|
|
|
|
Protocol buffer definition
|
|
==========================
|
|
.. literalinclude:: transfer.proto
|
|
:language: protobuf
|
|
:lines: 14-
|
|
|
|
Server to client transfer (read)
|
|
================================
|
|
.. seqdiag::
|
|
:scale: 110
|
|
|
|
seqdiag {
|
|
default_note_color = aliceblue;
|
|
|
|
client -> server [
|
|
label = "set transfer parameters",
|
|
leftnote = "transfer_id\noffset\npending_bytes\nmax_chunk_size\nchunk_delay"
|
|
];
|
|
|
|
client <-- server [
|
|
noactivate,
|
|
label = "requested bytes\n(zero or more chunks)",
|
|
rightnote = "transfer_id\noffset\ndata\n(remaining_bytes)"
|
|
];
|
|
|
|
client --> server [
|
|
noactivate,
|
|
label = "update transfer parameters\n(as needed)",
|
|
leftnote = "transfer_id\noffset\npending_bytes\n(max_chunk_size)\n(chunk_delay)"
|
|
];
|
|
|
|
client <- server [
|
|
noactivate,
|
|
label = "final chunk",
|
|
rightnote = "transfer_id\noffset\ndata\nremaining_bytes=0"
|
|
];
|
|
|
|
client -> server [
|
|
noactivate,
|
|
label = "acknowledge completion",
|
|
leftnote = "transfer_id\nstatus=OK"
|
|
];
|
|
}
|
|
|
|
Client to server transfer (write)
|
|
=================================
|
|
.. seqdiag::
|
|
:scale: 110
|
|
|
|
seqdiag {
|
|
default_note_color = aliceblue;
|
|
|
|
client -> server [
|
|
label = "start",
|
|
leftnote = "transfer_id"
|
|
];
|
|
|
|
client <- server [
|
|
noactivate,
|
|
label = "set transfer parameters",
|
|
rightnote = "transfer_id\noffset\npending_bytes\nmax_chunk_size\nchunk_delay"
|
|
];
|
|
|
|
client --> server [
|
|
noactivate,
|
|
label = "requested bytes\n(zero or more chunks)",
|
|
leftnote = "transfer_id\noffset\ndata\n(remaining_bytes)"
|
|
];
|
|
|
|
client <-- server [
|
|
noactivate,
|
|
label = "update transfer parameters\n(as needed)",
|
|
rightnote = "transfer_id\noffset\npending_bytes\n(max_chunk_size)\n(chunk_delay)"
|
|
];
|
|
|
|
client -> server [
|
|
noactivate,
|
|
label = "final chunk",
|
|
leftnote = "transfer_id\noffset\ndata\nremaining_bytes=0"
|
|
];
|
|
|
|
client <- server [
|
|
noactivate,
|
|
label = "acknowledge completion",
|
|
rightnote = "transfer_id\nstatus=OK"
|
|
];
|
|
}
|
|
|
|
Errors
|
|
======
|
|
At any point, either the client or server may terminate the transfer by sending
|
|
an error chunk with the transfer ID and a non-OK status.
|
|
|
|
Transmitter flow
|
|
================
|
|
.. mermaid::
|
|
|
|
graph TD
|
|
start([Client initiates<br>transfer]) -->data_request
|
|
data_request[Receive transfer<br>parameters]-->send_chunk
|
|
|
|
send_chunk[Send chunk]-->sent_all
|
|
|
|
sent_all{Sent final<br>chunk?} -->|yes|wait
|
|
sent_all-->|no|sent_requested
|
|
|
|
sent_requested{Sent all<br>pending?}-->|yes|data_request
|
|
sent_requested-->|no|send_chunk
|
|
|
|
wait[Wait for receiver]-->is_done
|
|
|
|
is_done{Received<br>final chunk?}-->|yes|done
|
|
is_done-->|no|data_request
|
|
|
|
done([Transfer complete])
|
|
|
|
Receiver flow
|
|
=============
|
|
.. mermaid::
|
|
|
|
graph TD
|
|
start([Client initiates<br>transfer]) -->request_bytes
|
|
request_bytes[Set transfer<br>parameters]-->wait
|
|
|
|
wait[Wait for chunk]-->received_chunk
|
|
|
|
received_chunk{Received<br>chunk by<br>deadline?}-->|no|request_bytes
|
|
received_chunk-->|yes|check_chunk
|
|
|
|
check_chunk{Correct<br>offset?} -->|yes|process_chunk
|
|
check_chunk --> |no|request_bytes
|
|
|
|
process_chunk[Process chunk]-->final_chunk
|
|
|
|
final_chunk{Final<br>chunk?}-->|yes|signal_completion
|
|
final_chunk{Final<br>chunk?}-->|no|received_requested
|
|
|
|
received_requested{Received all<br>pending?}-->|yes|request_bytes
|
|
received_requested-->|no|wait
|
|
|
|
signal_completion[Signal completion]-->done
|
|
|
|
done([Transfer complete])
|