system_rpc_server.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. * All rights reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * This file is a fork from: third_party/pigweed/repo/targets/host/system_rpc_server.cc
  19. * But changes the disconnect behaviour from closing and returning, to awaiting a
  20. * reconnection.
  21. */
  22. #include <cstddef>
  23. #include <cstdint>
  24. #include <cstdio>
  25. #include "pw_assert/check.h"
  26. #include "pw_hdlc/rpc_channel.h"
  27. #include "pw_hdlc/rpc_packets.h"
  28. #include "pw_log/log.h"
  29. #include "pw_rpc_system_server/rpc_server.h"
  30. #include "pw_stream/socket_stream.h"
  31. namespace pw::rpc::system_server {
  32. namespace {
  33. constexpr size_t kMaxTransmissionUnit = 512;
  34. uint16_t socket_port = 33000;
  35. stream::ServerSocket server_socket;
  36. stream::SocketStream socket_stream;
  37. hdlc::RpcChannelOutput hdlc_channel_output(socket_stream, hdlc::kDefaultRpcAddress, "HDLC channel");
  38. Channel channels[] = { rpc::Channel::Create<1>(&hdlc_channel_output) };
  39. rpc::Server server(channels);
  40. } // namespace
  41. void set_socket_port(uint16_t new_socket_port)
  42. {
  43. socket_port = new_socket_port;
  44. }
  45. int GetServerSocketFd()
  46. {
  47. return socket_stream.connection_fd();
  48. }
  49. void Init()
  50. {
  51. log_basic::SetOutput([](std::string_view log) {
  52. std::fprintf(stderr, "%.*s\n", static_cast<int>(log.size()), log.data());
  53. hdlc::WriteUIFrame(1, as_bytes(span(log)), socket_stream).IgnoreError(); // TODO(pwbug/387): Handle Status properly
  54. });
  55. PW_LOG_INFO("Starting pw_rpc server on port %d", socket_port);
  56. PW_CHECK_OK(server_socket.Listen(socket_port));
  57. auto accept_result = server_socket.Accept();
  58. PW_CHECK_OK(accept_result.status());
  59. socket_stream = *std::move(accept_result);
  60. }
  61. rpc::Server & Server()
  62. {
  63. return server;
  64. }
  65. Status Start()
  66. {
  67. // Declare a buffer for decoding incoming HDLC frames.
  68. std::array<std::byte, kMaxTransmissionUnit> input_buffer;
  69. hdlc::Decoder decoder(input_buffer);
  70. while (true)
  71. {
  72. std::array<std::byte, kMaxTransmissionUnit> data;
  73. auto ret_val = socket_stream.Read(data);
  74. if (!ret_val.ok())
  75. {
  76. if (ret_val.status() == Status::OutOfRange())
  77. {
  78. // An out of range status indicates the remote end has disconnected.
  79. // Start to serve the connection again, which will allow another
  80. // remote to connect.
  81. socket_stream.Close();
  82. server_socket.Close();
  83. PW_CHECK_OK(server_socket.Listen(socket_port));
  84. auto accept_result = server_socket.Accept();
  85. PW_CHECK_OK(accept_result.status());
  86. socket_stream = *std::move(accept_result);
  87. }
  88. continue;
  89. }
  90. for (std::byte byte : ret_val.value())
  91. {
  92. auto result = decoder.Process(byte);
  93. if (!result.ok())
  94. {
  95. // Non-OK means there isn't a complete packet yet, or there was some
  96. // other issue. Wait for more bytes that form a complete packet.
  97. continue;
  98. }
  99. hdlc::Frame & frame = result.value();
  100. if (frame.address() != hdlc::kDefaultRpcAddress)
  101. {
  102. // Wrong address; ignore the packet for now. In the future, this branch
  103. // could expand to add packet routing or metrics.
  104. continue;
  105. }
  106. server.ProcessPacket(frame.data()).IgnoreError();
  107. }
  108. }
  109. }
  110. } // namespace pw::rpc::system_server