blob: 494cbaa683c59c3b39ae03a702cc4716ad783139 [file] [log] [blame]
// 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);
// 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