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