• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 #pragma once
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <span>
19 
20 #include "pw_bytes/span.h"
21 #include "pw_rpc/internal/packet.pwpb.h"
22 #include "pw_status/status_with_size.h"
23 
24 namespace pw::rpc::internal {
25 
26 class Packet {
27  public:
28   static constexpr uint32_t kUnassignedId = 0;
29 
30   // Parses a packet from a protobuf message. Missing or malformed fields take
31   // their default values.
32   static Result<Packet> FromBuffer(ConstByteSpan data);
33 
34   // Creates an RPC packet with the channel, service, and method ID of the
35   // provided packet.
36   static constexpr Packet Response(const Packet& request,
37                                    Status status = OkStatus()) {
38     return Packet(PacketType::RESPONSE,
39                   request.channel_id(),
40                   request.service_id(),
41                   request.method_id(),
42                   {},
43                   status);
44   }
45 
46   // Creates a SERVER_ERROR packet with the channel, service, and method ID of
47   // the provided packet.
ServerError(const Packet & packet,Status status)48   static constexpr Packet ServerError(const Packet& packet, Status status) {
49     return Packet(PacketType::SERVER_ERROR,
50                   packet.channel_id(),
51                   packet.service_id(),
52                   packet.method_id(),
53                   {},
54                   status);
55   }
56 
57   // Creates a CLIENT_ERROR packet with the channel, service, and method ID of
58   // the provided packet.
ClientError(const Packet & packet,Status status)59   static constexpr Packet ClientError(const Packet& packet, Status status) {
60     return Packet(PacketType::CLIENT_ERROR,
61                   packet.channel_id(),
62                   packet.service_id(),
63                   packet.method_id(),
64                   {},
65                   status);
66   }
67 
68   // Creates an empty packet.
Packet()69   constexpr Packet()
70       : Packet(PacketType{}, kUnassignedId, kUnassignedId, kUnassignedId) {}
71 
72   constexpr Packet(PacketType type,
73                    uint32_t channel_id,
74                    uint32_t service_id,
75                    uint32_t method_id,
76                    ConstByteSpan payload = {},
77                    Status status = OkStatus())
type_(type)78       : type_(type),
79         channel_id_(channel_id),
80         service_id_(service_id),
81         method_id_(method_id),
82         payload_(payload),
83         status_(status) {}
84 
85   // Encodes the packet into its wire format. Returns the encoded size.
86   Result<ConstByteSpan> Encode(ByteSpan buffer) const;
87 
88   // Determines the space required to encode the packet proto fields for a
89   // response, excluding the payload. This may be used to split the buffer into
90   // reserved space and available space for the payload.
91   size_t MinEncodedSizeBytes() const;
92 
93   enum Destination : bool { kServer, kClient };
94 
destination()95   constexpr Destination destination() const {
96     return static_cast<int>(type_) % 2 == 0 ? kServer : kClient;
97   }
98 
type()99   constexpr PacketType type() const { return type_; }
channel_id()100   constexpr uint32_t channel_id() const { return channel_id_; }
service_id()101   constexpr uint32_t service_id() const { return service_id_; }
method_id()102   constexpr uint32_t method_id() const { return method_id_; }
payload()103   constexpr const ConstByteSpan& payload() const { return payload_; }
status()104   constexpr Status status() const { return status_; }
105 
set_type(PacketType type)106   constexpr void set_type(PacketType type) { type_ = type; }
set_channel_id(uint32_t channel_id)107   constexpr void set_channel_id(uint32_t channel_id) {
108     channel_id_ = channel_id;
109   }
set_service_id(uint32_t service_id)110   constexpr void set_service_id(uint32_t service_id) {
111     service_id_ = service_id;
112   }
set_method_id(uint32_t method_id)113   constexpr void set_method_id(uint32_t method_id) { method_id_ = method_id; }
set_payload(ConstByteSpan payload)114   constexpr void set_payload(ConstByteSpan payload) { payload_ = payload; }
set_status(Status status)115   constexpr void set_status(Status status) { status_ = status; }
116 
117  private:
118   PacketType type_;
119   uint32_t channel_id_;
120   uint32_t service_id_;
121   uint32_t method_id_;
122   ConstByteSpan payload_;
123   Status status_;
124 };
125 
126 }  // namespace pw::rpc::internal
127