pw_transfer: Add separate session_id to chunk
This partially reverts pigweed:89260 by renaming field number 1 in the
chunk proto back to transfer_id. The session_id field is introduced as
an entirely new field, so that its presence can be used to detect the
protocol version that a transfer is running.
Change-Id: I9765edc6fa5a263de1366176c2e08e8e5a1bd0f0
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/94063
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Alexei Frolov <frolv@google.com>
diff --git a/pw_transfer/chunk.cc b/pw_transfer/chunk.cc
index 8ccea66..5a018a1 100644
--- a/pw_transfer/chunk.cc
+++ b/pw_transfer/chunk.cc
@@ -16,6 +16,7 @@
#include "pw_assert/check.h"
#include "pw_protobuf/decoder.h"
+#include "pw_protobuf/serialized_size.h"
#include "pw_status/try.h"
#include "pw_transfer/transfer.pwpb.h"
@@ -26,22 +27,35 @@
Result<uint32_t> Chunk::ExtractSessionId(ConstByteSpan message) {
protobuf::Decoder decoder(message);
+ uint32_t session_id = 0;
+
while (decoder.Next().ok()) {
ProtoChunk::Fields field =
static_cast<ProtoChunk::Fields>(decoder.FieldNumber());
switch (field) {
- case ProtoChunk::Fields::SESSION_ID: {
- uint32_t session_id;
+ case ProtoChunk::Fields::TRANSFER_ID:
+ // Interpret a legacy transfer_id field as a session ID, but don't
+ // return immediately. Instead, check to see if the message also
+ // contains a newer session_id field.
+ PW_TRY(decoder.ReadUint32(&session_id));
+ break;
+
+ case ProtoChunk::Fields::SESSION_ID:
+ // A session_id field always takes precedence over transfer_id, so
+ // return it immediately when encountered.
PW_TRY(decoder.ReadUint32(&session_id));
return session_id;
- }
default:
continue;
}
}
+ if (session_id != 0) {
+ return session_id;
+ }
+
return Status::DataLoss();
}
@@ -68,7 +82,19 @@
static_cast<ProtoChunk::Fields>(decoder.FieldNumber());
switch (field) {
+ case ProtoChunk::Fields::TRANSFER_ID:
+ // transfer_id is a legacy field. session_id will always take precedence
+ // over it, so it should only be read if session_id has not yet been
+ // encountered.
+ if (chunk.session_id_ == 0) {
+ PW_TRY(decoder.ReadUint32(&chunk.session_id_));
+ }
+ break;
+
case ProtoChunk::Fields::SESSION_ID:
+ // The existence of a session_id field indicates that a newer protocol
+ // is running.
+ chunk.protocol_version_ = ProtocolVersion::kVersionTwo;
PW_TRY(decoder.ReadUint32(&chunk.session_id_));
break;
@@ -149,7 +175,21 @@
ProtoChunk::MemoryEncoder encoder(buffer);
- encoder.WriteSessionId(session_id_).IgnoreError();
+ // Write the payload first to avoid clobbering it if it shares the same buffer
+ // as the encode buffer.
+ if (has_payload()) {
+ encoder.WriteData(payload_).IgnoreError();
+ }
+
+ if (protocol_version_ >= ProtocolVersion::kVersionTwo) {
+ if (session_id_ != 0) {
+ encoder.WriteSessionId(session_id_).IgnoreError();
+ }
+
+ if (resource_id_.has_value()) {
+ encoder.WriteResourceId(resource_id_.value()).IgnoreError();
+ }
+ }
if (type_.has_value()) {
encoder.WriteType(static_cast<ProtoChunk::Type>(type_.value()))
@@ -160,7 +200,11 @@
encoder.WriteWindowEndOffset(window_end_offset_).IgnoreError();
}
- if (protocol_version_ == ProtocolVersion::kLegacy) {
+ // Encode additional fields from the legacy protocol.
+ if (ShouldEncodeLegacyFields()) {
+ // The legacy protocol uses the transfer_id field instead of session_id.
+ encoder.WriteTransferId(session_id_).IgnoreError();
+
// In the legacy protocol, the pending_bytes field must be set alongside
// window_end_offset, as some transfer implementations require it.
encoder.WritePendingBytes(window_end_offset_ - offset_).IgnoreError();
@@ -178,10 +222,6 @@
encoder.WriteOffset(offset_).IgnoreError();
}
- if (has_payload()) {
- encoder.WriteData(payload_).IgnoreError();
- }
-
if (remaining_bytes_.has_value()) {
encoder.WriteRemainingBytes(remaining_bytes_.value()).IgnoreError();
}
@@ -190,14 +230,79 @@
encoder.WriteStatus(status_.value().code()).IgnoreError();
}
- if (resource_id_.has_value()) {
- encoder.WriteResourceId(resource_id_.value()).IgnoreError();
- }
-
PW_TRY(encoder.status());
return ConstByteSpan(encoder);
}
-Status DecodeChunk(ConstByteSpan, Chunk&) { return Status::Unimplemented(); }
+size_t Chunk::EncodedSize() const {
+ size_t size = 0;
+
+ if (session_id_ != 0) {
+ if (protocol_version_ >= ProtocolVersion::kVersionTwo) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::SESSION_ID,
+ session_id_);
+ }
+
+ if (ShouldEncodeLegacyFields()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::TRANSFER_ID,
+ session_id_);
+ }
+ }
+
+ if (protocol_version_ >= ProtocolVersion::kVersionTwo) {
+ if (resource_id_.has_value()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::RESOURCE_ID,
+ resource_id_.value());
+ }
+ }
+
+ if (offset_ != 0) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::OFFSET, offset_);
+ }
+
+ if (window_end_offset_ != 0) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::WINDOW_END_OFFSET,
+ window_end_offset_);
+
+ if (ShouldEncodeLegacyFields()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::PENDING_BYTES,
+ window_end_offset_ - offset_);
+ }
+ }
+
+ if (type_.has_value()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::TYPE,
+ static_cast<uint32_t>(type_.value()));
+ }
+
+ if (has_payload()) {
+ size += protobuf::SizeOfDelimitedField(ProtoChunk::Fields::DATA,
+ payload_.size());
+ }
+
+ if (max_chunk_size_bytes_.has_value()) {
+ size +=
+ protobuf::SizeOfVarintField(ProtoChunk::Fields::MAX_CHUNK_SIZE_BYTES,
+ max_chunk_size_bytes_.value());
+ }
+
+ if (min_delay_microseconds_.has_value()) {
+ size +=
+ protobuf::SizeOfVarintField(ProtoChunk::Fields::MIN_DELAY_MICROSECONDS,
+ min_delay_microseconds_.value());
+ }
+
+ if (remaining_bytes_.has_value()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::REMAINING_BYTES,
+ remaining_bytes_.value());
+ }
+
+ if (status_.has_value()) {
+ size += protobuf::SizeOfVarintField(ProtoChunk::Fields::STATUS,
+ status_.value().code());
+ }
+
+ return size;
+}
} // namespace pw::transfer::internal
diff --git a/pw_transfer/client_test.cc b/pw_transfer/client_test.cc
index 8ea1a43..ab57e8a 100644
--- a/pw_transfer/client_test.cc
+++ b/pw_transfer/client_test.cc
@@ -90,7 +90,7 @@
EXPECT_EQ(c0.session_id(), 3u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
context_.server().SendServerStream<Transfer::Read>(
EncodeChunk(Chunk(ProtocolVersion::kLegacy, Chunk::Type::kTransferData)
@@ -133,7 +133,7 @@
EXPECT_EQ(c0.session_id(), 4u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
constexpr ConstByteSpan data(kData32);
context_.server().SendServerStream<Transfer::Read>(
@@ -222,7 +222,7 @@
EXPECT_EQ(c0.session_id(), 5u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 32u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
}
TEST_F(ReadTransferMaxBytes32, SetsPendingBytesFromWriterLimit) {
@@ -239,7 +239,7 @@
EXPECT_EQ(c0.session_id(), 5u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 16u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
}
TEST_F(ReadTransferMaxBytes32, MultiParameters) {
@@ -639,7 +639,7 @@
EXPECT_EQ(c0.session_id(), 12u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Wait for the timeout to expire without doing anything. The client should
// resend its initial parameters chunk.
@@ -650,7 +650,7 @@
EXPECT_EQ(c.session_id(), 12u);
EXPECT_EQ(c.offset(), 0u);
EXPECT_EQ(c.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Transfer has not yet completed.
EXPECT_EQ(transfer_status, Status::Unknown());
@@ -696,7 +696,7 @@
EXPECT_EQ(c0.session_id(), 13u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
constexpr ConstByteSpan data(kData32);
@@ -719,7 +719,7 @@
EXPECT_EQ(c.session_id(), 13u);
EXPECT_EQ(c.offset(), 16u);
EXPECT_EQ(c.window_end_offset(), 64u);
- EXPECT_EQ(c.legacy_type(), Chunk::Type::kParametersRetransmit);
+ EXPECT_EQ(c.type(), Chunk::Type::kParametersRetransmit);
// Transfer has not yet completed.
EXPECT_EQ(transfer_status, Status::Unknown());
@@ -765,7 +765,7 @@
EXPECT_EQ(c0.session_id(), 14u);
EXPECT_EQ(c0.offset(), 0u);
EXPECT_EQ(c0.window_end_offset(), 64u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
for (unsigned retry = 1; retry <= kTestRetries; ++retry) {
// Wait for the timeout to expire without doing anything. The client should
@@ -789,7 +789,7 @@
Chunk c4 = DecodeChunk(payloads.back());
EXPECT_EQ(c4.session_id(), 14u);
- EXPECT_EQ(c4.legacy_type(), Chunk::Type::kTransferCompletion);
+ EXPECT_EQ(c4.type(), Chunk::Type::kTransferCompletion);
ASSERT_TRUE(c4.status().has_value());
EXPECT_EQ(c4.status().value(), Status::DeadlineExceeded());
@@ -938,7 +938,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 3u);
EXPECT_EQ(c0.resource_id(), 3u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send transfer parameters. Client should send a data chunk and the final
// chunk.
@@ -995,7 +995,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 4u);
EXPECT_EQ(c0.resource_id(), 4u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send transfer parameters with a chunk size smaller than the data.
@@ -1062,7 +1062,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 5u);
EXPECT_EQ(c0.resource_id(), 5u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send transfer parameters with a nonzero offset, requesting a seek.
// Client should send a data chunk and the final chunk.
@@ -1142,7 +1142,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 6u);
EXPECT_EQ(c0.resource_id(), 6u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send transfer parameters with a nonzero offset, requesting a seek.
context_.server().SendServerStream<Transfer::Write>(EncodeChunk(
@@ -1158,7 +1158,7 @@
Chunk c1 = DecodeChunk(payloads[1]);
EXPECT_EQ(c1.session_id(), 6u);
- EXPECT_EQ(c1.legacy_type(), Chunk::Type::kTransferCompletion);
+ EXPECT_EQ(c1.type(), Chunk::Type::kTransferCompletion);
ASSERT_TRUE(c1.status().has_value());
EXPECT_EQ(c1.status().value(), Status::Unimplemented());
@@ -1184,7 +1184,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 7u);
EXPECT_EQ(c0.resource_id(), 7u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send an error from the server.
context_.server().SendServerStream<Transfer::Write>(EncodeChunk(
@@ -1215,7 +1215,7 @@
Chunk c0 = DecodeChunk(payloads[0]);
EXPECT_EQ(c0.session_id(), 9u);
EXPECT_EQ(c0.resource_id(), 9u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send an invalid transfer parameters chunk with 0 pending bytes.
context_.server().SendServerStream<Transfer::Write>(EncodeChunk(
@@ -1258,7 +1258,7 @@
Chunk c0 = DecodeChunk(payloads.back());
EXPECT_EQ(c0.session_id(), 10u);
EXPECT_EQ(c0.resource_id(), 10u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Wait for the timeout to expire without doing anything. The client should
// resend the initial transmit chunk.
@@ -1268,7 +1268,7 @@
Chunk c = DecodeChunk(payloads.back());
EXPECT_EQ(c.session_id(), 10u);
EXPECT_EQ(c.resource_id(), 10u);
- EXPECT_EQ(c.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c.type(), Chunk::Type::kTransferStart);
// Transfer has not yet completed.
EXPECT_EQ(transfer_status, Status::Unknown());
@@ -1299,7 +1299,7 @@
Chunk c0 = DecodeChunk(payloads.back());
EXPECT_EQ(c0.session_id(), 11u);
EXPECT_EQ(c0.resource_id(), 11u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send the first parameters chunk.
rpc::test::WaitForPackets(context_.output(), 2, [this] {
@@ -1372,7 +1372,7 @@
Chunk c0 = DecodeChunk(payloads.back());
EXPECT_EQ(c0.session_id(), 12u);
EXPECT_EQ(c0.resource_id(), 12u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send the first parameters chunk, requesting all the data. The client should
// respond with one data chunk and a remaining_bytes = 0 chunk.
@@ -1456,7 +1456,7 @@
Chunk c0 = DecodeChunk(payloads.back());
EXPECT_EQ(c0.session_id(), 13u);
EXPECT_EQ(c0.resource_id(), 13u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
for (unsigned retry = 1; retry <= kTestRetries; ++retry) {
// Wait for the timeout to expire without doing anything. The client should
@@ -1467,7 +1467,7 @@
Chunk c = DecodeChunk(payloads.back());
EXPECT_EQ(c.session_id(), 13u);
EXPECT_EQ(c.resource_id(), 13u);
- EXPECT_EQ(c.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c.type(), Chunk::Type::kTransferStart);
// Transfer has not yet completed.
EXPECT_EQ(transfer_status, Status::Unknown());
@@ -1516,7 +1516,7 @@
Chunk c0 = DecodeChunk(payloads.back());
EXPECT_EQ(c0.session_id(), 14u);
EXPECT_EQ(c0.resource_id(), 14u);
- EXPECT_EQ(c0.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(c0.type(), Chunk::Type::kTransferStart);
// Send the first parameters chunk.
rpc::test::WaitForPackets(context_.output(), 2, [this] {
@@ -1583,7 +1583,7 @@
Chunk chunk = DecodeChunk(payloads.back());
EXPECT_EQ(chunk.session_id(), 15u);
EXPECT_EQ(chunk.resource_id(), 15u);
- EXPECT_EQ(chunk.legacy_type(), Chunk::Type::kTransferStart);
+ EXPECT_EQ(chunk.type(), Chunk::Type::kTransferStart);
client_.CancelTransfer(15);
transfer_thread_.WaitUntilEventIsProcessed();
@@ -1592,7 +1592,7 @@
ASSERT_EQ(payloads.size(), 2u);
chunk = DecodeChunk(payloads.back());
EXPECT_EQ(chunk.session_id(), 15u);
- ASSERT_EQ(chunk.legacy_type(), Chunk::Type::kTransferCompletion);
+ ASSERT_EQ(chunk.type(), Chunk::Type::kTransferCompletion);
EXPECT_EQ(chunk.status().value(), Status::Cancelled());
EXPECT_EQ(transfer_status, Status::Cancelled());
diff --git a/pw_transfer/context.cc b/pw_transfer/context.cc
index be49f88..dae00cc 100644
--- a/pw_transfer/context.cc
+++ b/pw_transfer/context.cc
@@ -363,23 +363,16 @@
}
void Context::TransmitNextChunk(bool retransmit_requested) {
- ByteSpan buffer = thread_->encode_buffer();
-
- // Begin by doing a partial encode of all the metadata fields, leaving the
- // buffer with usable space for the chunk data at the end.
- transfer::Chunk::MemoryEncoder encoder{buffer};
- encoder.WriteSessionId(session_id_).IgnoreError();
- encoder.WriteOffset(offset_).IgnoreError();
-
- // TODO(frolv): Type field presence is currently meaningful, so this type must
- // be serialized. Once all users of transfer always set chunk types, the field
- // can be made non-optional and this write can be removed as TRANSFER_DATA has
- // the default proto value of 0.
- encoder.WriteType(transfer::Chunk::Type::TRANSFER_DATA).IgnoreError();
+ Chunk chunk(ProtocolVersion::kLegacy, Chunk::Type::kTransferData);
+ chunk.set_session_id(session_id_);
+ chunk.set_offset(offset_);
// Reserve space for the data proto field overhead and use the remainder of
// the buffer for the chunk data.
- size_t reserved_size = encoder.size() + 1 /* data key */ + 5 /* data size */;
+ size_t reserved_size =
+ chunk.EncodedSize() + 1 /* data key */ + 5 /* data size */;
+
+ ByteSpan buffer = thread_->encode_buffer();
ByteSpan data_buffer = buffer.subspan(reserved_size);
size_t max_bytes_to_send =
@@ -392,7 +385,7 @@
Result<ByteSpan> data = reader().Read(data_buffer);
if (data.status().IsOutOfRange()) {
// No more data to read.
- encoder.WriteRemainingBytes(0).IgnoreError();
+ chunk.set_remaining_bytes(0);
window_end_offset_ = offset_;
PW_LOG_DEBUG("Transfer %u sending final chunk with remaining_bytes=0",
@@ -420,7 +413,7 @@
static_cast<unsigned>(offset_),
static_cast<unsigned>(data.value().size()));
- encoder.WriteData(data.value()).IgnoreError();
+ chunk.set_payload(data.value());
last_chunk_offset_ = offset_;
offset_ += data.value().size();
} else {
@@ -431,14 +424,15 @@
return;
}
- if (!encoder.status().ok()) {
+ Result<ConstByteSpan> encoded_chunk = chunk.Encode(buffer);
+ if (!encoded_chunk.ok()) {
PW_LOG_ERROR("Transfer %u failed to encode transmit chunk",
static_cast<unsigned>(session_id_));
Finish(Status::Internal());
return;
}
- if (const Status status = rpc_writer_->Write(encoder); !status.ok()) {
+ if (const Status status = rpc_writer_->Write(*encoded_chunk); !status.ok()) {
PW_LOG_ERROR("Transfer %u failed to send transmit chunk, status %u",
static_cast<unsigned>(session_id_),
status.code());
diff --git a/pw_transfer/java/main/dev/pigweed/pw_transfer/Transfer.java b/pw_transfer/java/main/dev/pigweed/pw_transfer/Transfer.java
index 40b9a1e..7f1b702 100644
--- a/pw_transfer/java/main/dev/pigweed/pw_transfer/Transfer.java
+++ b/pw_transfer/java/main/dev/pigweed/pw_transfer/Transfer.java
@@ -250,7 +250,7 @@
final Chunk.Builder newChunk(Chunk.Type type) {
// TODO(frolv): Properly set the session ID after it is configured by the server.
- return Chunk.newBuilder().setSessionId(getId()).setType(type);
+ return Chunk.newBuilder().setTransferId(getId()).setType(type);
}
/** Sends a chunk. Returns true if sent, false if sending failed and the transfer was aborted. */
diff --git a/pw_transfer/java/main/dev/pigweed/pw_transfer/TransferClient.java b/pw_transfer/java/main/dev/pigweed/pw_transfer/TransferClient.java
index 5683e24..4321e56 100644
--- a/pw_transfer/java/main/dev/pigweed/pw_transfer/TransferClient.java
+++ b/pw_transfer/java/main/dev/pigweed/pw_transfer/TransferClient.java
@@ -205,7 +205,7 @@
private static String chunkToString(Chunk chunk) {
StringBuilder str = new StringBuilder();
- str.append("sessionId:").append(chunk.getSessionId()).append(" ");
+ str.append("sessionId:").append(chunk.getTransferId()).append(" ");
str.append("windowEndOffset:").append(chunk.getWindowEndOffset()).append(" ");
str.append("offset:").append(chunk.getOffset()).append(" ");
// Don't include the actual data; it's too much.
@@ -243,13 +243,13 @@
@Override
public final void onNext(Chunk chunk) {
- Transfer<?> transfer = transfers.get(chunk.getSessionId());
+ Transfer<?> transfer = transfers.get(chunk.getTransferId());
if (transfer != null) {
logger.atFinest().log("Received chunk: %s", chunkToString(chunk));
workDispatcher.accept(() -> transfer.handleChunk(chunk));
} else {
logger.atWarning().log(
- "Ignoring unrecognized transfer session ID %d", chunk.getSessionId());
+ "Ignoring unrecognized transfer session ID %d", chunk.getTransferId());
}
}
diff --git a/pw_transfer/java/test/dev/pigweed/pw_transfer/TransferClientTest.java b/pw_transfer/java/test/dev/pigweed/pw_transfer/TransferClientTest.java
index 97a1a1b..a54d218 100644
--- a/pw_transfer/java/test/dev/pigweed/pw_transfer/TransferClientTest.java
+++ b/pw_transfer/java/test/dev/pigweed/pw_transfer/TransferClientTest.java
@@ -881,7 +881,7 @@
}
private static Chunk.Builder newChunk(Chunk.Type type, int resourceId) {
- return Chunk.newBuilder().setType(type).setSessionId(resourceId);
+ return Chunk.newBuilder().setType(type).setTransferId(resourceId);
}
private static Chunk initialWriteChunk(int sessionId, int resourceId, int size) {
diff --git a/pw_transfer/public/pw_transfer/internal/chunk.h b/pw_transfer/public/pw_transfer/internal/chunk.h
index 6c10898..72ce600 100644
--- a/pw_transfer/public/pw_transfer/internal/chunk.h
+++ b/pw_transfer/public/pw_transfer/internal/chunk.h
@@ -23,7 +23,7 @@
class Chunk {
public:
- enum Type {
+ enum class Type {
kTransferData = 0,
kTransferStart = 1,
kParametersRetransmit = 2,
@@ -52,8 +52,14 @@
.set_status(status);
}
+ // Encodes the chunk to the specified buffer, returning a span of the
+ // serialized data on success.
Result<ConstByteSpan> Encode(ByteSpan buffer) const;
+ // Returns the size of the serialized chunk based on the fields currently set
+ // within the chunk object.
+ size_t EncodedSize() const;
+
constexpr Chunk& set_session_id(uint32_t session_id) {
session_id_ = session_id;
return *this;
@@ -104,8 +110,14 @@
constexpr uint32_t session_id() const { return session_id_; }
- constexpr uint32_t resource_id() const {
- return resource_id_.has_value() ? resource_id_.value() : session_id_;
+ constexpr std::optional<uint32_t> resource_id() const {
+ if (is_legacy()) {
+ // In the legacy protocol, resource_id and session_id are the same (i.e.
+ // transfer_id).
+ return session_id_;
+ }
+
+ return resource_id_;
}
constexpr uint32_t window_end_offset() const { return window_end_offset_; }
@@ -129,11 +141,25 @@
return protocol_version_ == ProtocolVersion::kLegacy;
}
- // Legacy protocol chunks may not have a type, but newer versions always will.
- constexpr std::optional<Type> legacy_type() const { return type_; }
constexpr Type type() const {
- PW_ASSERT(!is_legacy());
- return type_.value();
+ // Legacy protocol chunks may not have a type, but newer versions always
+ // will. Try to deduce the type of a legacy chunk without one set.
+ if (!is_legacy() || type_.has_value()) {
+ return type_.value();
+ }
+
+ // The type-less legacy transfer protocol doesn't support handshakes or
+ // continuation parameters. Therefore, there are only three possible chunk
+ // types: start, data, and retransmit.
+ if (IsInitialChunk()) {
+ return Type::kTransferStart;
+ }
+
+ if (has_payload()) {
+ return Type::kTransferData;
+ }
+
+ return Type::kParametersRetransmit;
}
// Returns true if this parameters chunk is requesting that the transmitter
@@ -143,13 +169,13 @@
return true;
}
- return type_.value() == Chunk::Type::kParametersRetransmit ||
- type_.value() == Chunk::Type::kTransferStart;
+ return type_.value() == Type::kParametersRetransmit ||
+ type_.value() == Type::kTransferStart;
}
constexpr bool IsInitialChunk() const {
if (protocol_version_ >= ProtocolVersion::kVersionTwo) {
- return type_ == kTransferStart;
+ return type_ == Type::kTransferStart;
}
// In legacy versions of the transfer protocol, the chunk type is not always
@@ -179,6 +205,18 @@
constexpr Chunk() : Chunk(ProtocolVersion::kUnknown, std::nullopt) {}
+ // Returns true if this chunk should write legacy protocol fields to the
+ // serialized message.
+ //
+ // The first chunk of a transfer (type TRANSFER_START) is a special case: as
+ // we do not yet know what version of the protocol the other end is speaking,
+ // every legacy field must be encoded alongside newer ones to ensure that the
+ // chunk is processable. Following a response, the common protocol version
+ // will be determined and fields omitted as necessary.
+ constexpr bool ShouldEncodeLegacyFields() const {
+ return is_legacy() || type_ == Chunk::Type::kTransferStart;
+ }
+
uint32_t session_id_;
std::optional<uint32_t> resource_id_;
uint32_t window_end_offset_;
diff --git a/pw_transfer/py/pw_transfer/client.py b/pw_transfer/py/pw_transfer/client.py
index 0c50d9b..27c5459 100644
--- a/pw_transfer/py/pw_transfer/client.py
+++ b/pw_transfer/py/pw_transfer/client.py
@@ -230,11 +230,11 @@
"""
try:
- transfer = transfers[chunk.session_id]
+ transfer = transfers[chunk.transfer_id]
except KeyError:
_LOG.error(
'TransferManager received chunk for unknown transfer %d',
- chunk.session_id)
+ chunk.transfer_id)
# TODO(frolv): What should be done here, if anything?
return
diff --git a/pw_transfer/py/pw_transfer/transfer.py b/pw_transfer/py/pw_transfer/transfer.py
index 53c2c39..0004522 100644
--- a/pw_transfer/py/pw_transfer/transfer.py
+++ b/pw_transfer/py/pw_transfer/transfer.py
@@ -202,7 +202,7 @@
"""Sends an error chunk to the server and finishes the transfer."""
self._send_chunk(
transfer_pb2.Chunk(
- session_id=self.id,
+ transfer_id=self.id,
status=error.value,
type=transfer_pb2.Chunk.Type.TRANSFER_COMPLETION))
self.finish(error)
@@ -246,7 +246,7 @@
def _initial_chunk(self) -> transfer_pb2.Chunk:
# TODO(frolv): session_id should not be set here, but assigned by the
# server during an initial handshake.
- return transfer_pb2.Chunk(session_id=self.id,
+ return transfer_pb2.Chunk(transfer_id=self.id,
resource_id=self.id,
type=transfer_pb2.Chunk.Type.TRANSFER_START)
@@ -353,7 +353,7 @@
def _next_chunk(self) -> transfer_pb2.Chunk:
"""Returns the next Chunk message to send in the data transfer."""
- chunk = transfer_pb2.Chunk(session_id=self.id,
+ chunk = transfer_pb2.Chunk(transfer_id=self.id,
offset=self._offset,
type=transfer_pb2.Chunk.Type.TRANSFER_DATA)
max_bytes_in_chunk = min(self._max_chunk_size,
@@ -444,7 +444,7 @@
# No more data to read. Acknowledge receipt and finish.
self._send_chunk(
transfer_pb2.Chunk(
- session_id=self.id,
+ transfer_id=self.id,
status=Status.OK.value,
type=transfer_pb2.Chunk.Type.TRANSFER_COMPLETION))
self.finish(Status.OK)
@@ -510,7 +510,7 @@
self._pending_bytes = self._max_bytes_to_receive
self._window_end_offset = self._offset + self._max_bytes_to_receive
- chunk = transfer_pb2.Chunk(session_id=self.id,
+ chunk = transfer_pb2.Chunk(transfer_id=self.id,
pending_bytes=self._pending_bytes,
window_end_offset=self._window_end_offset,
max_chunk_size_bytes=self._max_chunk_size,
diff --git a/pw_transfer/py/tests/transfer_test.py b/pw_transfer/py/tests/transfer_test.py
index 5d29afb..4c6ea5a 100644
--- a/pw_transfer/py/tests/transfer_test.py
+++ b/pw_transfer/py/tests/transfer_test.py
@@ -105,7 +105,7 @@
self._enqueue_server_responses(
_Method.READ,
((transfer_pb2.Chunk(
- session_id=3, offset=0, data=b'abc', remaining_bytes=0), ), ),
+ transfer_id=3, offset=0, data=b'abc', remaining_bytes=0), ), ),
)
data = manager.read(3)
@@ -122,9 +122,9 @@
_Method.READ,
((
transfer_pb2.Chunk(
- session_id=3, offset=0, data=b'abc', remaining_bytes=3),
+ transfer_id=3, offset=0, data=b'abc', remaining_bytes=3),
transfer_pb2.Chunk(
- session_id=3, offset=3, data=b'def', remaining_bytes=0),
+ transfer_id=3, offset=3, data=b'def', remaining_bytes=0),
), ),
)
@@ -142,9 +142,9 @@
_Method.READ,
((
transfer_pb2.Chunk(
- session_id=3, offset=0, data=b'abc', remaining_bytes=3),
+ transfer_id=3, offset=0, data=b'abc', remaining_bytes=3),
transfer_pb2.Chunk(
- session_id=3, offset=3, data=b'def', remaining_bytes=0),
+ transfer_id=3, offset=3, data=b'def', remaining_bytes=0),
), ),
)
@@ -169,22 +169,26 @@
_Method.READ,
(
(
- transfer_pb2.Chunk(
- session_id=3, offset=0, data=b'123',
- remaining_bytes=6),
+ transfer_pb2.Chunk(transfer_id=3,
+ offset=0,
+ data=b'123',
+ remaining_bytes=6),
# Incorrect offset; expecting 3.
- transfer_pb2.Chunk(
- session_id=3, offset=1, data=b'456',
- remaining_bytes=3),
+ transfer_pb2.Chunk(transfer_id=3,
+ offset=1,
+ data=b'456',
+ remaining_bytes=3),
),
(
- transfer_pb2.Chunk(
- session_id=3, offset=3, data=b'456',
- remaining_bytes=3),
- transfer_pb2.Chunk(
- session_id=3, offset=6, data=b'789',
- remaining_bytes=0),
+ transfer_pb2.Chunk(transfer_id=3,
+ offset=3,
+ data=b'456',
+ remaining_bytes=3),
+ transfer_pb2.Chunk(transfer_id=3,
+ offset=6,
+ data=b'789',
+ remaining_bytes=0),
),
))
@@ -206,7 +210,8 @@
(
(), # Send nothing in response to the initial parameters.
(transfer_pb2.Chunk(
- session_id=3, offset=0, data=b'xyz', remaining_bytes=0), ),
+ transfer_id=3, offset=0, data=b'xyz',
+ remaining_bytes=0), ),
))
data = manager.read(3)
@@ -238,7 +243,7 @@
self._enqueue_server_responses(
_Method.READ,
- ((transfer_pb2.Chunk(session_id=31,
+ ((transfer_pb2.Chunk(transfer_id=31,
status=Status.NOT_FOUND.value), ), ),
)
@@ -269,11 +274,11 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=32,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -288,12 +293,12 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=32,
max_chunk_size_bytes=8), ),
(),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -310,15 +315,15 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=8,
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -335,15 +340,15 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=8,
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -368,27 +373,27 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=8,
pending_bytes=8,
max_chunk_size_bytes=8), ),
(
transfer_pb2.Chunk(
- session_id=4,
+ transfer_id=4,
offset=4, # rewind
pending_bytes=8,
max_chunk_size_bytes=8), ),
(
transfer_pb2.Chunk(
- session_id=4,
+ transfer_id=4,
offset=12,
pending_bytes=16, # update max size
max_chunk_size_bytes=16), ),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -406,17 +411,17 @@
self._enqueue_server_responses(
_Method.WRITE,
(
- (transfer_pb2.Chunk(session_id=4,
+ (transfer_pb2.Chunk(transfer_id=4,
offset=0,
pending_bytes=8,
max_chunk_size_bytes=8), ),
(
transfer_pb2.Chunk(
- session_id=4,
+ transfer_id=4,
offset=100, # larger offset than data
pending_bytes=8,
max_chunk_size_bytes=8), ),
- (transfer_pb2.Chunk(session_id=4, status=Status.OK.value), ),
+ (transfer_pb2.Chunk(transfer_id=4, status=Status.OK.value), ),
),
)
@@ -433,7 +438,7 @@
self._enqueue_server_responses(
_Method.WRITE,
- ((transfer_pb2.Chunk(session_id=21,
+ ((transfer_pb2.Chunk(transfer_id=21,
status=Status.UNAVAILABLE.value), ), ),
)
@@ -468,16 +473,16 @@
self.assertEqual(
self._sent_chunks,
[
- transfer_pb2.Chunk(session_id=22,
+ transfer_pb2.Chunk(transfer_id=22,
resource_id=22,
type=transfer_pb2.Chunk.Type.TRANSFER_START
), # initial chunk
transfer_pb2.Chunk(
- session_id=22,
+ transfer_id=22,
resource_id=22,
type=transfer_pb2.Chunk.Type.TRANSFER_START), # retry 1
transfer_pb2.Chunk(
- session_id=22,
+ transfer_id=22,
resource_id=22,
type=transfer_pb2.Chunk.Type.TRANSFER_START), # retry 2
])
@@ -495,14 +500,14 @@
self._enqueue_server_responses(_Method.WRITE, [[
transfer_pb2.Chunk(
- session_id=22, pending_bytes=10, max_chunk_size_bytes=5)
+ transfer_id=22, pending_bytes=10, max_chunk_size_bytes=5)
]])
with self.assertRaises(pw_transfer.Error) as context:
manager.write(22, b'0123456789')
last_data_chunk = transfer_pb2.Chunk(
- session_id=22,
+ transfer_id=22,
data=b'56789',
offset=5,
remaining_bytes=0,
@@ -512,10 +517,10 @@
self._sent_chunks,
[
transfer_pb2.Chunk(
- session_id=22,
+ transfer_id=22,
resource_id=22,
type=transfer_pb2.Chunk.Type.TRANSFER_START),
- transfer_pb2.Chunk(session_id=22,
+ transfer_pb2.Chunk(transfer_id=22,
data=b'01234',
type=transfer_pb2.Chunk.Type.TRANSFER_DATA),
last_data_chunk, # last chunk
@@ -533,7 +538,7 @@
self._enqueue_server_responses(
_Method.WRITE,
- ((transfer_pb2.Chunk(session_id=23, pending_bytes=0), ), ),
+ ((transfer_pb2.Chunk(transfer_id=23, pending_bytes=0), ), ),
)
with self.assertRaises(pw_transfer.Error) as context:
diff --git a/pw_transfer/transfer.proto b/pw_transfer/transfer.proto
index 8f88904..e4bb5a8 100644
--- a/pw_transfer/transfer.proto
+++ b/pw_transfer/transfer.proto
@@ -41,11 +41,13 @@
// stable depending on the implementation. Sent in every request to identify
// the transfer target.
//
+ // LEGACY FIELD ONLY. Split into resource_id and session_id in transfer v2.
+ //
// Read → ID of transfer
// Read ← ID of transfer
// Write → ID of transfer
// Write ← ID of transfer
- uint32 session_id = 1;
+ uint32 transfer_id = 1;
// Used by the receiver to indicate how many bytes it can accept. The
// transmitter sends this much data, divided into chunks no larger than
@@ -173,6 +175,23 @@
// Write ← Chunk type (start/parameters).
optional Type type = 10;
- // Not currently used. Will inherit session_id's behavior in the future.
- uint32 resource_id = 11;
+ // Unique identifier for the source or destination of transfer data. May be
+ // stable or ephemeral depending on the implementation. Only sent during the
+ // initial handshake phase of a version 2 or higher transfer.
+ //
+ // Read → ID of transferable resource
+ // Read ← ID of transferable resource
+ // Write → ID of transferable resource
+ // Write ← ID of transferable resource
+ optional uint32 resource_id = 11;
+
+ // Unique identifier for a specific transfer session. Assigned by a transfer
+ // service during the initial handshake phase, and persists for the remainder
+ // of that transfer operation.
+ //
+ // Read → ID of transfer session
+ // Read ← ID of transfer session
+ // Write → ID of transfer session
+ // Write ← ID of transfer session
+ optional uint32 session_id = 12;
}
diff --git a/pw_transfer/transfer_test.cc b/pw_transfer/transfer_test.cc
index 1591fac..868dc6c 100644
--- a/pw_transfer/transfer_test.cc
+++ b/pw_transfer/transfer_test.cc
@@ -1012,7 +1012,7 @@
chunk = DecodeChunk(ctx_.responses().back());
EXPECT_EQ(chunk.session_id(), 7u);
EXPECT_EQ(chunk.window_end_offset(), 32u);
- EXPECT_EQ(chunk.legacy_type(), Chunk::Type::kParametersContinue);
+ EXPECT_EQ(chunk.type(), Chunk::Type::kParametersContinue);
ctx_.SendClientStream<64>(
EncodeChunk(Chunk(ProtocolVersion::kLegacy, Chunk::Type::kTransferData)
@@ -1068,7 +1068,7 @@
EXPECT_EQ(chunk.session_id(), 7u);
EXPECT_EQ(chunk.offset(), 12u);
EXPECT_EQ(chunk.window_end_offset(), 32u);
- EXPECT_EQ(chunk.legacy_type(), Chunk::Type::kParametersRetransmit);
+ EXPECT_EQ(chunk.type(), Chunk::Type::kParametersRetransmit);
}
TEST_F(WriteTransfer, TransmitterExtendsWindow_TerminatesWithInvalid) {
diff --git a/pw_transfer/ts/client.ts b/pw_transfer/ts/client.ts
index fd3ca50..2deb453 100644
--- a/pw_transfer/ts/client.ts
+++ b/pw_transfer/ts/client.ts
@@ -86,7 +86,9 @@
progressCallback?: ProgressCallback
): Promise<Uint8Array> {
if (resourceId in this.readTransfers) {
- throw new Error(`Read transfer for resource ${resourceId} already exists`);
+ throw new Error(
+ `Read transfer for resource ${resourceId} already exists`
+ );
}
const transfer = new ReadTransfer(
resourceId,
@@ -250,10 +252,10 @@
* is invoked.
*/
private async handleChunk(transfers: TransferDict, chunk: Chunk) {
- const transfer = transfers[chunk.getSessionId()];
+ const transfer = transfers[chunk.getTransferId()];
if (transfer === undefined) {
console.error(
- `TransferManager received chunk for unknown transfer ${chunk.getSessionId()}`
+ `TransferManager received chunk for unknown transfer ${chunk.getTransferId()}`
);
return;
}
diff --git a/pw_transfer/ts/transfer.ts b/pw_transfer/ts/transfer.ts
index 55b6ccc..8264f0a 100644
--- a/pw_transfer/ts/transfer.ts
+++ b/pw_transfer/ts/transfer.ts
@@ -137,7 +137,7 @@
protected sendError(error: Status): void {
const chunk = new Chunk();
chunk.setStatus(error);
- chunk.setSessionId(this.id);
+ chunk.setTransferId(this.id);
chunk.setType(Chunk.Type.TRANSFER_COMPLETION);
this.sendChunk(chunk);
this.finish(error);
@@ -262,7 +262,7 @@
this.windowEndOffset = this.offset + this.maxBytesToReceive;
const chunk = new Chunk();
- chunk.setSessionId(this.id);
+ chunk.setTransferId(this.id);
chunk.setPendingBytes(this.pendingBytes);
chunk.setMaxChunkSizeBytes(this.maxChunkSize);
chunk.setOffset(this.offset);
@@ -303,7 +303,7 @@
if (chunk.getRemainingBytes() === 0) {
// No more data to read. Acknowledge receipt and finish.
const endChunk = new Chunk();
- endChunk.setSessionId(this.id);
+ endChunk.setTransferId(this.id);
endChunk.setStatus(Status.OK);
endChunk.setType(Chunk.Type.TRANSFER_COMPLETION);
this.sendChunk(endChunk);
@@ -405,7 +405,7 @@
// TODO(frolv): The session ID should not be set here but assigned by the
// server during an initial handshake.
const chunk = new Chunk();
- chunk.setSessionId(this.id);
+ chunk.setTransferId(this.id);
chunk.setResourceId(this.id);
chunk.setType(Chunk.Type.TRANSFER_START);
return chunk;
@@ -516,7 +516,7 @@
/** Returns the next Chunk message to send in the data transfer. */
private nextChunk(): Chunk {
const chunk = new Chunk();
- chunk.setSessionId(this.id);
+ chunk.setTransferId(this.id);
chunk.setOffset(this.offset);
chunk.setType(Chunk.Type.TRANSFER_DATA);
diff --git a/pw_transfer/ts/transfer_test.ts b/pw_transfer/ts/transfer_test.ts
index 16325bf..584df42 100644
--- a/pw_transfer/ts/transfer_test.ts
+++ b/pw_transfer/ts/transfer_test.ts
@@ -118,7 +118,7 @@
remainingBytes: number
): Chunk {
const chunk = new Chunk();
- chunk.setSessionId(sessionId);
+ chunk.setTransferId(sessionId);
chunk.setOffset(offset);
chunk.setData(textEncoder.encode(data));
chunk.setRemainingBytes(remainingBytes);
@@ -230,7 +230,7 @@
const chunk = new Chunk();
chunk.setStatus(Status.NOT_FOUND);
- chunk.setSessionId(31);
+ chunk.setTransferId(31);
enqueueServerResponses(service.method('Read')!, [[chunk]]);
await manager
@@ -263,13 +263,13 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(4);
+ chunk.setTransferId(4);
chunk.setOffset(0);
chunk.setPendingBytes(32);
chunk.setMaxChunkSizeBytes(8);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -286,13 +286,13 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(4);
+ chunk.setTransferId(4);
chunk.setOffset(0);
chunk.setPendingBytes(32);
chunk.setMaxChunkSizeBytes(8);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -311,19 +311,19 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(4);
+ chunk.setTransferId(4);
chunk.setOffset(0);
chunk.setPendingBytes(8);
chunk.setMaxChunkSizeBytes(8);
const chunk2 = new Chunk();
- chunk2.setSessionId(4);
+ chunk2.setTransferId(4);
chunk2.setOffset(8);
chunk2.setPendingBytes(8);
chunk2.setMaxChunkSizeBytes(8);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -343,7 +343,7 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(4);
+ chunk.setTransferId(4);
chunk.setOffset(0);
chunk.setPendingBytes(8);
chunk.setMaxChunkSizeBytes(4);
@@ -351,42 +351,42 @@
chunk.setWindowEndOffset(8);
const chunk2 = new Chunk();
- chunk2.setSessionId(4);
+ chunk2.setTransferId(4);
chunk2.setOffset(4);
chunk2.setPendingBytes(8);
chunk2.setType(Chunk.Type.PARAMETERS_CONTINUE);
chunk2.setWindowEndOffset(12);
const chunk3 = new Chunk();
- chunk3.setSessionId(4);
+ chunk3.setTransferId(4);
chunk3.setOffset(8);
chunk3.setPendingBytes(8);
chunk3.setType(Chunk.Type.PARAMETERS_CONTINUE);
chunk3.setWindowEndOffset(16);
const chunk4 = new Chunk();
- chunk4.setSessionId(4);
+ chunk4.setTransferId(4);
chunk4.setOffset(12);
chunk4.setPendingBytes(8);
chunk4.setType(Chunk.Type.PARAMETERS_CONTINUE);
chunk4.setWindowEndOffset(20);
const chunk5 = new Chunk();
- chunk5.setSessionId(4);
+ chunk5.setTransferId(4);
chunk5.setOffset(16);
chunk5.setPendingBytes(8);
chunk5.setType(Chunk.Type.PARAMETERS_CONTINUE);
chunk5.setWindowEndOffset(24);
const chunk6 = new Chunk();
- chunk6.setSessionId(4);
+ chunk6.setTransferId(4);
chunk6.setOffset(20);
chunk6.setPendingBytes(8);
chunk6.setType(Chunk.Type.PARAMETERS_CONTINUE);
chunk6.setWindowEndOffset(28);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -415,19 +415,19 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(4);
+ chunk.setTransferId(4);
chunk.setOffset(0);
chunk.setPendingBytes(8);
chunk.setMaxChunkSizeBytes(8);
const chunk2 = new Chunk();
- chunk2.setSessionId(4);
+ chunk2.setTransferId(4);
chunk2.setOffset(8);
chunk2.setPendingBytes(8);
chunk2.setMaxChunkSizeBytes(8);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -461,31 +461,31 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk1 = new Chunk();
- chunk1.setSessionId(4);
+ chunk1.setTransferId(4);
chunk1.setOffset(0);
chunk1.setPendingBytes(8);
chunk1.setMaxChunkSizeBytes(8);
const chunk2 = new Chunk();
- chunk2.setSessionId(4);
+ chunk2.setTransferId(4);
chunk2.setOffset(8);
chunk2.setPendingBytes(8);
chunk2.setMaxChunkSizeBytes(8);
const chunk3 = new Chunk();
- chunk3.setSessionId(4);
+ chunk3.setTransferId(4);
chunk3.setOffset(4); // Rewind
chunk3.setPendingBytes(8);
chunk3.setMaxChunkSizeBytes(8);
const chunk4 = new Chunk();
- chunk4.setSessionId(4);
+ chunk4.setTransferId(4);
chunk4.setOffset(12); // Rewind
chunk4.setPendingBytes(16);
chunk4.setMaxChunkSizeBytes(16);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -508,19 +508,19 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk1 = new Chunk();
- chunk1.setSessionId(4);
+ chunk1.setTransferId(4);
chunk1.setOffset(0);
chunk1.setPendingBytes(8);
chunk1.setMaxChunkSizeBytes(8);
const chunk2 = new Chunk();
- chunk2.setSessionId(4);
+ chunk2.setTransferId(4);
chunk2.setOffset(100); // larger offset than data
chunk2.setPendingBytes(8);
chunk2.setMaxChunkSizeBytes(8);
const completeChunk = new Chunk();
- completeChunk.setSessionId(4);
+ completeChunk.setTransferId(4);
completeChunk.setStatus(Status.OK);
enqueueServerResponses(service.method('Write')!, [
@@ -544,7 +544,7 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(21);
+ chunk.setTransferId(21);
chunk.setStatus(Status.UNAVAILABLE);
enqueueServerResponses(service.method('Write')!, [[chunk]]);
@@ -564,7 +564,7 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(21);
+ chunk.setTransferId(21);
chunk.setStatus(Status.NOT_FOUND);
enqueueServerError(service.method('Write')!, Status.NOT_FOUND);
@@ -599,7 +599,7 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S, 4, 2);
const chunk = new Chunk();
- chunk.setSessionId(22);
+ chunk.setTransferId(22);
chunk.setPendingBytes(10);
chunk.setMaxChunkSizeBytes(5);
@@ -612,15 +612,15 @@
})
.catch(error => {
const expectedChunk1 = new Chunk();
- expectedChunk1.setSessionId(22);
+ expectedChunk1.setTransferId(22);
expectedChunk1.setResourceId(22);
expectedChunk1.setType(Chunk.Type.TRANSFER_START);
const expectedChunk2 = new Chunk();
- expectedChunk2.setSessionId(22);
+ expectedChunk2.setTransferId(22);
expectedChunk2.setData(textEncoder.encode('01234'));
expectedChunk2.setType(Chunk.Type.TRANSFER_DATA);
const lastChunk = new Chunk();
- lastChunk.setSessionId(22);
+ lastChunk.setTransferId(22);
lastChunk.setData(textEncoder.encode('56789'));
lastChunk.setOffset(5);
lastChunk.setRemainingBytes(0);
@@ -645,7 +645,7 @@
const manager = new Manager(service, DEFAULT_TIMEOUT_S);
const chunk = new Chunk();
- chunk.setSessionId(23);
+ chunk.setTransferId(23);
chunk.setPendingBytes(0);
enqueueServerResponses(service.method('Write')!, [[chunk]]);