mirror of
https://fuchsia.googlesource.com/third_party/pigweed.googlesource.com/pigweed/pigweed
synced 2024-09-20 13:51:05 +00:00
86e05def88
This expands the RPC protocol to include an optional call_id field, used to map server->client packets to the client call object that made them. This fixes an issue where a reinvoked call could receive a response intended for the original invocation, with potentially stale data. This feature is opt-in for RPC clients. Setting all call_ids to the same number (such as the proto3 default 0) results in the previous client behavior. Therefore, it is backwards compatible with all existing RPC clients. Change-Id: I6f1894afd491e6308dca5c31ae1704af920381c6 Requires: pigweed-internal:16840 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/66064 Commit-Queue: Alexei Frolov <frolv@google.com> Reviewed-by: Wyatt Hepler <hepler@google.com>
77 lines
2.9 KiB
C++
77 lines
2.9 KiB
C++
// Copyright 2021 The Pigweed Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
// use this file except in compliance with the License. You may obtain a copy of
|
|
// the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations under
|
|
// the License.
|
|
|
|
#include "pw_transfer/internal/context.h"
|
|
|
|
#include "pw_assert/check.h"
|
|
#include "pw_status/try.h"
|
|
#include "pw_varint/varint.h"
|
|
|
|
namespace pw::transfer::internal {
|
|
|
|
uint32_t Context::MaxWriteChunkSize(uint32_t max_chunk_size_bytes,
|
|
uint32_t channel_id) const {
|
|
// Start with the user-provided maximum chunk size, which should be the usable
|
|
// payload length on the RPC ingress path after any transport overhead.
|
|
ssize_t max_size = max_chunk_size_bytes;
|
|
|
|
// Subtract the RPC overhead (pw_rpc/internal/packet.proto).
|
|
//
|
|
// type: 1 byte key, 1 byte value (CLIENT_STREAM)
|
|
// channel_id: 1 byte key, varint value (calculate from stream)
|
|
// service_id: 1 byte key, 4 byte value
|
|
// method_id: 1 byte key, 4 byte value
|
|
// payload: 1 byte key, varint length (remaining space)
|
|
// status: 0 bytes (not set in stream packets)
|
|
//
|
|
// TOTAL: 14 bytes + encoded channel_id size + encoded payload length
|
|
//
|
|
max_size -= 14;
|
|
max_size -= varint::EncodedSize(channel_id);
|
|
max_size -= varint::EncodedSize(max_size);
|
|
|
|
// TODO(frolv): Temporarily add 5 bytes for the new call_id change. The RPC
|
|
// overhead calculation will be moved into an RPC helper to avoid having
|
|
// pw_transfer depend on RPC internals.
|
|
max_size -= 5;
|
|
|
|
// Subtract the transfer service overhead for a client write chunk
|
|
// (pw_transfer/transfer.proto).
|
|
//
|
|
// transfer_id: 1 byte key, varint value (calculate)
|
|
// offset: 1 byte key, varint value (calculate)
|
|
// data: 1 byte key, varint length (remaining space)
|
|
//
|
|
// TOTAL: 3 + encoded transfer_id + encoded offset + encoded data length
|
|
//
|
|
size_t max_offset_in_window = offset() + pending_bytes();
|
|
max_size -= 3;
|
|
max_size -= varint::EncodedSize(transfer_id());
|
|
max_size -= varint::EncodedSize(max_offset_in_window);
|
|
max_size -= varint::EncodedSize(max_size);
|
|
|
|
// A resulting value of zero (or less) renders write transfers unusable, as
|
|
// there is no space to send any payload. This should be considered a
|
|
// programmer error in the transfer service setup.
|
|
PW_CHECK_INT_GT(
|
|
max_size,
|
|
0,
|
|
"Transfer service maximum chunk size is too small to fit a payload. "
|
|
"Increase max_chunk_size_bytes to support write transfers.");
|
|
|
|
return max_size;
|
|
}
|
|
|
|
} // namespace pw::transfer::internal
|