blob: 56ce68536468a652a49fc9b71b0132d34f400ad1 [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.
// Simple RPC server with the transfer service registered. Reads HDLC frames
// with RPC packets through a socket. The transfer service reads and writes to a
// fixed-size buffer. The buffer's contents can be set by writing
// null-terminated strings through stdin.
#include <cstddef>
#include <thread>
#include <variant>
#include "pw_assert/check.h"
#include "pw_log/log.h"
#include "pw_rpc_system_server/rpc_server.h"
#include "pw_rpc_system_server/socket.h"
#include "pw_stream/memory_stream.h"
#include "pw_transfer/transfer.h"
namespace pw::transfer {
namespace {
class BufferReaderWriter final : public ReadWriteHandler {
public:
BufferReaderWriter(uint32_t transfer_id, ByteSpan buffer)
: ReadWriteHandler(transfer_id), buffer_(buffer), size_bytes_(0) {}
Status PrepareRead() override {
set_reader(
stream_.emplace<stream::MemoryReader>(buffer_.first(size_bytes_)));
return OkStatus();
}
Status PrepareWrite() override {
set_writer(stream_.emplace<stream::MemoryWriter>(buffer_));
return OkStatus();
}
Status FinalizeWrite(Status) override {
size_bytes_ = std::get<stream::MemoryWriter>(stream_).bytes_written();
return OkStatus();
}
void set_size(size_t new_size) { size_bytes_ = new_size; }
private:
// TODO(hepler): Use a seekable MemoryReaderWriter when available.
std::variant<std::monostate, stream::MemoryReader, stream::MemoryWriter>
stream_;
ByteSpan buffer_;
size_t size_bytes_;
};
TransferService transfer_service;
std::byte buffer[512];
void RunServer() {
rpc::system_server::set_socket_port(33001);
BufferReaderWriter transfer(99, buffer);
// Read characters from stdin directly into the buffer. Stop at 0 or overflow.
std::thread([&transfer] {
int next_char;
size_t index = 0;
while ((next_char = std::getchar()) != EOF) {
if (next_char == '\0') {
transfer.set_size(index);
index = 0;
continue;
}
PW_CHECK_UINT_LT(index, sizeof(buffer), "Sent too many characters!");
buffer[index++] = static_cast<std::byte>(next_char);
}
}).detach();
transfer_service.RegisterHandler(transfer);
rpc::system_server::Init();
rpc::system_server::Server().RegisterService(transfer_service);
PW_LOG_INFO("Starting pw_rpc server");
rpc::system_server::Start()
.IgnoreError(); // TODO(pwbug/387): Handle Status properly
}
} // namespace
} // namespace pw::transfer
int main() {
pw::transfer::RunServer();
return 0;
}