blob: 5b01e518428d0a12d4bcddcd814e060bc361cb9d [file] [log] [blame]
Wyatt Hepler22530402021-07-30 23:40:40 -07001// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15// Simple RPC server with the transfer service registered. Reads HDLC frames
16// with RPC packets through a socket. The transfer service reads and writes to a
17// fixed-size buffer. The buffer's contents can be set by writing
18// null-terminated strings through stdin.
19
20#include <cstddef>
21#include <thread>
22#include <variant>
23
24#include "pw_assert/check.h"
25#include "pw_log/log.h"
26#include "pw_rpc_system_server/rpc_server.h"
27#include "pw_rpc_system_server/socket.h"
28#include "pw_stream/memory_stream.h"
29#include "pw_transfer/transfer.h"
30
31namespace pw::transfer {
32namespace {
33
34class BufferReaderWriter final : public ReadWriteHandler {
35 public:
36 BufferReaderWriter(uint32_t transfer_id, ByteSpan buffer)
37 : ReadWriteHandler(transfer_id), buffer_(buffer), size_bytes_(0) {}
38
39 Status PrepareRead() override {
40 set_reader(
41 stream_.emplace<stream::MemoryReader>(buffer_.first(size_bytes_)));
42 return OkStatus();
43 }
44
45 Status PrepareWrite() override {
46 set_writer(stream_.emplace<stream::MemoryWriter>(buffer_));
47 return OkStatus();
48 }
49
50 Status FinalizeWrite(Status) override {
51 size_bytes_ = std::get<stream::MemoryWriter>(stream_).bytes_written();
52 return OkStatus();
53 }
54
55 void set_size(size_t new_size) { size_bytes_ = new_size; }
56
57 private:
58 // TODO(hepler): Use a seekable MemoryReaderWriter when available.
59 std::variant<std::monostate, stream::MemoryReader, stream::MemoryWriter>
60 stream_;
61 ByteSpan buffer_;
62 size_t size_bytes_;
63};
64
Alexei Frolov563946f2021-08-05 18:58:48 -070065constexpr size_t kChunkSizeBytes = 256;
66constexpr size_t kMaxReceiveSizeBytes = 1024;
67
68TransferService transfer_service(kChunkSizeBytes, kMaxReceiveSizeBytes);
Wyatt Hepler22530402021-07-30 23:40:40 -070069
70std::byte buffer[512];
71
Wyatt Hepler82d499b2021-08-23 09:13:16 -070072void RunServer(int socket_port) {
73 rpc::system_server::set_socket_port(socket_port);
Wyatt Hepler22530402021-07-30 23:40:40 -070074
75 BufferReaderWriter transfer(99, buffer);
76
77 // Read characters from stdin directly into the buffer. Stop at 0 or overflow.
78 std::thread([&transfer] {
79 int next_char;
80 size_t index = 0;
81
82 while ((next_char = std::getchar()) != EOF) {
83 if (next_char == '\0') {
84 transfer.set_size(index);
85 index = 0;
86 continue;
87 }
88
89 PW_CHECK_UINT_LT(index, sizeof(buffer), "Sent too many characters!");
90 buffer[index++] = static_cast<std::byte>(next_char);
91 }
92 }).detach();
93
94 transfer_service.RegisterHandler(transfer);
95
96 rpc::system_server::Init();
97 rpc::system_server::Server().RegisterService(transfer_service);
98
99 PW_LOG_INFO("Starting pw_rpc server");
Wyatt Hepler82d499b2021-08-23 09:13:16 -0700100 PW_CHECK_OK(rpc::system_server::Start());
Wyatt Hepler22530402021-07-30 23:40:40 -0700101}
102
103} // namespace
104} // namespace pw::transfer
105
Wyatt Hepler82d499b2021-08-23 09:13:16 -0700106int main(int argc, char* argv[]) {
107 if (argc != 2) {
108 PW_LOG_ERROR("Usage: %s PORT", argv[0]);
109 return 1;
110 }
111 pw::transfer::RunServer(std::atoi(argv[1]));
Wyatt Hepler22530402021-07-30 23:40:40 -0700112 return 0;
113}